From 67e2d855bd3353659e25ca4ea9775d09646e1e6a Mon Sep 17 00:00:00 2001 From: coulsonwang Date: Wed, 6 May 2020 14:35:34 +0800 Subject: [PATCH] add glslang and spriv-cross (#86) --- android/CMakeLists.txt | 20 + android/arm64-v8a/glslang/libOGLCompiler.a | Bin 0 -> 25332 bytes android/arm64-v8a/glslang/libOSDependent.a | Bin 0 -> 18046 bytes android/arm64-v8a/glslang/libSPIRV.a | Bin 0 -> 560250 bytes android/arm64-v8a/glslang/libglslang.a | Bin 0 -> 1986142 bytes .../include/glslang/SPIRV/GLSL.ext.AMD.h | 108 + .../include/glslang/SPIRV/GLSL.ext.EXT.h | 39 + .../include/glslang/SPIRV/GLSL.ext.KHR.h | 51 + .../include/glslang/SPIRV/GLSL.ext.NV.h | 81 + .../include/glslang/SPIRV/GLSL.std.450.h | 131 + .../include/glslang/SPIRV/GlslangToSpv.h | 61 + .../arm64-v8a/include/glslang/SPIRV/Logger.h | 83 + .../glslang/SPIRV/NonSemanticDebugPrintf.h | 50 + .../include/glslang/SPIRV/SPVRemapper.h | 304 ++ .../include/glslang/SPIRV/SpvBuilder.h | 838 ++++++ .../include/glslang/SPIRV/SpvTools.h | 82 + .../include/glslang/SPIRV/bitutils.h | 81 + .../include/glslang/SPIRV/disassemble.h | 53 + android/arm64-v8a/include/glslang/SPIRV/doc.h | 258 ++ .../include/glslang/SPIRV/hex_float.h | 1078 +++++++ .../arm64-v8a/include/glslang/SPIRV/spirv.hpp | 2114 ++++++++++++++ .../arm64-v8a/include/glslang/SPIRV/spvIR.h | 485 ++++ .../glslang/glslang/Include/BaseTypes.h | 565 ++++ .../include/glslang/glslang/Include/Common.h | 292 ++ .../glslang/glslang/Include/ConstantUnion.h | 974 +++++++ .../glslang/glslang/Include/InfoSink.h | 144 + .../glslang/Include/InitializeGlobals.h | 44 + .../glslang/glslang/Include/PoolAlloc.h | 316 +++ .../glslang/glslang/Include/ResourceLimits.h | 149 + .../glslang/glslang/Include/ShHandle.h | 176 ++ .../include/glslang/glslang/Include/Types.h | 2483 +++++++++++++++++ .../include/glslang/glslang/Include/arrays.h | 341 +++ .../glslang/Include/glslang_c_interface.h | 232 ++ .../glslang/Include/glslang_c_shader_types.h | 182 ++ .../glslang/glslang/Include/intermediate.h | 1805 ++++++++++++ .../glslang/glslang/Include/revision.h | 3 + .../glslang/MachineIndependent/Initialize.h | 112 + .../MachineIndependent/LiveTraverser.h | 138 + .../glslang/MachineIndependent/ParseHelper.h | 525 ++++ .../glslang/MachineIndependent/RemoveTree.h | 41 + .../glslang/glslang/MachineIndependent/Scan.h | 276 ++ .../glslang/MachineIndependent/ScanContext.h | 93 + .../glslang/MachineIndependent/SymbolTable.h | 885 ++++++ .../glslang/MachineIndependent/Versions.h | 327 +++ .../glslang/MachineIndependent/attribute.h | 149 + .../glslang/MachineIndependent/gl_types.h | 210 ++ .../MachineIndependent/glslang_tab.cpp.h | 521 ++++ .../glslang/MachineIndependent/iomapper.h | 300 ++ .../MachineIndependent/localintermediate.h | 1013 +++++++ .../MachineIndependent/parseVersions.h | 236 ++ .../preprocessor/PpContext.h | 703 +++++ .../preprocessor/PpTokens.h | 179 ++ .../propagateNoContraction.h | 55 + .../glslang/MachineIndependent/reflection.h | 223 ++ .../glslang/glslang/Public/ShaderLang.h | 927 ++++++ .../glslang/glslang/SPIRV/GLSL.ext.AMD.h | 108 + .../glslang/glslang/SPIRV/GLSL.ext.EXT.h | 39 + .../glslang/glslang/SPIRV/GLSL.ext.KHR.h | 51 + .../glslang/glslang/SPIRV/GLSL.ext.NV.h | 81 + .../glslang/glslang/SPIRV/GLSL.std.450.h | 131 + .../glslang/glslang/SPIRV/GlslangToSpv.h | 61 + .../include/glslang/glslang/SPIRV/Logger.h | 83 + .../glslang/SPIRV/NonSemanticDebugPrintf.h | 50 + .../glslang/glslang/SPIRV/SPVRemapper.h | 304 ++ .../glslang/glslang/SPIRV/SpvBuilder.h | 838 ++++++ .../include/glslang/glslang/SPIRV/SpvTools.h | 82 + .../include/glslang/glslang/SPIRV/bitutils.h | 81 + .../glslang/glslang/SPIRV/disassemble.h | 53 + .../include/glslang/glslang/SPIRV/doc.h | 258 ++ .../include/glslang/glslang/SPIRV/hex_float.h | 1078 +++++++ .../include/glslang/glslang/SPIRV/spirv.hpp | 2114 ++++++++++++++ .../include/glslang/glslang/SPIRV/spvIR.h | 485 ++++ android/armeabi-v7a/glslang/libOGLCompiler.a | Bin 0 -> 24996 bytes android/armeabi-v7a/glslang/libOSDependent.a | Bin 0 -> 16274 bytes android/armeabi-v7a/glslang/libSPIRV.a | Bin 0 -> 635162 bytes android/armeabi-v7a/glslang/libglslang.a | Bin 0 -> 2240838 bytes .../armeabi-v7a/include/SPIRV/GLSL.ext.AMD.h | 108 + .../armeabi-v7a/include/SPIRV/GLSL.ext.EXT.h | 39 + .../armeabi-v7a/include/SPIRV/GLSL.ext.KHR.h | 51 + .../armeabi-v7a/include/SPIRV/GLSL.ext.NV.h | 81 + .../armeabi-v7a/include/SPIRV/GLSL.std.450.h | 131 + .../armeabi-v7a/include/SPIRV/GlslangToSpv.h | 61 + android/armeabi-v7a/include/SPIRV/Logger.h | 83 + .../include/SPIRV/NonSemanticDebugPrintf.h | 50 + .../armeabi-v7a/include/SPIRV/SPVRemapper.h | 304 ++ .../armeabi-v7a/include/SPIRV/SpvBuilder.h | 838 ++++++ android/armeabi-v7a/include/SPIRV/SpvTools.h | 82 + android/armeabi-v7a/include/SPIRV/bitutils.h | 81 + .../armeabi-v7a/include/SPIRV/disassemble.h | 53 + android/armeabi-v7a/include/SPIRV/doc.h | 258 ++ android/armeabi-v7a/include/SPIRV/hex_float.h | 1078 +++++++ android/armeabi-v7a/include/SPIRV/spirv.hpp | 2114 ++++++++++++++ android/armeabi-v7a/include/SPIRV/spvIR.h | 485 ++++ .../include/glslang/Include/BaseTypes.h | 565 ++++ .../include/glslang/Include/Common.h | 292 ++ .../include/glslang/Include/ConstantUnion.h | 974 +++++++ .../include/glslang/Include/InfoSink.h | 144 + .../glslang/Include/InitializeGlobals.h | 44 + .../include/glslang/Include/PoolAlloc.h | 316 +++ .../include/glslang/Include/ResourceLimits.h | 149 + .../include/glslang/Include/ShHandle.h | 176 ++ .../include/glslang/Include/Types.h | 2483 +++++++++++++++++ .../include/glslang/Include/arrays.h | 341 +++ .../glslang/Include/glslang_c_interface.h | 232 ++ .../glslang/Include/glslang_c_shader_types.h | 182 ++ .../include/glslang/Include/intermediate.h | 1805 ++++++++++++ .../include/glslang/Include/revision.h | 3 + .../glslang/MachineIndependent/Initialize.h | 112 + .../MachineIndependent/LiveTraverser.h | 138 + .../glslang/MachineIndependent/ParseHelper.h | 525 ++++ .../glslang/MachineIndependent/RemoveTree.h | 41 + .../include/glslang/MachineIndependent/Scan.h | 276 ++ .../glslang/MachineIndependent/ScanContext.h | 93 + .../glslang/MachineIndependent/SymbolTable.h | 885 ++++++ .../glslang/MachineIndependent/Versions.h | 327 +++ .../glslang/MachineIndependent/attribute.h | 149 + .../glslang/MachineIndependent/gl_types.h | 210 ++ .../MachineIndependent/glslang_tab.cpp.h | 521 ++++ .../glslang/MachineIndependent/iomapper.h | 300 ++ .../MachineIndependent/localintermediate.h | 1013 +++++++ .../MachineIndependent/parseVersions.h | 236 ++ .../preprocessor/PpContext.h | 703 +++++ .../preprocessor/PpTokens.h | 179 ++ .../propagateNoContraction.h | 55 + .../glslang/MachineIndependent/reflection.h | 223 ++ .../include/glslang/Public/ShaderLang.h | 927 ++++++ .../include/glslang/SPIRV/GLSL.ext.AMD.h | 108 + .../include/glslang/SPIRV/GLSL.ext.EXT.h | 39 + .../include/glslang/SPIRV/GLSL.ext.KHR.h | 51 + .../include/glslang/SPIRV/GLSL.ext.NV.h | 81 + .../include/glslang/SPIRV/GLSL.std.450.h | 131 + .../include/glslang/SPIRV/GlslangToSpv.h | 61 + .../include/glslang/SPIRV/Logger.h | 83 + .../glslang/SPIRV/NonSemanticDebugPrintf.h | 50 + .../include/glslang/SPIRV/SPVRemapper.h | 304 ++ .../include/glslang/SPIRV/SpvBuilder.h | 838 ++++++ .../include/glslang/SPIRV/SpvTools.h | 82 + .../include/glslang/SPIRV/bitutils.h | 81 + .../include/glslang/SPIRV/disassemble.h | 53 + .../armeabi-v7a/include/glslang/SPIRV/doc.h | 258 ++ .../include/glslang/SPIRV/hex_float.h | 1078 +++++++ .../include/glslang/SPIRV/spirv.hpp | 2114 ++++++++++++++ .../armeabi-v7a/include/glslang/SPIRV/spvIR.h | 485 ++++ android/x86/glslang/libOGLCompiler.a | Bin 0 -> 23824 bytes android/x86/glslang/libOSDependent.a | Bin 0 -> 14622 bytes android/x86/glslang/libSPIRV.a | Bin 0 -> 653462 bytes android/x86/glslang/libglslang.a | Bin 0 -> 2297190 bytes android/x86/include/SPIRV/GLSL.ext.AMD.h | 108 + android/x86/include/SPIRV/GLSL.ext.EXT.h | 39 + android/x86/include/SPIRV/GLSL.ext.KHR.h | 51 + android/x86/include/SPIRV/GLSL.ext.NV.h | 81 + android/x86/include/SPIRV/GLSL.std.450.h | 131 + android/x86/include/SPIRV/GlslangToSpv.h | 61 + android/x86/include/SPIRV/Logger.h | 83 + .../include/SPIRV/NonSemanticDebugPrintf.h | 50 + android/x86/include/SPIRV/SPVRemapper.h | 304 ++ android/x86/include/SPIRV/SpvBuilder.h | 838 ++++++ android/x86/include/SPIRV/SpvTools.h | 82 + android/x86/include/SPIRV/bitutils.h | 81 + android/x86/include/SPIRV/disassemble.h | 53 + android/x86/include/SPIRV/doc.h | 258 ++ android/x86/include/SPIRV/hex_float.h | 1078 +++++++ android/x86/include/SPIRV/spirv.hpp | 2114 ++++++++++++++ android/x86/include/SPIRV/spvIR.h | 485 ++++ .../x86/include/glslang/Include/BaseTypes.h | 565 ++++ android/x86/include/glslang/Include/Common.h | 292 ++ .../include/glslang/Include/ConstantUnion.h | 974 +++++++ .../x86/include/glslang/Include/InfoSink.h | 144 + .../glslang/Include/InitializeGlobals.h | 44 + .../x86/include/glslang/Include/PoolAlloc.h | 316 +++ .../include/glslang/Include/ResourceLimits.h | 149 + .../x86/include/glslang/Include/ShHandle.h | 176 ++ android/x86/include/glslang/Include/Types.h | 2483 +++++++++++++++++ android/x86/include/glslang/Include/arrays.h | 341 +++ .../glslang/Include/glslang_c_interface.h | 232 ++ .../glslang/Include/glslang_c_shader_types.h | 182 ++ .../include/glslang/Include/intermediate.h | 1805 ++++++++++++ .../x86/include/glslang/Include/revision.h | 3 + .../glslang/MachineIndependent/Initialize.h | 112 + .../MachineIndependent/LiveTraverser.h | 138 + .../glslang/MachineIndependent/ParseHelper.h | 525 ++++ .../glslang/MachineIndependent/RemoveTree.h | 41 + .../include/glslang/MachineIndependent/Scan.h | 276 ++ .../glslang/MachineIndependent/ScanContext.h | 93 + .../glslang/MachineIndependent/SymbolTable.h | 885 ++++++ .../glslang/MachineIndependent/Versions.h | 327 +++ .../glslang/MachineIndependent/attribute.h | 149 + .../glslang/MachineIndependent/gl_types.h | 210 ++ .../MachineIndependent/glslang_tab.cpp.h | 521 ++++ .../glslang/MachineIndependent/iomapper.h | 300 ++ .../MachineIndependent/localintermediate.h | 1013 +++++++ .../MachineIndependent/parseVersions.h | 236 ++ .../preprocessor/PpContext.h | 703 +++++ .../preprocessor/PpTokens.h | 179 ++ .../propagateNoContraction.h | 55 + .../glslang/MachineIndependent/reflection.h | 223 ++ .../x86/include/glslang/Public/ShaderLang.h | 927 ++++++ .../x86/include/glslang/SPIRV/GLSL.ext.AMD.h | 108 + .../x86/include/glslang/SPIRV/GLSL.ext.EXT.h | 39 + .../x86/include/glslang/SPIRV/GLSL.ext.KHR.h | 51 + .../x86/include/glslang/SPIRV/GLSL.ext.NV.h | 81 + .../x86/include/glslang/SPIRV/GLSL.std.450.h | 131 + .../x86/include/glslang/SPIRV/GlslangToSpv.h | 61 + android/x86/include/glslang/SPIRV/Logger.h | 83 + .../glslang/SPIRV/NonSemanticDebugPrintf.h | 50 + .../x86/include/glslang/SPIRV/SPVRemapper.h | 304 ++ .../x86/include/glslang/SPIRV/SpvBuilder.h | 838 ++++++ android/x86/include/glslang/SPIRV/SpvTools.h | 82 + android/x86/include/glslang/SPIRV/bitutils.h | 81 + .../x86/include/glslang/SPIRV/disassemble.h | 53 + android/x86/include/glslang/SPIRV/doc.h | 258 ++ android/x86/include/glslang/SPIRV/hex_float.h | 1078 +++++++ android/x86/include/glslang/SPIRV/spirv.hpp | 2114 ++++++++++++++ android/x86/include/glslang/SPIRV/spvIR.h | 485 ++++ mac/CMakeLists.txt | 34 + mac/include/SPIRV/GLSL.ext.AMD.h | 108 + mac/include/SPIRV/GLSL.ext.EXT.h | 39 + mac/include/SPIRV/GLSL.ext.KHR.h | 51 + mac/include/SPIRV/GLSL.ext.NV.h | 81 + mac/include/SPIRV/GLSL.std.450.h | 131 + mac/include/SPIRV/GlslangToSpv.h | 61 + mac/include/SPIRV/Logger.h | 83 + mac/include/SPIRV/NonSemanticDebugPrintf.h | 50 + mac/include/SPIRV/SPVRemapper.h | 304 ++ mac/include/SPIRV/SpvBuilder.h | 838 ++++++ mac/include/SPIRV/SpvTools.h | 82 + mac/include/SPIRV/bitutils.h | 81 + mac/include/SPIRV/disassemble.h | 53 + mac/include/SPIRV/doc.h | 258 ++ mac/include/SPIRV/hex_float.h | 1078 +++++++ mac/include/SPIRV/spirv.hpp | 2114 ++++++++++++++ mac/include/SPIRV/spvIR.h | 485 ++++ mac/include/glslang/Include/BaseTypes.h | 565 ++++ mac/include/glslang/Include/Common.h | 292 ++ mac/include/glslang/Include/ConstantUnion.h | 974 +++++++ mac/include/glslang/Include/InfoSink.h | 144 + .../glslang/Include/InitializeGlobals.h | 44 + mac/include/glslang/Include/PoolAlloc.h | 316 +++ mac/include/glslang/Include/ResourceLimits.h | 149 + mac/include/glslang/Include/ShHandle.h | 176 ++ mac/include/glslang/Include/Types.h | 2483 +++++++++++++++++ mac/include/glslang/Include/arrays.h | 341 +++ .../glslang/Include/glslang_c_interface.h | 232 ++ .../glslang/Include/glslang_c_shader_types.h | 182 ++ mac/include/glslang/Include/intermediate.h | 1805 ++++++++++++ mac/include/glslang/Include/revision.h | 3 + .../glslang/MachineIndependent/Initialize.h | 112 + .../MachineIndependent/LiveTraverser.h | 138 + .../glslang/MachineIndependent/ParseHelper.h | 525 ++++ .../glslang/MachineIndependent/RemoveTree.h | 41 + mac/include/glslang/MachineIndependent/Scan.h | 276 ++ .../glslang/MachineIndependent/ScanContext.h | 93 + .../glslang/MachineIndependent/SymbolTable.h | 885 ++++++ .../glslang/MachineIndependent/Versions.h | 327 +++ .../glslang/MachineIndependent/attribute.h | 149 + .../glslang/MachineIndependent/gl_types.h | 210 ++ .../MachineIndependent/glslang_tab.cpp.h | 521 ++++ .../glslang/MachineIndependent/iomapper.h | 300 ++ .../MachineIndependent/localintermediate.h | 1013 +++++++ .../MachineIndependent/parseVersions.h | 236 ++ .../preprocessor/PpContext.h | 703 +++++ .../preprocessor/PpTokens.h | 179 ++ .../propagateNoContraction.h | 55 + .../glslang/MachineIndependent/reflection.h | 223 ++ mac/include/glslang/Public/ShaderLang.h | 927 ++++++ mac/include/glslang/SPIRV/GLSL.ext.AMD.h | 108 + mac/include/glslang/SPIRV/GLSL.ext.EXT.h | 39 + mac/include/glslang/SPIRV/GLSL.ext.KHR.h | 51 + mac/include/glslang/SPIRV/GLSL.ext.NV.h | 81 + mac/include/glslang/SPIRV/GLSL.std.450.h | 131 + mac/include/glslang/SPIRV/GlslangToSpv.h | 61 + mac/include/glslang/SPIRV/Logger.h | 83 + .../glslang/SPIRV/NonSemanticDebugPrintf.h | 50 + mac/include/glslang/SPIRV/SPVRemapper.h | 304 ++ mac/include/glslang/SPIRV/SpvBuilder.h | 838 ++++++ mac/include/glslang/SPIRV/SpvTools.h | 82 + mac/include/glslang/SPIRV/bitutils.h | 81 + mac/include/glslang/SPIRV/disassemble.h | 53 + mac/include/glslang/SPIRV/doc.h | 258 ++ mac/include/glslang/SPIRV/hex_float.h | 1078 +++++++ mac/include/glslang/SPIRV/spirv.hpp | 2114 ++++++++++++++ mac/include/glslang/SPIRV/spvIR.h | 485 ++++ mac/include/spirv_cross/GLSL.std.450.h | 131 + mac/include/spirv_cross/spirv.h | 2104 ++++++++++++++ mac/include/spirv_cross/spirv.hpp | 2114 ++++++++++++++ mac/include/spirv_cross/spirv_cfg.hpp | 156 ++ mac/include/spirv_cross/spirv_common.hpp | 1781 ++++++++++++ mac/include/spirv_cross/spirv_cpp.hpp | 86 + mac/include/spirv_cross/spirv_cross.hpp | 1055 +++++++ mac/include/spirv_cross/spirv_cross_c.h | 912 ++++++ .../spirv_cross/spirv_cross_containers.hpp | 734 +++++ .../spirv_cross_error_handling.hpp | 87 + .../spirv_cross/spirv_cross_parsed_ir.hpp | 231 ++ mac/include/spirv_cross/spirv_cross_util.hpp | 30 + mac/include/spirv_cross/spirv_glsl.hpp | 760 +++++ mac/include/spirv_cross/spirv_hlsl.hpp | 329 +++ mac/include/spirv_cross/spirv_msl.hpp | 962 +++++++ mac/include/spirv_cross/spirv_parser.hpp | 93 + mac/include/spirv_cross/spirv_reflect.hpp | 83 + mac/libs/libOGLCompiler.a | Bin 0 -> 2488 bytes mac/libs/libOSDependent.a | Bin 0 -> 3816 bytes mac/libs/libSPIRV.a | Bin 0 -> 747176 bytes mac/libs/libglslang.a | Bin 0 -> 2593128 bytes mac/libs/libspirv-cross-core.a | Bin 0 -> 655096 bytes mac/libs/libspirv-cross-glsl.a | Bin 0 -> 1200016 bytes mac/libs/libspirv-cross-msl.a | Bin 0 -> 1626488 bytes win32/CMakeLists.txt | 20 + win32/include/glslang/SPIRV/GLSL.ext.AMD.h | 108 + win32/include/glslang/SPIRV/GLSL.ext.EXT.h | 39 + win32/include/glslang/SPIRV/GLSL.ext.KHR.h | 51 + win32/include/glslang/SPIRV/GLSL.ext.NV.h | 81 + win32/include/glslang/SPIRV/GLSL.std.450.h | 131 + win32/include/glslang/SPIRV/GlslangToSpv.h | 61 + win32/include/glslang/SPIRV/Logger.h | 83 + .../glslang/SPIRV/NonSemanticDebugPrintf.h | 50 + win32/include/glslang/SPIRV/SPVRemapper.h | 304 ++ win32/include/glslang/SPIRV/SpvBuilder.h | 838 ++++++ win32/include/glslang/SPIRV/SpvTools.h | 82 + win32/include/glslang/SPIRV/bitutils.h | 81 + win32/include/glslang/SPIRV/disassemble.h | 53 + win32/include/glslang/SPIRV/doc.h | 258 ++ win32/include/glslang/SPIRV/hex_float.h | 1078 +++++++ win32/include/glslang/SPIRV/spirv.hpp | 2114 ++++++++++++++ win32/include/glslang/SPIRV/spvIR.h | 485 ++++ .../glslang/glslang/Include/BaseTypes.h | 565 ++++ .../include/glslang/glslang/Include/Common.h | 292 ++ .../glslang/glslang/Include/ConstantUnion.h | 974 +++++++ .../glslang/glslang/Include/InfoSink.h | 144 + .../glslang/Include/InitializeGlobals.h | 44 + .../glslang/glslang/Include/PoolAlloc.h | 316 +++ .../glslang/glslang/Include/ResourceLimits.h | 149 + .../glslang/glslang/Include/ShHandle.h | 176 ++ win32/include/glslang/glslang/Include/Types.h | 2483 +++++++++++++++++ .../include/glslang/glslang/Include/arrays.h | 341 +++ .../glslang/Include/glslang_c_interface.h | 232 ++ .../glslang/Include/glslang_c_shader_types.h | 182 ++ .../glslang/glslang/Include/intermediate.h | 1805 ++++++++++++ .../glslang/glslang/Include/revision.h | 3 + .../glslang/MachineIndependent/Initialize.h | 112 + .../MachineIndependent/LiveTraverser.h | 138 + .../glslang/MachineIndependent/ParseHelper.h | 525 ++++ .../glslang/MachineIndependent/RemoveTree.h | 41 + .../glslang/glslang/MachineIndependent/Scan.h | 276 ++ .../glslang/MachineIndependent/ScanContext.h | 93 + .../glslang/MachineIndependent/SymbolTable.h | 885 ++++++ .../glslang/MachineIndependent/Versions.h | 327 +++ .../glslang/MachineIndependent/attribute.h | 149 + .../glslang/MachineIndependent/gl_types.h | 210 ++ .../MachineIndependent/glslang_tab.cpp.h | 521 ++++ .../glslang/MachineIndependent/iomapper.h | 300 ++ .../MachineIndependent/localintermediate.h | 1013 +++++++ .../MachineIndependent/parseVersions.h | 236 ++ .../preprocessor/PpContext.h | 703 +++++ .../preprocessor/PpTokens.h | 179 ++ .../propagateNoContraction.h | 55 + .../glslang/MachineIndependent/reflection.h | 223 ++ .../glslang/glslang/Public/ShaderLang.h | 927 ++++++ .../glslang/glslang/SPIRV/GLSL.ext.AMD.h | 108 + .../glslang/glslang/SPIRV/GLSL.ext.EXT.h | 39 + .../glslang/glslang/SPIRV/GLSL.ext.KHR.h | 51 + .../glslang/glslang/SPIRV/GLSL.ext.NV.h | 81 + .../glslang/glslang/SPIRV/GLSL.std.450.h | 131 + .../glslang/glslang/SPIRV/GlslangToSpv.h | 61 + win32/include/glslang/glslang/SPIRV/Logger.h | 83 + .../glslang/SPIRV/NonSemanticDebugPrintf.h | 50 + .../glslang/glslang/SPIRV/SPVRemapper.h | 304 ++ .../glslang/glslang/SPIRV/SpvBuilder.h | 838 ++++++ .../include/glslang/glslang/SPIRV/SpvTools.h | 82 + .../include/glslang/glslang/SPIRV/bitutils.h | 81 + .../glslang/glslang/SPIRV/disassemble.h | 53 + win32/include/glslang/glslang/SPIRV/doc.h | 258 ++ .../include/glslang/glslang/SPIRV/hex_float.h | 1078 +++++++ win32/include/glslang/glslang/SPIRV/spirv.hpp | 2114 ++++++++++++++ win32/include/glslang/glslang/SPIRV/spvIR.h | 485 ++++ win32/libs/glslang/OGLCompiler.lib | Bin 0 -> 13024 bytes win32/libs/glslang/OSDependent.lib | Bin 0 -> 5522 bytes win32/libs/glslang/SPIRV.lib | Bin 0 -> 1837386 bytes win32/libs/glslang/glslang.lib | Bin 0 -> 5829776 bytes 378 files changed, 143787 insertions(+) create mode 100644 android/arm64-v8a/glslang/libOGLCompiler.a create mode 100644 android/arm64-v8a/glslang/libOSDependent.a create mode 100644 android/arm64-v8a/glslang/libSPIRV.a create mode 100644 android/arm64-v8a/glslang/libglslang.a create mode 100644 android/arm64-v8a/include/glslang/SPIRV/GLSL.ext.AMD.h create mode 100644 android/arm64-v8a/include/glslang/SPIRV/GLSL.ext.EXT.h create mode 100644 android/arm64-v8a/include/glslang/SPIRV/GLSL.ext.KHR.h create mode 100644 android/arm64-v8a/include/glslang/SPIRV/GLSL.ext.NV.h create mode 100644 android/arm64-v8a/include/glslang/SPIRV/GLSL.std.450.h create mode 100644 android/arm64-v8a/include/glslang/SPIRV/GlslangToSpv.h create mode 100644 android/arm64-v8a/include/glslang/SPIRV/Logger.h create mode 100644 android/arm64-v8a/include/glslang/SPIRV/NonSemanticDebugPrintf.h create mode 100644 android/arm64-v8a/include/glslang/SPIRV/SPVRemapper.h create mode 100644 android/arm64-v8a/include/glslang/SPIRV/SpvBuilder.h create mode 100644 android/arm64-v8a/include/glslang/SPIRV/SpvTools.h create mode 100644 android/arm64-v8a/include/glslang/SPIRV/bitutils.h create mode 100644 android/arm64-v8a/include/glslang/SPIRV/disassemble.h create mode 100644 android/arm64-v8a/include/glslang/SPIRV/doc.h create mode 100644 android/arm64-v8a/include/glslang/SPIRV/hex_float.h create mode 100644 android/arm64-v8a/include/glslang/SPIRV/spirv.hpp create mode 100644 android/arm64-v8a/include/glslang/SPIRV/spvIR.h create mode 100644 android/arm64-v8a/include/glslang/glslang/Include/BaseTypes.h create mode 100644 android/arm64-v8a/include/glslang/glslang/Include/Common.h create mode 100644 android/arm64-v8a/include/glslang/glslang/Include/ConstantUnion.h create mode 100644 android/arm64-v8a/include/glslang/glslang/Include/InfoSink.h create mode 100644 android/arm64-v8a/include/glslang/glslang/Include/InitializeGlobals.h create mode 100644 android/arm64-v8a/include/glslang/glslang/Include/PoolAlloc.h create mode 100644 android/arm64-v8a/include/glslang/glslang/Include/ResourceLimits.h create mode 100644 android/arm64-v8a/include/glslang/glslang/Include/ShHandle.h create mode 100644 android/arm64-v8a/include/glslang/glslang/Include/Types.h create mode 100644 android/arm64-v8a/include/glslang/glslang/Include/arrays.h create mode 100644 android/arm64-v8a/include/glslang/glslang/Include/glslang_c_interface.h create mode 100644 android/arm64-v8a/include/glslang/glslang/Include/glslang_c_shader_types.h create mode 100644 android/arm64-v8a/include/glslang/glslang/Include/intermediate.h create mode 100644 android/arm64-v8a/include/glslang/glslang/Include/revision.h create mode 100644 android/arm64-v8a/include/glslang/glslang/MachineIndependent/Initialize.h create mode 100644 android/arm64-v8a/include/glslang/glslang/MachineIndependent/LiveTraverser.h create mode 100644 android/arm64-v8a/include/glslang/glslang/MachineIndependent/ParseHelper.h create mode 100644 android/arm64-v8a/include/glslang/glslang/MachineIndependent/RemoveTree.h create mode 100644 android/arm64-v8a/include/glslang/glslang/MachineIndependent/Scan.h create mode 100644 android/arm64-v8a/include/glslang/glslang/MachineIndependent/ScanContext.h create mode 100644 android/arm64-v8a/include/glslang/glslang/MachineIndependent/SymbolTable.h create mode 100644 android/arm64-v8a/include/glslang/glslang/MachineIndependent/Versions.h create mode 100644 android/arm64-v8a/include/glslang/glslang/MachineIndependent/attribute.h create mode 100644 android/arm64-v8a/include/glslang/glslang/MachineIndependent/gl_types.h create mode 100644 android/arm64-v8a/include/glslang/glslang/MachineIndependent/glslang_tab.cpp.h create mode 100644 android/arm64-v8a/include/glslang/glslang/MachineIndependent/iomapper.h create mode 100644 android/arm64-v8a/include/glslang/glslang/MachineIndependent/localintermediate.h create mode 100644 android/arm64-v8a/include/glslang/glslang/MachineIndependent/parseVersions.h create mode 100644 android/arm64-v8a/include/glslang/glslang/MachineIndependent/preprocessor/PpContext.h create mode 100644 android/arm64-v8a/include/glslang/glslang/MachineIndependent/preprocessor/PpTokens.h create mode 100644 android/arm64-v8a/include/glslang/glslang/MachineIndependent/propagateNoContraction.h create mode 100644 android/arm64-v8a/include/glslang/glslang/MachineIndependent/reflection.h create mode 100644 android/arm64-v8a/include/glslang/glslang/Public/ShaderLang.h create mode 100644 android/arm64-v8a/include/glslang/glslang/SPIRV/GLSL.ext.AMD.h create mode 100644 android/arm64-v8a/include/glslang/glslang/SPIRV/GLSL.ext.EXT.h create mode 100644 android/arm64-v8a/include/glslang/glslang/SPIRV/GLSL.ext.KHR.h create mode 100644 android/arm64-v8a/include/glslang/glslang/SPIRV/GLSL.ext.NV.h create mode 100644 android/arm64-v8a/include/glslang/glslang/SPIRV/GLSL.std.450.h create mode 100644 android/arm64-v8a/include/glslang/glslang/SPIRV/GlslangToSpv.h create mode 100644 android/arm64-v8a/include/glslang/glslang/SPIRV/Logger.h create mode 100644 android/arm64-v8a/include/glslang/glslang/SPIRV/NonSemanticDebugPrintf.h create mode 100644 android/arm64-v8a/include/glslang/glslang/SPIRV/SPVRemapper.h create mode 100644 android/arm64-v8a/include/glslang/glslang/SPIRV/SpvBuilder.h create mode 100644 android/arm64-v8a/include/glslang/glslang/SPIRV/SpvTools.h create mode 100644 android/arm64-v8a/include/glslang/glslang/SPIRV/bitutils.h create mode 100644 android/arm64-v8a/include/glslang/glslang/SPIRV/disassemble.h create mode 100644 android/arm64-v8a/include/glslang/glslang/SPIRV/doc.h create mode 100644 android/arm64-v8a/include/glslang/glslang/SPIRV/hex_float.h create mode 100644 android/arm64-v8a/include/glslang/glslang/SPIRV/spirv.hpp create mode 100644 android/arm64-v8a/include/glslang/glslang/SPIRV/spvIR.h create mode 100644 android/armeabi-v7a/glslang/libOGLCompiler.a create mode 100644 android/armeabi-v7a/glslang/libOSDependent.a create mode 100644 android/armeabi-v7a/glslang/libSPIRV.a create mode 100644 android/armeabi-v7a/glslang/libglslang.a create mode 100644 android/armeabi-v7a/include/SPIRV/GLSL.ext.AMD.h create mode 100644 android/armeabi-v7a/include/SPIRV/GLSL.ext.EXT.h create mode 100644 android/armeabi-v7a/include/SPIRV/GLSL.ext.KHR.h create mode 100644 android/armeabi-v7a/include/SPIRV/GLSL.ext.NV.h create mode 100644 android/armeabi-v7a/include/SPIRV/GLSL.std.450.h create mode 100644 android/armeabi-v7a/include/SPIRV/GlslangToSpv.h create mode 100644 android/armeabi-v7a/include/SPIRV/Logger.h create mode 100644 android/armeabi-v7a/include/SPIRV/NonSemanticDebugPrintf.h create mode 100644 android/armeabi-v7a/include/SPIRV/SPVRemapper.h create mode 100644 android/armeabi-v7a/include/SPIRV/SpvBuilder.h create mode 100644 android/armeabi-v7a/include/SPIRV/SpvTools.h create mode 100644 android/armeabi-v7a/include/SPIRV/bitutils.h create mode 100644 android/armeabi-v7a/include/SPIRV/disassemble.h create mode 100644 android/armeabi-v7a/include/SPIRV/doc.h create mode 100644 android/armeabi-v7a/include/SPIRV/hex_float.h create mode 100644 android/armeabi-v7a/include/SPIRV/spirv.hpp create mode 100644 android/armeabi-v7a/include/SPIRV/spvIR.h create mode 100644 android/armeabi-v7a/include/glslang/Include/BaseTypes.h create mode 100644 android/armeabi-v7a/include/glslang/Include/Common.h create mode 100644 android/armeabi-v7a/include/glslang/Include/ConstantUnion.h create mode 100644 android/armeabi-v7a/include/glslang/Include/InfoSink.h create mode 100644 android/armeabi-v7a/include/glslang/Include/InitializeGlobals.h create mode 100644 android/armeabi-v7a/include/glslang/Include/PoolAlloc.h create mode 100644 android/armeabi-v7a/include/glslang/Include/ResourceLimits.h create mode 100644 android/armeabi-v7a/include/glslang/Include/ShHandle.h create mode 100644 android/armeabi-v7a/include/glslang/Include/Types.h create mode 100644 android/armeabi-v7a/include/glslang/Include/arrays.h create mode 100644 android/armeabi-v7a/include/glslang/Include/glslang_c_interface.h create mode 100644 android/armeabi-v7a/include/glslang/Include/glslang_c_shader_types.h create mode 100644 android/armeabi-v7a/include/glslang/Include/intermediate.h create mode 100644 android/armeabi-v7a/include/glslang/Include/revision.h create mode 100644 android/armeabi-v7a/include/glslang/MachineIndependent/Initialize.h create mode 100644 android/armeabi-v7a/include/glslang/MachineIndependent/LiveTraverser.h create mode 100644 android/armeabi-v7a/include/glslang/MachineIndependent/ParseHelper.h create mode 100644 android/armeabi-v7a/include/glslang/MachineIndependent/RemoveTree.h create mode 100644 android/armeabi-v7a/include/glslang/MachineIndependent/Scan.h create mode 100644 android/armeabi-v7a/include/glslang/MachineIndependent/ScanContext.h create mode 100644 android/armeabi-v7a/include/glslang/MachineIndependent/SymbolTable.h create mode 100644 android/armeabi-v7a/include/glslang/MachineIndependent/Versions.h create mode 100644 android/armeabi-v7a/include/glslang/MachineIndependent/attribute.h create mode 100644 android/armeabi-v7a/include/glslang/MachineIndependent/gl_types.h create mode 100644 android/armeabi-v7a/include/glslang/MachineIndependent/glslang_tab.cpp.h create mode 100644 android/armeabi-v7a/include/glslang/MachineIndependent/iomapper.h create mode 100644 android/armeabi-v7a/include/glslang/MachineIndependent/localintermediate.h create mode 100644 android/armeabi-v7a/include/glslang/MachineIndependent/parseVersions.h create mode 100644 android/armeabi-v7a/include/glslang/MachineIndependent/preprocessor/PpContext.h create mode 100644 android/armeabi-v7a/include/glslang/MachineIndependent/preprocessor/PpTokens.h create mode 100644 android/armeabi-v7a/include/glslang/MachineIndependent/propagateNoContraction.h create mode 100644 android/armeabi-v7a/include/glslang/MachineIndependent/reflection.h create mode 100644 android/armeabi-v7a/include/glslang/Public/ShaderLang.h create mode 100644 android/armeabi-v7a/include/glslang/SPIRV/GLSL.ext.AMD.h create mode 100644 android/armeabi-v7a/include/glslang/SPIRV/GLSL.ext.EXT.h create mode 100644 android/armeabi-v7a/include/glslang/SPIRV/GLSL.ext.KHR.h create mode 100644 android/armeabi-v7a/include/glslang/SPIRV/GLSL.ext.NV.h create mode 100644 android/armeabi-v7a/include/glslang/SPIRV/GLSL.std.450.h create mode 100644 android/armeabi-v7a/include/glslang/SPIRV/GlslangToSpv.h create mode 100644 android/armeabi-v7a/include/glslang/SPIRV/Logger.h create mode 100644 android/armeabi-v7a/include/glslang/SPIRV/NonSemanticDebugPrintf.h create mode 100644 android/armeabi-v7a/include/glslang/SPIRV/SPVRemapper.h create mode 100644 android/armeabi-v7a/include/glslang/SPIRV/SpvBuilder.h create mode 100644 android/armeabi-v7a/include/glslang/SPIRV/SpvTools.h create mode 100644 android/armeabi-v7a/include/glslang/SPIRV/bitutils.h create mode 100644 android/armeabi-v7a/include/glslang/SPIRV/disassemble.h create mode 100644 android/armeabi-v7a/include/glslang/SPIRV/doc.h create mode 100644 android/armeabi-v7a/include/glslang/SPIRV/hex_float.h create mode 100644 android/armeabi-v7a/include/glslang/SPIRV/spirv.hpp create mode 100644 android/armeabi-v7a/include/glslang/SPIRV/spvIR.h create mode 100644 android/x86/glslang/libOGLCompiler.a create mode 100644 android/x86/glslang/libOSDependent.a create mode 100644 android/x86/glslang/libSPIRV.a create mode 100644 android/x86/glslang/libglslang.a create mode 100644 android/x86/include/SPIRV/GLSL.ext.AMD.h create mode 100644 android/x86/include/SPIRV/GLSL.ext.EXT.h create mode 100644 android/x86/include/SPIRV/GLSL.ext.KHR.h create mode 100644 android/x86/include/SPIRV/GLSL.ext.NV.h create mode 100644 android/x86/include/SPIRV/GLSL.std.450.h create mode 100644 android/x86/include/SPIRV/GlslangToSpv.h create mode 100644 android/x86/include/SPIRV/Logger.h create mode 100644 android/x86/include/SPIRV/NonSemanticDebugPrintf.h create mode 100644 android/x86/include/SPIRV/SPVRemapper.h create mode 100644 android/x86/include/SPIRV/SpvBuilder.h create mode 100644 android/x86/include/SPIRV/SpvTools.h create mode 100644 android/x86/include/SPIRV/bitutils.h create mode 100644 android/x86/include/SPIRV/disassemble.h create mode 100644 android/x86/include/SPIRV/doc.h create mode 100644 android/x86/include/SPIRV/hex_float.h create mode 100644 android/x86/include/SPIRV/spirv.hpp create mode 100644 android/x86/include/SPIRV/spvIR.h create mode 100644 android/x86/include/glslang/Include/BaseTypes.h create mode 100644 android/x86/include/glslang/Include/Common.h create mode 100644 android/x86/include/glslang/Include/ConstantUnion.h create mode 100644 android/x86/include/glslang/Include/InfoSink.h create mode 100644 android/x86/include/glslang/Include/InitializeGlobals.h create mode 100644 android/x86/include/glslang/Include/PoolAlloc.h create mode 100644 android/x86/include/glslang/Include/ResourceLimits.h create mode 100644 android/x86/include/glslang/Include/ShHandle.h create mode 100644 android/x86/include/glslang/Include/Types.h create mode 100644 android/x86/include/glslang/Include/arrays.h create mode 100644 android/x86/include/glslang/Include/glslang_c_interface.h create mode 100644 android/x86/include/glslang/Include/glslang_c_shader_types.h create mode 100644 android/x86/include/glslang/Include/intermediate.h create mode 100644 android/x86/include/glslang/Include/revision.h create mode 100644 android/x86/include/glslang/MachineIndependent/Initialize.h create mode 100644 android/x86/include/glslang/MachineIndependent/LiveTraverser.h create mode 100644 android/x86/include/glslang/MachineIndependent/ParseHelper.h create mode 100644 android/x86/include/glslang/MachineIndependent/RemoveTree.h create mode 100644 android/x86/include/glslang/MachineIndependent/Scan.h create mode 100644 android/x86/include/glslang/MachineIndependent/ScanContext.h create mode 100644 android/x86/include/glslang/MachineIndependent/SymbolTable.h create mode 100644 android/x86/include/glslang/MachineIndependent/Versions.h create mode 100644 android/x86/include/glslang/MachineIndependent/attribute.h create mode 100644 android/x86/include/glslang/MachineIndependent/gl_types.h create mode 100644 android/x86/include/glslang/MachineIndependent/glslang_tab.cpp.h create mode 100644 android/x86/include/glslang/MachineIndependent/iomapper.h create mode 100644 android/x86/include/glslang/MachineIndependent/localintermediate.h create mode 100644 android/x86/include/glslang/MachineIndependent/parseVersions.h create mode 100644 android/x86/include/glslang/MachineIndependent/preprocessor/PpContext.h create mode 100644 android/x86/include/glslang/MachineIndependent/preprocessor/PpTokens.h create mode 100644 android/x86/include/glslang/MachineIndependent/propagateNoContraction.h create mode 100644 android/x86/include/glslang/MachineIndependent/reflection.h create mode 100644 android/x86/include/glslang/Public/ShaderLang.h create mode 100644 android/x86/include/glslang/SPIRV/GLSL.ext.AMD.h create mode 100644 android/x86/include/glslang/SPIRV/GLSL.ext.EXT.h create mode 100644 android/x86/include/glslang/SPIRV/GLSL.ext.KHR.h create mode 100644 android/x86/include/glslang/SPIRV/GLSL.ext.NV.h create mode 100644 android/x86/include/glslang/SPIRV/GLSL.std.450.h create mode 100644 android/x86/include/glslang/SPIRV/GlslangToSpv.h create mode 100644 android/x86/include/glslang/SPIRV/Logger.h create mode 100644 android/x86/include/glslang/SPIRV/NonSemanticDebugPrintf.h create mode 100644 android/x86/include/glslang/SPIRV/SPVRemapper.h create mode 100644 android/x86/include/glslang/SPIRV/SpvBuilder.h create mode 100644 android/x86/include/glslang/SPIRV/SpvTools.h create mode 100644 android/x86/include/glslang/SPIRV/bitutils.h create mode 100644 android/x86/include/glslang/SPIRV/disassemble.h create mode 100644 android/x86/include/glslang/SPIRV/doc.h create mode 100644 android/x86/include/glslang/SPIRV/hex_float.h create mode 100644 android/x86/include/glslang/SPIRV/spirv.hpp create mode 100644 android/x86/include/glslang/SPIRV/spvIR.h create mode 100644 mac/include/SPIRV/GLSL.ext.AMD.h create mode 100644 mac/include/SPIRV/GLSL.ext.EXT.h create mode 100644 mac/include/SPIRV/GLSL.ext.KHR.h create mode 100644 mac/include/SPIRV/GLSL.ext.NV.h create mode 100644 mac/include/SPIRV/GLSL.std.450.h create mode 100644 mac/include/SPIRV/GlslangToSpv.h create mode 100644 mac/include/SPIRV/Logger.h create mode 100644 mac/include/SPIRV/NonSemanticDebugPrintf.h create mode 100644 mac/include/SPIRV/SPVRemapper.h create mode 100644 mac/include/SPIRV/SpvBuilder.h create mode 100644 mac/include/SPIRV/SpvTools.h create mode 100644 mac/include/SPIRV/bitutils.h create mode 100644 mac/include/SPIRV/disassemble.h create mode 100644 mac/include/SPIRV/doc.h create mode 100644 mac/include/SPIRV/hex_float.h create mode 100644 mac/include/SPIRV/spirv.hpp create mode 100644 mac/include/SPIRV/spvIR.h create mode 100644 mac/include/glslang/Include/BaseTypes.h create mode 100644 mac/include/glslang/Include/Common.h create mode 100644 mac/include/glslang/Include/ConstantUnion.h create mode 100644 mac/include/glslang/Include/InfoSink.h create mode 100644 mac/include/glslang/Include/InitializeGlobals.h create mode 100644 mac/include/glslang/Include/PoolAlloc.h create mode 100644 mac/include/glslang/Include/ResourceLimits.h create mode 100644 mac/include/glslang/Include/ShHandle.h create mode 100644 mac/include/glslang/Include/Types.h create mode 100644 mac/include/glslang/Include/arrays.h create mode 100644 mac/include/glslang/Include/glslang_c_interface.h create mode 100644 mac/include/glslang/Include/glslang_c_shader_types.h create mode 100644 mac/include/glslang/Include/intermediate.h create mode 100644 mac/include/glslang/Include/revision.h create mode 100644 mac/include/glslang/MachineIndependent/Initialize.h create mode 100644 mac/include/glslang/MachineIndependent/LiveTraverser.h create mode 100644 mac/include/glslang/MachineIndependent/ParseHelper.h create mode 100644 mac/include/glslang/MachineIndependent/RemoveTree.h create mode 100644 mac/include/glslang/MachineIndependent/Scan.h create mode 100644 mac/include/glslang/MachineIndependent/ScanContext.h create mode 100644 mac/include/glslang/MachineIndependent/SymbolTable.h create mode 100644 mac/include/glslang/MachineIndependent/Versions.h create mode 100644 mac/include/glslang/MachineIndependent/attribute.h create mode 100644 mac/include/glslang/MachineIndependent/gl_types.h create mode 100644 mac/include/glslang/MachineIndependent/glslang_tab.cpp.h create mode 100644 mac/include/glslang/MachineIndependent/iomapper.h create mode 100644 mac/include/glslang/MachineIndependent/localintermediate.h create mode 100644 mac/include/glslang/MachineIndependent/parseVersions.h create mode 100644 mac/include/glslang/MachineIndependent/preprocessor/PpContext.h create mode 100644 mac/include/glslang/MachineIndependent/preprocessor/PpTokens.h create mode 100644 mac/include/glslang/MachineIndependent/propagateNoContraction.h create mode 100644 mac/include/glslang/MachineIndependent/reflection.h create mode 100644 mac/include/glslang/Public/ShaderLang.h create mode 100644 mac/include/glslang/SPIRV/GLSL.ext.AMD.h create mode 100644 mac/include/glslang/SPIRV/GLSL.ext.EXT.h create mode 100644 mac/include/glslang/SPIRV/GLSL.ext.KHR.h create mode 100644 mac/include/glslang/SPIRV/GLSL.ext.NV.h create mode 100644 mac/include/glslang/SPIRV/GLSL.std.450.h create mode 100644 mac/include/glslang/SPIRV/GlslangToSpv.h create mode 100644 mac/include/glslang/SPIRV/Logger.h create mode 100644 mac/include/glslang/SPIRV/NonSemanticDebugPrintf.h create mode 100644 mac/include/glslang/SPIRV/SPVRemapper.h create mode 100644 mac/include/glslang/SPIRV/SpvBuilder.h create mode 100644 mac/include/glslang/SPIRV/SpvTools.h create mode 100644 mac/include/glslang/SPIRV/bitutils.h create mode 100644 mac/include/glslang/SPIRV/disassemble.h create mode 100644 mac/include/glslang/SPIRV/doc.h create mode 100644 mac/include/glslang/SPIRV/hex_float.h create mode 100644 mac/include/glslang/SPIRV/spirv.hpp create mode 100644 mac/include/glslang/SPIRV/spvIR.h create mode 100644 mac/include/spirv_cross/GLSL.std.450.h create mode 100644 mac/include/spirv_cross/spirv.h create mode 100644 mac/include/spirv_cross/spirv.hpp create mode 100644 mac/include/spirv_cross/spirv_cfg.hpp create mode 100644 mac/include/spirv_cross/spirv_common.hpp create mode 100644 mac/include/spirv_cross/spirv_cpp.hpp create mode 100644 mac/include/spirv_cross/spirv_cross.hpp create mode 100644 mac/include/spirv_cross/spirv_cross_c.h create mode 100644 mac/include/spirv_cross/spirv_cross_containers.hpp create mode 100644 mac/include/spirv_cross/spirv_cross_error_handling.hpp create mode 100644 mac/include/spirv_cross/spirv_cross_parsed_ir.hpp create mode 100644 mac/include/spirv_cross/spirv_cross_util.hpp create mode 100644 mac/include/spirv_cross/spirv_glsl.hpp create mode 100644 mac/include/spirv_cross/spirv_hlsl.hpp create mode 100644 mac/include/spirv_cross/spirv_msl.hpp create mode 100644 mac/include/spirv_cross/spirv_parser.hpp create mode 100644 mac/include/spirv_cross/spirv_reflect.hpp create mode 100644 mac/libs/libOGLCompiler.a create mode 100644 mac/libs/libOSDependent.a create mode 100644 mac/libs/libSPIRV.a create mode 100644 mac/libs/libglslang.a create mode 100644 mac/libs/libspirv-cross-core.a create mode 100644 mac/libs/libspirv-cross-glsl.a create mode 100644 mac/libs/libspirv-cross-msl.a create mode 100644 win32/include/glslang/SPIRV/GLSL.ext.AMD.h create mode 100644 win32/include/glslang/SPIRV/GLSL.ext.EXT.h create mode 100644 win32/include/glslang/SPIRV/GLSL.ext.KHR.h create mode 100644 win32/include/glslang/SPIRV/GLSL.ext.NV.h create mode 100644 win32/include/glslang/SPIRV/GLSL.std.450.h create mode 100644 win32/include/glslang/SPIRV/GlslangToSpv.h create mode 100644 win32/include/glslang/SPIRV/Logger.h create mode 100644 win32/include/glslang/SPIRV/NonSemanticDebugPrintf.h create mode 100644 win32/include/glslang/SPIRV/SPVRemapper.h create mode 100644 win32/include/glslang/SPIRV/SpvBuilder.h create mode 100644 win32/include/glslang/SPIRV/SpvTools.h create mode 100644 win32/include/glslang/SPIRV/bitutils.h create mode 100644 win32/include/glslang/SPIRV/disassemble.h create mode 100644 win32/include/glslang/SPIRV/doc.h create mode 100644 win32/include/glslang/SPIRV/hex_float.h create mode 100644 win32/include/glslang/SPIRV/spirv.hpp create mode 100644 win32/include/glslang/SPIRV/spvIR.h create mode 100644 win32/include/glslang/glslang/Include/BaseTypes.h create mode 100644 win32/include/glslang/glslang/Include/Common.h create mode 100644 win32/include/glslang/glslang/Include/ConstantUnion.h create mode 100644 win32/include/glslang/glslang/Include/InfoSink.h create mode 100644 win32/include/glslang/glslang/Include/InitializeGlobals.h create mode 100644 win32/include/glslang/glslang/Include/PoolAlloc.h create mode 100644 win32/include/glslang/glslang/Include/ResourceLimits.h create mode 100644 win32/include/glslang/glslang/Include/ShHandle.h create mode 100644 win32/include/glslang/glslang/Include/Types.h create mode 100644 win32/include/glslang/glslang/Include/arrays.h create mode 100644 win32/include/glslang/glslang/Include/glslang_c_interface.h create mode 100644 win32/include/glslang/glslang/Include/glslang_c_shader_types.h create mode 100644 win32/include/glslang/glslang/Include/intermediate.h create mode 100644 win32/include/glslang/glslang/Include/revision.h create mode 100644 win32/include/glslang/glslang/MachineIndependent/Initialize.h create mode 100644 win32/include/glslang/glslang/MachineIndependent/LiveTraverser.h create mode 100644 win32/include/glslang/glslang/MachineIndependent/ParseHelper.h create mode 100644 win32/include/glslang/glslang/MachineIndependent/RemoveTree.h create mode 100644 win32/include/glslang/glslang/MachineIndependent/Scan.h create mode 100644 win32/include/glslang/glslang/MachineIndependent/ScanContext.h create mode 100644 win32/include/glslang/glslang/MachineIndependent/SymbolTable.h create mode 100644 win32/include/glslang/glslang/MachineIndependent/Versions.h create mode 100644 win32/include/glslang/glslang/MachineIndependent/attribute.h create mode 100644 win32/include/glslang/glslang/MachineIndependent/gl_types.h create mode 100644 win32/include/glslang/glslang/MachineIndependent/glslang_tab.cpp.h create mode 100644 win32/include/glslang/glslang/MachineIndependent/iomapper.h create mode 100644 win32/include/glslang/glslang/MachineIndependent/localintermediate.h create mode 100644 win32/include/glslang/glslang/MachineIndependent/parseVersions.h create mode 100644 win32/include/glslang/glslang/MachineIndependent/preprocessor/PpContext.h create mode 100644 win32/include/glslang/glslang/MachineIndependent/preprocessor/PpTokens.h create mode 100644 win32/include/glslang/glslang/MachineIndependent/propagateNoContraction.h create mode 100644 win32/include/glslang/glslang/MachineIndependent/reflection.h create mode 100644 win32/include/glslang/glslang/Public/ShaderLang.h create mode 100644 win32/include/glslang/glslang/SPIRV/GLSL.ext.AMD.h create mode 100644 win32/include/glslang/glslang/SPIRV/GLSL.ext.EXT.h create mode 100644 win32/include/glslang/glslang/SPIRV/GLSL.ext.KHR.h create mode 100644 win32/include/glslang/glslang/SPIRV/GLSL.ext.NV.h create mode 100644 win32/include/glslang/glslang/SPIRV/GLSL.std.450.h create mode 100644 win32/include/glslang/glslang/SPIRV/GlslangToSpv.h create mode 100644 win32/include/glslang/glslang/SPIRV/Logger.h create mode 100644 win32/include/glslang/glslang/SPIRV/NonSemanticDebugPrintf.h create mode 100644 win32/include/glslang/glslang/SPIRV/SPVRemapper.h create mode 100644 win32/include/glslang/glslang/SPIRV/SpvBuilder.h create mode 100644 win32/include/glslang/glslang/SPIRV/SpvTools.h create mode 100644 win32/include/glslang/glslang/SPIRV/bitutils.h create mode 100644 win32/include/glslang/glslang/SPIRV/disassemble.h create mode 100644 win32/include/glslang/glslang/SPIRV/doc.h create mode 100644 win32/include/glslang/glslang/SPIRV/hex_float.h create mode 100644 win32/include/glslang/glslang/SPIRV/spirv.hpp create mode 100644 win32/include/glslang/glslang/SPIRV/spvIR.h create mode 100644 win32/libs/glslang/OGLCompiler.lib create mode 100644 win32/libs/glslang/OSDependent.lib create mode 100644 win32/libs/glslang/SPIRV.lib create mode 100644 win32/libs/glslang/glslang.lib diff --git a/android/CMakeLists.txt b/android/CMakeLists.txt index 23e2fb0e..ab4cafc3 100644 --- a/android/CMakeLists.txt +++ b/android/CMakeLists.txt @@ -173,6 +173,24 @@ if(USE_SE_V8 AND USE_V8_DEBUGGER) ) endif() +add_library(glslang STATIC IMPORTED GLOBAL) +set_target_properties(glslang PROPERTIES + IMPORTED_LOCATION ${platform_spec_path}/glslang/glslang.lib +) +add_library(OGLCompiler STATIC IMPORTED GLOBAL) +set_target_properties(OGLCompiler PROPERTIES + IMPORTED_LOCATION ${platform_spec_path}/glslang/OGLCompiler.lib +) +add_library(OSDependent STATIC IMPORTED GLOBAL) +set_target_properties(OSDependent PROPERTIES + IMPORTED_LOCATION ${platform_spec_path}/glslang/OSDependent.lib +) +add_library(SPIRV STATIC IMPORTED GLOBAL) +set_target_properties(SPIRV PROPERTIES + IMPORTED_LOCATION ${platform_spec_path}/glslang/SPIRV.lib +) +set(glslang_libs_name glslang OGLCompiler OSDependent SPIRV) + list(APPEND CC_EXTERNAL_LIBS freetype @@ -183,6 +201,7 @@ list(APPEND CC_EXTERNAL_LIBS ${se_libs_name} z android_platform + ${glslang_libs_name} ) @@ -190,5 +209,6 @@ list(APPEND CC_EXTERNAL_INCLUDES ${platform_spec_path}/include ${platform_spec_path}/include/v8 ${platform_spec_path}/include/uv + ${platform_spec_path}/include/glslang ${CMAKE_ANDROID_NDK}/sources/android/native_app_glue ) \ No newline at end of file diff --git a/android/arm64-v8a/glslang/libOGLCompiler.a b/android/arm64-v8a/glslang/libOGLCompiler.a new file mode 100644 index 0000000000000000000000000000000000000000..fe032c646ecad114a14f9276af081f540ce77907 GIT binary patch literal 25332 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 literal 0 HcmV?d00001 diff --git a/android/arm64-v8a/glslang/libOSDependent.a b/android/arm64-v8a/glslang/libOSDependent.a new file mode 100644 index 0000000000000000000000000000000000000000..3aaae6f595730950166d8df47bdfebfdf198d1e7 GIT binary patch literal 18046 zcmeI3dz4hgnZWB#Ps6-GWKiDF0|O4n*pGRG28O^00|Si13BsGvc6z#-emS5~ z!Qk5{sPTahjM0dXqtPTjqpq5>N>;PGn#63@Bc7b>K{v_zh`Ov2_xq~8x?Q*Wc0xSI zoc&|#%-pZ)_kHz!RdwrD*S+1h;j~aDGQ70L=dq_iTW4o;b7yO3yT{|_D)s2`w6wHR zg{?J=v1-PQy?^aLc;@%2{Xv`iHn2E7W18ThCmA)zbPw&IU!F*$B9?(YLPx)uFhg0h zT>G2-;9v!qB=hNk;fxuIt_j7h7vC?Cw3i!Z6^3h-9$GSg|B2WA7~~ z=DT>di=8Aar+oeb`-*sdzW7`f*z3i4{M$LcT$=JZr^S*ZA!`iMR;A_uwuHY}x9^C)%=y}f` zIO<}1SS33HnW%TijHBoM!@b;2@F~Y)Teh9xU$*fOhf)-I$%Eq{&{^p-)}}zqv?3U^qd>d4SQA&uIme~*f6+$pu2ygCu+vxNi*unr94^F z^hD@1d)e}2G?R))Jxy)R&3=DtvnLD_D(XokJ(-r)_Lk1Ykwu;eUMZdeOp7@1POsnF z;b|Jq<+t(K+XEeo{wCjvL}Ap^5@}i75;HqO9cG{> zh1xq?q8*{Oa3Bzgf@`aLy}g^(iN0hD$wkaJn1%lNBB@9!>sz;dRXpdTCBl*$Hm)?& zCS0h=oNq80AM>eK$X{|0&c_o`8tAg#7=>d)>+(5sj0J<~OuP`vnJk{nK?#m6&A}X& zxC{oD_xCT~65QBxW_NI4OJ8>|$kI7}l?O-B1K6r-S#xkz?}o1}?+pgm2LtUQNH@zT zv+*IE7#O5)V0C}@@|D4Lg9F{0gX=f+uUp=$!T#@n(CG&{{m@i_K!7&OZqay(j+0%P^yBR<5NH`*V*xOsd3`$(4VlgPi(y1)^j_)wB z6iKAACX2-q`Rp*unz?X3#$f7aFkiqz49;aT2QnK8C1Wg`q;ghD!3)wZ7%YT>iFg)U zfU_qTPg+E33goPirOKAqf^-`jGIJ4z$1F4GjW)2Xb=5^ z#+v2`9z`ijVrB|@1-Vp)rG<#4;38qMjLBsNK2{1Q)Juj& zO_m!?$6$p*31!|6946jC*$X~GG%naiG~lf+5L9M$Z=hqPnF~dR#m8H3JelX8q9sth z6q@~VN)4p?#1*sF+>RfbRXL+2W{G%5Pqv{iT~4 zmhOX*5~nkfF7RC&<7;IomxD>BuAWHX($-T2yQcD3m~LaRJ{{?0gKtH2YAYX;my$q# z&sw(TLg5%)StfYtOO~7Xz$Jh+` zXESjaFE^k^v#R*GOaphb>%rtSU~^7|3}bV>U?jS7+H~x_#|`lqYdDUJc~UKu^QVE| z#)Vw9K%5B17A^#Mk{8^me%NoS;Oy}!P{r>NN-i+2!$SogTwK2#@~#J}T}Z6tex6&v zxj%WFgsx@Ac-JznfH)$d2O}j*t~J$zG7l1!u5}FWCVAQnM`M%<%vD$eSr|`|Tw{kY zWSv#shGk;{mR;M>wCJc23W}rM{{-!UffdQM8;zABw)nUgq#7h|*Hx2{yvDKBLhP5) zoxNDK=xHxHF7bRwF&D`7o> z)nNRzr$A9zxd>)BB!0vz1Dq*GLEutD#rVn@?pLL^RqkKQY^%^#S)nRcah3aQJe82f zEuM*DR(0YWAhW7RcW{w>kc;%=Tx@%li_BYGWRG%@o9)I5`K4SG2DvzQ8y91jak2dl zE_S@i#d+^=aegIS7qhCr*~rBO%ec6(kBf^&xY)Uqi(NNzaq+!eeCru5cE8TWC4b`L z@)_gN*_CZve7lc}Ytvlp*~!J;Z*y_oJ}$0*fQuV`!o^Joxw!cd7q@)M#lAY29J8u# zoyWy(r*LuSQZDZ5;o|Nyxwt36#eKWDxc_=C9=Mx}2Y(EL&BnoHbMP>0eCvBK_U=54 z9;T{OxzfE`mOI?nQnto)@1v}-!hMg-o-Afbm34Y+m%>8>@HB!G$@4PWHQ;F!G+Ctc zxY=dg#PdG4`xuVgUzH)uFSpFOg@+e$8j!nfMSUxr$oZ^cF^ER=BOK&)1A#x~7=wDy zn@3a@y6+ZsD!zhaBsS}->;XJaf&p{?6pxVV<}BEZt%W3Tr&sw)g@ z-KaPNoA-Y_{r@w-4*m>~F}{<5vt{h)XU6$+jG1+FIm6v7CYXRcVfibR$NeGetD8OP z_KMpoud8CHTTQw~l)a>bEc%ZkgM=SZn9zQV=ivH8so10LdeZTFN*wg{FzMv}6WNOn z>)QaN8foAJeykwiXf+MkzxX<>ZfI6UvN zb?Mk1?tYOvKChSlHmvGhAs)tOvMYOgk;upPE+;Zqj!q0A5%L!MQ-ST%lt@Z>tk47a<+RWK?l z;hMASJ_cP)P1O!}^|%k*#<;3S+-#id=mj4*nC>-s~k8!*D zin@|sK3!Jx0%+Vd(|H{^U}fZQ;Y?Su_dnOw|Hz*Q@DE{|>Os!=9iEMUmvdZY?de9& zXV@W>uHu~Ewb^t#ITtq^s-nO---f7|jd1R0PX}zi8lMrTrDWw7-Iv z_E+#?f3Yl+OWZ=rq9t9dbe^Nq#djK(nU!&|(s?fIOXsuTrStGKxE^uup{EZ4OjgE0 z?o$qOUL3b5RqW=xIR0{vR0pSavU0v;3$W#rmGdGwKHHnDocGP-exc` z?x%b`aF4>J&l5C$8rh(qHpPCc!qt9B6Wzb;m+oKAckFMwtgOf{;-^EYFSF>UK^8!& z?NPbfo>LWjnZ=t1{PdLPTiQ$BM}|{KN-pQYERDGnQwLDOU|F8^yTH|uuf2DCMvbW0ccgye(G%o#5fN{ix-W_Sdg*VFlNe#-;s6h2uH(P=&KJ{&nI*8sADhrST|n*kJQi0eU&t5Xkiy`8;95 zkCQ1cx%gs<9=d`K`9j5Bo>OVxL+y|@$QLN~Cu{z%AbWZ3OFw&wf0gWU{5^^v{Jg^? z?cXH(4FX&I4p^5lZ4$!bkJ1S~Q{%rRehzVrtL_TMH2X!gMLJ*O>xf@k#?Ork$8|ua zyD2046(&FOdXan=ae2KUpD&$&d|dPM2bu^kYWy(u_a%+P_pdy?uJL)q4-wbbnLldw z*O9%vzGVA2za}Xh=ktG4f9DdH?UeK0tJq^)xvt?C z;+W80&TTBOQtZ+H%hdk08b3^Ylfu#eo#+J8nF>cgvR`rHdfYL^9{tGm?qbDWU6=MK z_UQi;YR?TCpGxDiU*YIqu6N&4xZ2J~iDNr4t{l(j6?^m}*TGj5dtBdS`i)|b{!gOz zyruDO;{Ty=^e@-VcNLC)47wHjm^ijm-HlgPh!)6sH9-EWG`@}aam3LN|3XYuXR|f? z3&|e$lbEFc{luFTKk8jA?n_nsN63DO#(zcpbdAgL?brCt)c=&me?WYP#=lQ|r^fFh zewoIfAbz99>!^I2#^t!&rSZj7KA>^gpNBM_r1Fn6emRw&*7)bt&X+Wf`*lpOY5XTt z{x^-^PvzffT-N`+#^0v$M;iZx%AaZ6aEbP8q4ikKpYIS4YFxG>rSVB*U(k3J@e4KH zPW%du`-$J6@h0N?H9m*<_ceY3@kccNRpL)*d?oRpYkV#7LmKZV{)xu75dX8r&n7;H z)U>XOpZMyk*oLhO&V{cvR~oqK33gdBbV*#QtZ|JV?|F70KT-Ox_;e93V`K8@<4=%qYzb^K-f zk*ni;zGAPA=S>QiZ9pXNNxzn!qxt!X&zSNnC9!qt8;Zxp^D9}0%T;fz^e-i(j0b{4%Eaet`13ete0cjHT172hOJDe^u{nA1Hkxpp0S3%K&BU9Nz>`N2pnS z!2{k^boNvB{YO6J%nR?!jl#=Z@(W>lZ7L4$eA*Fz7eHWqdqxBkCo%(X#+iUbDGP5A z*uHHhJ{pR|ld+VoCI|4=5xl)J5{wLw1Y@Ci!X7u6Pr}QeBO2t$n@r_Q@2d5Kr*H?B z3BL0bg||ZCH6Hm*IHCx=-=iSworfU2+=E|Y+gg@@Hw6ip!@*bvU))jq3=OcHL;Y;p zjKpK{A{$be7ltGk3NvqZ`zV*rGv4_%7jHP5wOts_@31vSy@ACHj{FelWQ}89H~{Uy zEF2))j#)TBwhgmzfNU#f;Q-kd%)$Y(&6tG)WCNHDK=)Hocy$(g6M!OW{HT%ZEG=VS zSiBGSQM82Fd`#;Q#edb5ungJKr2vr8cG1#xSvh-#mM05-KG5S| z56mh4@G-`}2I@P-zsVs!ew(hx_rmpq41_J^D1MWTmd1JIPx%&N)P+Rq%sSx!ETjFKv=#?^{R!T@Xong&WXyU&m0}6K~w)lL~sr`M}U`WICQx7cSep|Ye z>(4=`?-aj|e)_T>>ZnP#{b`x_kJFD29;ONyANTKi{P#ew`^0z;P<&mdm#?P!`uus2 z>Q`$OWKqhVGUNZ_(x0+nvr5{E&zI2`O%rZ|hsUY@VT*{2?7zhKK}DzYH%vcrc!Laa z{N};GtS`^s?G#`7lX5@Zyxplem;IJ@HlE00Z&`+aMcAVjGfx!^KXZ$TkUvkQ*4t9YfMTGSDVYXbK@M z;?j(`w6zm=%1M~U5GG?gq(fWN+B2NS5T=h3m=^vpE%Oh3B7-xPF=q}W2BZY4|9#iq z+u9Z~IO+5p^N6jzuHX9BcU#~3)>8hAWzRq5{hH(U+w;EE-{eWfdiiR{oK-KZTK3In zs-9i=+>5t8_1tr}J$t)j?l%{Fec98?maqEy1J6JG_2-RblqmmJ&8q$>4?g?C>Ia{H z_NlMG@Pbk9>6#aoz3{@N>Ug zs?}0ob?mNx^JjP>79r}ajlKn+Sw%~^5cR>4qJD$Zw_u!Te7-A16gO=e6Gk%)Oy~17 z%5~y<&^oe(?`)%a)01JhV(-}{MAg-GmCd~m%xOk{^&Qrwzn68bql@`H`hN29E6-#! zhnHqHUs{rda-#rGcJtLu$@MDWco;CLiYH>v^h7RKi26%brR5^}`|OaVzIUvscPtb2 zs-o0)zbztXQ$-~7sE81bPOD4868(vYj6yr5R!>9~z7e5?N_)XmqQ20o)Q3>MTb9?# zhRQvW0!6fjQazDw^rdciGMuNV+tfTyyP}LKCfvh>Z~@14`NWGgL-r9Y7m?~eM_c_C z--6IDM07JeZ@1}YPjjK79x1$9{?V)? zQF}xYRhO*p7Ip25ZJ}YJJqQ>(?-2E;tr~1B|NCT&O|SFup~9Yb{v55kgmGn9F|J|2 z!6*;#gYhb}eh)kr8Djw9Op*CRw0ywaavC3&vt!IrjB%j+bk@BN&J29BUjygFhe0nY z=C=E7PlWUWat6IT3OaZM^zbm~VoCFrXBIbuPWotv^KZbN0@(PTsy_)U=0~R8sNbM9 zU89kxQds3YY7?6k^{`FsRXitb;(#UXq)qf%)K;5lus(>CE^8xN#$R;jROJ?*VmqZM zP0GYBMLD5N5@NH(R%a1@ixVTW*cvU$4t~{Y$Z8@QRn|Q2Jn0bI74?`yw4vU4yjb%> zc(KmL_bb-CE{ABct-|+)q`aU*bR@a(y)N0cIaLIb)3&FI?J251RqRXQ_fsh<(z{af zdQnDYnWL)foI{*f)efZCAH?^dy$e7@cRr+4RN1y$mDOsKRe3pWhgE4+oO`WGhmzM| zRd!m^@I7F$`K`)Piw`x9T5Tt-;+PeKIAyhktV)ny`;A9y^PEL_PDQmfX<>`9PjRA; z14>@6MY*D+;d_(C7P2UNWt)4gwl=HS$A%7AZ2@$CO`B0gouoc3N<4r$s%%%p9(1`! z8Natg97}q*wM6VlsZ)X_7@~Jii3r=(K#4f%NJGZv)RReVC8A@vvje3@KHZ2Um%6h= zw7Hx+O2pxGCsINg&bks280Bn26Qdt)K;<#~-saC@y>rDMxMl9uOy!OZ*RrrW9xRe$kOqfbR|JUKJUEG$&rpr7>gk@Q3le zcR0WMMohVKzc?_GWx^w!r|uVfTmc7O&W+iO?#{crM&c!O$M`xlJH@%<0ns((zz`-? zID79Gt+S6Qc-elBy7>XI=N{GffH+#|vmoi@yh$hS7yf(mj@~a$-upOGg7cln?iaoD z*;Uhh&cOZR*nLjqp1RL-@_w=N{_#R|+%I9h|7CrgJr)7J!RPTkvq8zu0~Mk%sbJ@9 z%%NxRY_T^vD_kymlaDIMKB>OkTMjaHcHnriK~ zOaz8*R*sd6lfz~+DQ#k1IS}L8F1-$$p^*hA z%f$}Y6~#AOv}Q1)D$*La!PIjIz6K%yRYuu4_s!SZdqr--A z?I;Obk=8ULYX>@lBIbwfKGc)605*ML4oP2u-Z{N9*79^ZXA>Xib~l*5#xIS(SGDR(}; zH;jIHN1+IesZ*JB%TWbsy#=IEz&%N9hHbLh+Ggt*Dh{OVfa!6E zsX>%Hm7Nwq{qx!9l*79LcJBD?D6?nu4l7@e=J^#r-h=toJ5Z-%>_j2Xjm-_C;<0fh zSJ?6RiD5jt#)oVH^xrta#jegxD5yiV)`{}%{KSI8c7oO=a{O?QM8zV=Rap5p5?=Se(HPIDf^!#CY|6py+R=RPKu zI1i)I6QxhH(UW&|C=IB1a;AC$kIi4pWop~koP0a+H7DO1XW7o9;=Wm)V=UsCeG-qO z9_MBxhRU3K31a#DUc7CtP+4Jnh4UzjRJcyz(KUO1D-aaC+qoGf58UJQ;ZZkdkHXZp zO6ML7*f-bNh(}k9Za0(Y+&L%HH^frd1>eIxH8Y#i^ukRC)KgF z`6?SbJYVfV$?$yVUOZ0R_c#*|+&}v$-u66Dz_&dQrtxj>Lpx>nrxqMji0QpmptDm| zSxuO(os06Aw0*HBfRaZSdynA}T%sOE-sXp$$4DlRICtU^e8kDb^N)IhC=z%q_XH9f zAMaK8y6?%nV{ZW7Cm-)ZnTF~~Av^-rkDte5`|{kQD0*`F#9qAZd@9e!#HXEnJMi@r ziUjx>Rf6GFPa!qnbq4S_=aq@QUVyu&ChI6V*t|j}HLY-Rd>t!t_aQO3B8_iXR#bK1 z?ZnCk3txM`k#+#DC%-wHZ^xc>?#0{rXV=KQ=cWYk)>NC;hDXEmQx4-1cs{KakG(JK z8O}1H%}TXw;Co6nO9ft0s+oWIZ))?(Q0jm!SGQ}0P!#Yq;*N^yY7tx8oFN@|I+wyf_IxkBWsGsJj^9kiD|e@2%g{0i15rxX=m zyA%{)UpsG7G9FZSCMyr`r4+ZR;Uux$){vmh;ZQ*WA9b%yoU@$hgY}d$KkI0Y@VXA< zKzXTMIig9K63P+h6cx!~#npxsi+UZJ4b2)dH&y8?@g( z`C>ajVZ)u|qsBRYnZ1m=h< zL!7O1gn#Jl!*j&>p?j30b40`N#^fE9qASzcHb-pFa-EtZj%FRRBB^e)t7DF68XZ#c za`@&4S@@RFP*|>0T}^XD-L#X*LWE|dA-!#8*2y{I*i5W6ba)1u)8V2ObKPoDuUN5) z3iaV(pz^SMP^L|Bo=*XOAb~+A&T}c^yrl`>ci5bv6tTw!RUiUMPWT^AB=LJV*%?d` zn^S-l9iDi)9S+I??OW9ISaO(XZlLt3B8=62cvxkZON7##o707FxGU@udxpENxWs|s z9)G&nKEmTm7w1RJ4IsJkSi=@9^*WMw!a|c}u)xIP z2cJm?mS8|>`<8&qA8f;S3%0>#W2O3p~a#j zH4SCXIr%;8d~Wj+5gh95S|s)jV?&$MoS{YH@bDR3ivj8Qj>Y1@h$(H00q@i27mGTV zbMF!naD^1#5^*vkZSx}G%W{UQKoYaBpitKMQ&plj+u6EE?9Ea4E)rci>W)QXdv2q$ zd9k>XH~!QjaV|gY@M5ufoLaX?92n=s_nqU_6X<{ZlVPMQ?T;TO`7_IN*&smtOgc|W0M~~3Mh-6fcx+rS-!<0IK_FaO0-UOq9Nb3tSgH|1FVxOaca7= zqe|>8aUQ4=2TD}`B5}UN*;XYwN}a7$;#jGArAh?vbfUBKcX|#l5^Z-m!x-9K&K*G8 zj2ZaeHG^Osm|3TE0X?&_dKZa39%rCRobx#Mp-~trfVWHyqnmQ)PJAy{w=WV`%AF^x z#GZ;=d~dsF6*@jK$JvB2%_Y!B=jNRUTIQ-gjCkJ5jhNZ_s{jfXQ+ojPeXEI&hgPA@ zJqw(T7}x@5Z7P;A4_FoCza8vpO(ZoXT<@9xa+iIgjD{C`iK5 zVsnnOW3;HtapC)(oB)P|I!hsSxQch4Oo3!hJCOnb>hk^vDWyUm&gj|2d!OA%qKGn@=TS<;q*1(13^S!_;1 zk=CTNE6L(;5-pfx$!aJWP6o9r8BlFTO5Z#I341K+IV+ZmhF<f` zrDECXJgN$KkAkW=XYEMR`rcWnu&+3q1`)z3gZu?eT&- zML`94*A&~%e#oLf?&gPWCl$q~j1MZx9@h6+Y}+lcuAFeHT5LNlN<+Lm4))94O3A~v zqZX)EXBSE+c>w2>l7{boi!ESLwp(DiZMNF#tiU>2YOvZGt;&u#riA@PS(43%9{HuhcJw zA3OlRI(_o+{YIkWL}?KIYgNFf3qQ3g)NS^BPkS?bvB7bgU!LW=;q#?mHQy$x=x@Ec zZZ_JjfN!-N{&+?6sow30^jahhojFM?>}T}cv)iFe>j5uhq(HE`wyn{>+e5k?SciheGb54>@jp=--cr|^04Z|az6FGQVsa$CW+y*6m=yUt}Yehpl(?j`WD+;7VP-^=|r?29JaZ)3jPZ{vPt|NXWQ@}l7DMEP>R&BV*` zdz6Meq-^Q7sx4}q%pr_H=mkFIUaj@fu+$N9@9hc5!p9*KAA@Xs6f*LW<}1%W+zgqS zaQ|(%zSjmilY4F%ctXRwDC1!PxB!dG*rPM}n0e5aF5phq>4TShh&O=O;Irua%JI*i zu>eLZV6_3}B*^b%>>Dffk3e=806%@Y(h6Of0$f4{*}wlJTrc)*MbMS=R53MA>OQ5& zr|Ug0b=@*?yc@iLPbu{Zby>FRX%AJz$t?X{?nmn1Wqr{1i>UMdtDg2hK!2>aiOKmE zQN{YkzNJPtkb8PPL+*hNi~HoBo@aH75%0e$+M5AerQNrn(yBV#`J(o$HM`h0eBMh1 z!-+Rn(bn&JUK_7$eVsV!gnT^BePqxbY^nW(s~LOEl)o|EY?r(jv})rb&id>H&;se_ z>biS?+q;3|*}!!L=mB=a`?}o#`r&>nb-6>IPpQ`pxXo#LAJ^0M!2xtV=Q=V{ME;_= zP8s}M|KFbHCd^eA=2Md$f4#YkjD(E&KRuTfmgAq@B_c-5$wKg|7d#@m#It8$V>N9W z6AoG}?*^?3KH^>IQz?%P8fDq|*pkog!Z=K^CFFafykTEK)``jd4}W8|hbYsZMtZ*f zJ|-^x_PF;v{XM?E(atzM-)Il|SN<9AIr_U%etcZM(f^fa{|Wr2fbT5eKP&hUYk_r; zbFkZ^)^W!l1@0=rvmx+?It8-fkBsp^oQ5^4c)bu8XhVJmoYH3f0=8>tf@p_LT3VuP zdL3O#`}z-$Lax!)|Akl^TB(#q*QYc`r(=EbLwx^567A&%750IuKz2Q)HlvM5^c}Rb z-roG#W15|N<}pts0+{Z2OM#s@y4W%!?GEA{GDymo9^|cFHmp8+hq^YpGOaY4V~IpF zEs@@lmdGWyCGx@jm8G2jP>#KL#jdpaZtL*Un$EQP=)Jb~yp#dlcWy z75O9T^YEO=p5{FTUm2Km-x9lk8R{jB=XgyiTQCDLXQ6+{DpakW z(#jEtGXkw196O>ubjDh0v={sx=rL+-j^>ES2j47@1Xh$sRxJ9_f_aPfKd;%Y6(1FT z$C1Mrs%>^r^+k_p{s43zNfGU5L7Rq+JWI)4`Ne0-&o9CjyNnNQW!lG&Zm`yO-|}Ym zx51hMLa+8YS~9+>HgO@D%)OXdGZmT zTrU}R>{zNinqDI&C= zI>#xnC9fE`#&j9+U;CFEF<=$1t;d*(zLWC?;g23F>Ph`Pit&4zBPpJC=2@WU z(P!f`Hv z-&5N2PDOJFINfXU{G50Yilx2)q!@vt@f6vCA}vI`=}GP z_UY5Kk+e9%P_iciT57#an-F$bAR66&5jH{ywvByASr~W&zA}4)SEIlY~~x>+7@c?ITeoM!X(jZ^O@ILFo=cG`($OvKdrcWzuzgAZ-pi-7C0)zNZxjHi7m)-KynpRmjW+|UUwz_ii_e6w83 z53o+cTA$^60b>|6A1Izn7^afO7fIZtw=|)C$RhR!X%_-_osi{T^f&8e(L7y+zaUq% z@3MeC-T{382N-8-=p7N+g?d52$~vK6ATJ5D1Ahc*hyAl%FMK;Y&=&jkUWraIkL}wC z;HgAj;ULBaeI>^h#CVOdZI$z;jqNh*(M01Y_-`D?jphyh+2ZiMN_*%5r9JTZeWhx$ zxMsZG2^$y8#pgzI`BleTiMIc{<}EPRQ~JSBPvqZj7Lq4-S+>CL*Z3xQuZS4=^hc0q z-_r9Tdx}UC!G!|;n2eT-L+6AeV@3UYmQg)$&0>uLd6;jl4`I&iL&{5PgqTj+A+I)N zV|_4TL30Rlc9!Dk!MdUf{;EjmHC;BnCL&GX*^m(X9Vp)kxe(NS159rMOA&tdLql==dvQ0&xTJDKE@nI*F&F;6OkZ%G@LK$Q@{vcB6Nw;F*D!pc{lLC zwl9DWHKKaN+TbwXOhpy%y8WV5!@K4mqwIqZt;K7Sf3vJvJtA3Dnenv-{2sb}FCjEaETxoNz&jI9Cz=AoXt?^RK z)&LA?6KcFA^X#eHJc|4G#24*W;;Yi;ThNUdb_1`W_u&&5xoJlCNZXote9>Mu<0}NZ z>IPrTvS##5h1?fb&^`8^Xgf5&v2np-q;18MJQA{|wxo`xZndv`2lSN+nS3Nmv|a)o zML_wj)-AHV1k7 z5@00W{X@n6Wo%2AADI|K`dIRQW()B`Il?(=LLY9s)<+ZP3w>lOkQ;z0Zyfju<}zZ7+vd5v zjJ6Fu>%R@-k!{l+QCmW68+f3+3+ZhyX4@D`qih@Y0B}=@wpm`vI}@r)pydO!0En4}Kz@Ox5M;!2~wWLDWlR<0yt5tLwv~7TTE_ z-Yb*)(_r=!`zHMf-{uC`0jE<&7gO#Z!dNK( z#sX%-m`Gn9`hUvXD{WX)0;Uk!8mJuBYVFAx0GP%jam1U6zU*e~W-xIdK$uYp(QmNFkU;FQy;B5|4D#M&7< z08RoQqRbdEg);U>ST|8us1r9XD1of))@^Q0&N^CJAg>IYgZ3Y7j)TAv^^eHXWQzlG zwgvj@qP~8j-zgFN|1NE}7~cI^V*k(3mXxPx8>c<`t*s1vPWuY>+|PBH+k|$nohP@P zr?0YR3p`q``AfhjP2h`e*qnto1+wQVVjAs2+Ju~=vGAWH!U6N%Ur^p|=4qVmDxzI! z@U`SW_+#V~dQ|dX>KMs?2955%4*$tM29PVOfS11p{mMQEl6ftVSK#kz*lOhOWrfgv zpuHy8Vzk=|f3$JIBG8@#&w*^Kdr_8p+-$e;{T719Xcn&x(C_9*Wugnnpzpu|b z{O*#jY8tin=ixa}`|qR;vi*@_|9AEFy+gG2w_uEfe+8ZcwSNR_lR?3sCiXvz_6@tj z54#=mr0=~lMeM%?@1%3Kmq@Ou;GeH*KXG2iqJI3GQZB{Q-eWg_Bk&jak_bonAmJ!A z;|I3n5Yu}gN$jUj*T82b-VyZF4}VSYMVNhge$XN7m~qT`Fqf$WEpcAVW#aXV7xeH| z=OG@~j15q+SFXYz-3eLAJ><|c50=8Nni>MG)G~ZFEDeYL0RM#H7adt1iCSDeLd9C; zv-Lm68oHS4j_^XPb?y-D_6g|}l{r==qWPjUAGWJ! zLpUn;%n1weg1!6}em6cr;u7!Nv+Ks*D`ZsaVW58~b~+vCmh5{l0SS`;{T? z;x|pkd3n}zVXUe6kX}d+Dn7&TL5#lKgFlWZ*Q>+{am&4Uj?2h5`ZxCA=^J7hugNzQ zymz+d-(Hqi-w2;h2Izo&Gj8FRu)~5Cv$5A|i+GU7^v=6xg9fx%r;8J2M;5`S-Bj)= z{UvQ6wA(nssIQknI~iKH>YG@KPnUCkUFE$g-e^ zRf_Y-n@OGvW!Mu4!zNU(R=kEa@r9_{7I_MD&}dNm#ux}F7{MN zyf?xhOuSd4PU8rn&s!Yc&s1phTQ;ozGUzem;OP43nOIwwH;$<9*!X1l_q)Y$_MO$& zcUDUq`tCscA6rCU-yd5tdp7WnfoIDj@F}zgF!z7Z=f0zF?zMXoE@ADHN%)_Eta!%K z*GBNMayiaxXl)_NEi{#zGeEgnC^ySg?v4SvhD5=#e8T$h&oPn3({lW`p)Z#Hz3=GTP|lyu|jqfu8&E9k2_dv;`fc1*S` z8!!ZcR@@$JKd(yF$qDLhxe^###v+!j|u&l}k(BmpZb4JUDCs(g_A6rB`n)FI5rO&N3L!h&L_jO7B)nX(QsPi3i3%Ra=yItCM{* z8{yYUgqNC@dz#n3VkupJCvdvaQo7>1$;~xmMZ|@s1k185@5bcjzVc{`?UKexQtp%bKS!s&H&$F=JB^3@uMBN=Vpp{ZpN5@@7J*2!I-fADf$-r`8ZkB-iz24FL;2o zXOu&XQwwe-colO!^-YJU^+JDEqiz5(yy|z--++x(s~mjub)2s$B3uGvH|iMU4#JKw z#?HDd=e>vLazx8zeLUCjFL)O|L<#^&SzSpA2V;j$cj{k@)jVOAxCV$^dQ{hYc9~PSI-MvID*i?@v7Kl}g_9Kx)=B z?>v;Vf)+sse)yfeZ^KrAzjBJA9+^X0ew%AawFhuXyaJDM-`s_#I#uH_H)5`Ri1k`M z)>2 z#Cw=eAL5PP!<>Nz7cD(*8@DF+VG}aC5>mY1_f{y9i z_FFQy1%_gMk8uSoi$^E44 z;<<>Ca}4n_Smrsd#>Fv}1?NV;iKS9_(usfqs@M z;=;VY-}?Hzt7We(9WE|ZP2L7P<6IzUIShUl!^*;nLfX-Er+ROBDd3snMLRWU$KVOj z-4P3DE)Vp_Iq~59l^6M>N4p}n-38b#qP<-|m>q7$+F-1r^!PygTplw zCcu8P;@C#r>~>;Lle`KTYl^@x;18}@RPYXYgX1Kfa!lU0m1fQj;pM!@GMEeEbs6&4 ze;53Pd6j$xpBmFUksj~s0p0bTts#!gb_ii5ovAm)=(~}9WB%#qssSGm2I_2{ZzM0; zL8Hx}CCB(OoKq4lOVRIG@C0J&i)KMCl0O{F%1h@#-WFY5TC!BhTgfzzL0gZxiwcv( zar+Pv;k)r2^0t)kmxtws2jX?=6zUW5I^$?N#=@ruJ|8RjTpX!^PlfoK4n8M;Qw|&a z-GTM0Dl)eQw9Y>A_&)q*pi7Wmn$;C~zBKoaBu&JV4_eVFen_43|H#@6dRufo4io~I4@ z8SqG5eLSRVcYXV+c=kI{F>v{^s2 z$TZ%u$g_6qhbiG%)Q!mBxci>wN~{;MF$e!+x2WH^)zbXNX;J?=HoIdav&T~sUVhix_Bj{PF zTVdzF4ZW)I9NGj=b%S^O&@G&I=t;yriK35(Vjl^6GqjHikQM@O`OvljQ>N6tn%sAb z%pUA%$+C?9JB{`@{;`1VDSQYE$5(CB;315J$$*Ej5GI~iHp4?W2-7aKDfyRvS%Xi3 zr>pDcfF|w%ZQKnSnGIU0fKL|ZpKw1%Z0F?>W3^aVlA1*wtmT2OFjNEJx{c|UEnjs1ZAlrf_U+We|K4gaz<4^ zU#RcjtwcIe594uB-unO}$Len>lkv~~7A5jg27L!HdC;f(ArB&mYfU5z%;yOqLm}62 zmL?PDV4|Wq3i-f3+#d0>)7YyZJnqNEh1Fwm76#+%2JHo2axa_?{Tv!6N*CiS9`}rJ zbzptg|9Tnoshyn#Zhj7X1#(kqrj2ZzAvWyK&P|AoM_aVNqbsI?6-i%^mso3r#_93x zpk1cRb9|s>>YEMVt#~?)@NB70!?gc{sTxgi-4NW=F(dR3WzEs`N^=x&a8IcqOGNTi z-^@bbow4SA;Fvh~66bi|h4*UcO7`u&4SA3^-rFFn2-g=W(@%jXf`Fa*{4kyLhx*fu zbEpR0#jjUfCp^t8i%Um(Jdgn^N6_vW*|GwA0rRj2u+`$&HXpFu`u+0oyGrV|pCbLY zNdLi#Z-!T5PhdOJ-of(-o}`QU*c(`nvlY~L_o3c)!1{e<$dUIjlj2g-Gw$>=66j72v^iFlRyh?%GQX#+WkYf($wp8dgOMNBRVpyYb z?PILtL$|}80zKI~?k-i=0>?SHUl?>wc`4~^3&xM{9XS6Y=f9n@0=6R3_)b~CdPbUB z0Ge1nroJ0=i?-w$HQ>Ll9Op|&%V*vf^<8giG?AVq+GU&O`lRh!wLVpxz4eOlG}to5 z-a|>H@%?+V%Ol^~t<*oaJFVUe9RR!Nc#)!>O~qO(2%Nf=)Sh#Q%WcBg+=KpAPr5f2@d=`Ix7lA&$iXyXs@; zjHi(IJGAv*?dlsJgP!u>Q=$Lqw~Bo$-y31G5YF@9Ar-jm!wbfulqN4Ey&LQ6pj#im zsT}KO*nk5QP6Br(FSOsP#YHTqJw+VV=<{L|(|LASTQ6y`J>cge-rHdKMG$OJ)QNS8 zxl9INcK^LnTTMK@tJH2lyGA>pFP=A%ZJa^eZvS?)zWT}_|BR_G#GDsd(RKv7iDz5n zoSDX_Vr<>@VWMfZOKTqbpR2IoBEN{;kRo-sk#h5qZCJNi= zOv;cK9NOeM-N32r=T`JHdhq>(uwTx; zDCc*Nh5e3w^$_;G+229D=Yn44n3u)yV-Z%#d!#?mLQ5CshA;w;MXx_8rpDt4W9;*p zvP>!bRo5#+8jH`Dc>WoD6QB{wi#&^%o~Vq}<+2>^%0Rgw&YlD?$12khdnnJ&QwEia zX^2gE$bBo~gP`Bw2aqvvTjS#Yz0Z5v?bV2t!x=*0DDFI$X77Ic6;I^Fv9|gph}&u^ z+PGi~KBQajRStBPYXtDR6zz4msP8keM)ibOxMH#JO^8KVin}6!yQ(h(!;eSe%oX}C z90Uxw144_391(+|1vl>*=gAV`SK?8h15bgNW{mx^j2+L=V&QKQ`wP*wHhw*Jys&@l z_!#6fR=07S)^~uh&Z(U=nIV0NoNJjTd0V@) zz)W}Dn2#@m$3Gx$&kr2d3<8fIqixQmCo_h}v!De7kAvwqA+B|~VuxJu>NHlE?s;|A zC~;xK5K+ZA#BYP{<^skde5j8SogLYBM#HN)29a?FPW zdHrLEh>uUv$1l@8?U!&4yeK(VwleOFMghwH31x36!yvD&kztb|!}7nH3_AoJV3uK> zc&Dv=Lpac<8IDA9`m{-ZfwqcHLq4A|$zRI0AnfAcAEK?$$I{lzo+hRq_;WNfkgClU z>1p0|=IY)*3~sIhi0k_W@J}8i-B;rMN3fA!!kQIldgc0zGELRxnsMH1oV{b_he?R* zA15M?4xC@YnJ>$B@h;YaGu?-cb6?t-V8-?|9Z%^y^STw|FlZw%tUqmdF{YKkvjGo$ ztNUN3FCRMBi#3~OgCLd(d`iAtZq;-M*4L29+L=R^BM#Mr9D`OCa=+BBavdU`ADiye z?)f$))*0}h;x(dm=#m3V)~gfDO08N33-oSS3c4q{E>-3Yi9 zZH?mHC?W^ZPBr+Dy3V^5d0eAx)z>m6n}WJ(uzJXslvsua^z(-OWatz9Whmy><$gqq zx0ZO&*TCd$p1(106F=4f&O-cE#tPdlUgz$@83{w@23=y>(p1D#V~xA?4pHlY-d%c& zs6Ck4U&rCReS)*o{dMhS?)M<}e=a^Z(zW;Ndal|Tlg|$99VL>_gXufdE?NuFuYC}G z-=g>JgFlS(K|NoT^40sEj=GiTw{Q@BJN3RBvBzZeJr6!@W88^!cL4Fa6LdZ%9m#WF zyZX~z9_jAyKzFcB`sfaRbA#>-8R3N=#~g#ovl>~b+m{~~$I5ZxZpK)CTnsC5PMRNx zu0uGV`4`c(lsnpb)Q~&ISx?HJyC8qa`{eE5Ekct~c&FcHV~421UB%LGa~e9Q8@j>2 z&b@FNeKzll(wE`0q5s)mA?h=w&xUr3=9`3kVytV+l}%Q8E?To`aTD&F#XIo6cj<2;eG=yx9aWElmr--B}bSTD1kYV6Ch zPH^0tj{=YID`KBPh+3=iMxR_gjkDcmd;W9ic|YWy+D@6Q;U=^RJ|wIeLOH+ze6FxN z`mf2czsLTvU7~#re8km<^6EoxAr=nh`^w^7uHVrX%Vwdh>}Nx)AK63Jbi~hn=#>B8yR=V+^`+kS$+|k-XyYq6%gmAheY15 zPNOXc=506hgNi559&j&*xFueVwb$wAv>5a++h3CiP7jF6Uxmbjvagx!1O9pLf$@Ap zDV}R|+fVb6YPK2AAoA?sCBsL`^XT;&pQ_NK^pU!d@BTjIE!N{KM;lv(Z^H1A8hlg` zita}|ZJ)kq`criOSkrp}-nD$Rfw_p+CtjWJj5FC^MtAaz;g_8!*jz0ZIk#MYW=dOt zbKB2Hk_CFPyGFQ&dun}HH#7edX~^ssKpAVPbK&Wc+8P@E-o$O?@_wU&BKPR$KCK?0 zE$bRj>1o|}(yyI?Xm-5bW?|OzLA}lE(m2Xn=c)@08+E{Or-2TV#N+|tME-Kjmqw=p zj2C#3s>%GW;)fwwF;JDF(y`^{4y{=J{( zL66eUp>CL08o+%G33XT^+v$(}b(l)t!2JzD$m%{F2H&Wm!wlYtr}cn-SA%f|@5|77 zA{w;5>?!4$xOg1)8$W4z)bJ7R&N;RDu$d&S$I%u2{zhyV<>tX*@D-6Ku!fZPoWky= z4^&NuoJ@zD#Cf&?=TUdT0+A`*Hrsvba zjzxjpb`3mnV^IefOXUD#@nbBH3@{dJiD&KD8;zq5I%l+4;Dvrmgbyq7mvfzE;tff+ z3g~utV!BnaMxp#C?e*DS`W+)2KV>==cJhvqJnVZKbQ_R1oo4e(JRwHVm~(dt&QO1b zJ5J;0(~Liyt2^{5&RIh~8uNEX_vzI^4PRfl+9Rc~^< zVI2ioIbGncJauIwWC_Q+TW^bY4g2iZh5^&$`#&8}wxWzR^8823<6wgQ*G`#<{pOV& zdS7Rdwj8zz>8!86IN6~7o#x-qvx#YjPg=qiUrzTokxng>ac28{%{B{;L;Qsz7{C`K>_ANc{Gfot8)$oU~-|Om!Npc@@I_<7I zLF;DU+4a_DhK`6<6G-DF6bUa|1y&e>`Q@7W-Ls+b=)Ir6ARam-D~+amM-I%D>u?Z4JM)3=~H%fo#( zY^A8p$GWwT-UrZC+yizii$3-8eyjADEHu_5^ zHy}C1$CD9Ynm3h-S&{{vzZ?D<;Eg@8X(_ObTc{rccOE$oCy;Uk`Q z2kxj*v5#1QeMI%DRo+V<`th6DOGgXbALB0W#{Tb8+;ae3iTm(W2YhE!*5W+Vn&rdl z;c(s`fqvq;9($ECHY$u*zzF#@G3M)D#Qe-d?9W`p097Iu zXbxf*??LRMRmLu|9~CtJW9$b8psN+|)@Z5QRBinNp7DPTXLU{Yj&ffR`%@)FXk@%mJIe{I??t?+yKqrB{AlU@GxdXeWY6B?Bf)CTr z;P*x7L;X*E4F!9-$nYbZVSz74!a`YPtc~bbHSbl%mpAqs4f$q{-(c*ZvG>U{F5Q5m zPu4Aitb;uLGH|1>q74phZGre|=^Nu%$Ug=D8J&v7MCP~Ueq&DJ{l?CY8Dnv8BE}Sv zcS{C+GvK$I>0V>(Giv_t5r9>;GtfPi7Y@!CJH+#DUpwbF%)k#Gz3V>Eza9F>3p!)_ zm6Fec(Wy?rIS@`s4~WH)^G3NQ-?8p7@I)MRj@06x%sAjaZ^s{F`@HPS|HtUm3)qun zJM527{*DD>S!sI>$A|kHgp)Dge%=E;PTNmp9%H>#d{XeC4Vj7$Z3Xg+1s|r%^M~lW z5pvF0Q!$U}?0AebOe2AH2Uz91YffxLcD{Qk{KLd0S^2Ugj zy~wja*4R0P>)%bEa$Lq3LJvu~w8?^d=tWCQo_ zyeeT=QLYKNvg3S1Gh%@(&{@POW9ErBi=FNC_g_j|!${7cV_qPzM*#*4X9}!YF zXXvqzvb}%N`jGu48izUmM&mG-z0o+#WsP>f;y7v!>G7n)ARF~PC^;U(#(>`L7u)$d zVz&OMJ~V44*2h>g8NAH-&|(Yv_V~2>X&8TiIs5kMr20nS(%6^lR}bUq*Ei^fXBdt7 zQ{(gXF+-k!uTTy=;s;!uXZIh~+G^aR7(8RG--Z6dcuF4n!qXnLWc7qB7$@w~Fy>fE zy{Ea_lC0(Dl(koHOs@C7uCyzul^|!)um&`2Z?`;zn4nt3OCz3B+t-61BQ14p%^Kq# zTRHZ47@^Y$KVWLXIf~W*@dLPx{d$SxuWM!UUK7(~{@t;B->YK3Oj{O9^T0k!*p6wg z=!15bX?HAkLv9r02eP|u4MvRJii1DI-K>P=p;)_o=N-iAeX%t9yxYDj_Wu|kKk|0~ zzt_yKK1SwCANh4~V9YmUq14NAP6&sT5&YdSZN5WHlX!yu0{+Z%9IO!S(Ws?4iuj)( zc(W6H$#%RyMV%z986cNJ6Dpbu?X)EvJ2Je7r|aCX+IBR?Z>juBbM> zCeXL1en(yC9&W2`f}V(9`>(^k=gWw1`wztZnSFX!tU35C5=YAltbLZk7rG5~S72?z zJ05?e$2@p&$0N&a#oFgA?s#N*u6+{X=0>~>yO{H=KB$eCx+Md)U;%VQzj5j~mN=@_ z>QtxbajMrVTcec)4^E?uaQ};?mgj^i<4FhZ@1!=nmkIcNM7xwvpexc;!m%WpXUq}h z&OkI_v?cjt063{n-`iXW8Au)04Y{-%GMG9{>a8b4gzFwdRxyn<$=^fdZ_5~cMGqDB z^x&LrLVEhYB*%zH@d(y-h}RVu$72`=^$7VW^hvbUkNp~423N@Y2nqN9pv?hT4Lx9% zMa-A+tfqX4PtY3a3_MzN8gk@Muz|F*6r>_q(jjA18sZY`H~BG)`vceb;vv@6b(tqqRom}#~vf>^gzb6tsZu$-@8 zvi|PS-Ul;JhCVQCsgTLn)Qi4--_+XlJ+HOtds2U2uJ;L_NoW}MxdzFn3lstmq7`Ax)r?tl*qpH;vq zZ9GHfo~Zyo{4?|wZJBh#Z=&73LO%j+Lv4LwrOyF#t?dUHxC($?G+T3UXBtA-Zw-zU z;6b~*OF;U5ax~tPwx_OxSZ)REPnMep8+0D{cOLA|vp6%h5wJRR+mkdR>%E}qF2YJW z*fqwt;0(s8>3eNF(niMlP)RT7Q__n*9^PFp@o$!?(6t+$OE52ne;8*PcIC$Kyki;m zGa&o6;6vYu_PZ;Ie@ny;UB|skv5fb}X}=}XQXSjJy2*D( zx@S#w2P^AOdazH5adzu_*4Kmg*T5~u+PEYJ@4O{3cnvyjn~5{MX!C&L##WbUzl1i+X&`0wi`oXU6^)qi?Tt8+xYVd2ixS#+wqt6}pz-~l;a|hAqeR`k1xv@Tr=EnM5!#g1;_hF+L z@*8IYTY|o5YXQ^mW;%YynKl>puw>e@SX$$Hy`0p$S~;nA4VzDoeWDMd^1HZKHGvPp z_nl~!gyCOeFwmy#csZ)UCSlNQLc$=+N*J^>-#WdVgh96*X?G=nq2Q&&FjTLNRxQE4 zQiys%;zIK`aGmB`6V=is99lZzkYyztTAJtEdN~P)mNpPBLf=XZM;_9pZYm=#w6k^U z4*1x<2fx!?&5v^yIGmgRLH3F<{sk@AlG3aeqDL=W(Rr93^}`j;Hi|$Og4L zS;lNzp69*CrWhtU-o$=7e;+J-|NEH@866Ye(} zK9etS#FVVV^c6Iofm|ZP>d6H(e`7+Nd=Za^9 z2l59<`X126&Vt>=GY%QBu`}hKmf7ETLf&ykd)!^bJ<`?iAv}IHnzE{AF{V*5b}2j z^eyMxmv554`7!w$g3prncY)cjfi$_#06UN{t4{d9)~;#eIZ5ne_S-+x?8MlfCg*D~ z{wLlea=kf~{waN4-G~o42zm`s7Azu8OtP&|lLe{~W1l|cdDT9R`F{uXWgjXz46cEhr|pVHHiGX1(`8Sm1w?j!n$1n$C@{TO(L zJ|(~KPKtt;5nKL*QX8tr@2Tp1v9&&$Hes!|Z!dytUE}@(*4uo=^xKGW=SpeEcrjPB ziJLHPFV2;kWljikqZ;`Jui!T>K;0 z#e0G2J%ryOn`nCX;(Zd{4R}Lp|NffL-xO1M?6=DLMtLvZ&G6A)WPg46@xMKW_WF%4 zK0XrpJagAqKkm$32>INT?#qvhgH(~Pn)Bmiz8Cq7)i7dVv6i^Tm$(b_mPqCY$0?F; zF5)R5Q}DYG*#E*E=Gg!8fVVqS?~eI2R+@YosdJ=HgX_W&(xpG+4)`-R1^Vri1n<(< zr?Z46XD8_Iw`=eI8}X6O8{$j&@Nw4ix;z)J$K;(i@wSf6%fty`lyYx?GKOE?d-J2s zyblz=t#hFf^2z(_vi2AMNolWyo${?;EA5m^lu2hHn^GxHAeW%Cipqe)>*2wG;YPBV z@dM`AJ<4X;u9VFtIc3O1*YaX_Q4%@nQWS{4=tA4({PI<*OB1`%P${dY*k0 z+^zA1v`Z!5Oq< zTnp!zPu3TYp+A%pOSQhp*R(VFWIlB^pR%2A;Eq4QEx*^A`g+2YzD!StACZ39zIYhX zjAjps*OWuzys`$(ud(v~zxE${(f)mzo{T!iQ;6vMypzk0I6Md9@lp|&=R|zo5ZuW% z6u%W=tvBB>=R%we<71jOWrr)V?&N*jQg>sG)C8HL#mV6AQtET0QJ-@j?bnTy;l0h; zIX|}Xk{*{K*KK+m=Jl;PCPVXYYwJ7Of&%BJq|cmkU)qnFz0G*KT{iFv_v1F$YI)8H zzvokX5ce>%PxXJ&)&tfb$611=ACj$&ZbZ_GMpPdn|_IhV`&E?5k(m4p)GgSmXzTog&`0+6N8#iTn`+>!r*MHGGbWafwox{NQ9Hh5~$ zMBN6zRodXrq6yLlA5v5#ZE)smHh7`5!JV+b?L|!-FV_EF=+q`XUZNQ|%|X1xdfaQl z_y?ZP>Aqu2cK1lc@R;#?tBzmz&sZmM%!Fw^jPiQS#3i)*9Oh%-^}mKo`r~*P)f(JU zVP5}h=fo5HmB9)zyI*&qEJ6!eU74vPFq8A|#Yi2uyAXYc^$(hC_u8z+GKY-4Lh z4OYs5_%x%gwm+iXE5?`u{N_B?n7rqg>q?Ec9DqB%KGvdoyr!$gD98Q{S~JU=6h_a>!& z(rA|Zc#mTYr&AGognRkl>BF~G;+y%Wt=6J5z@;`1xiX#b<9-m#rI_MQAzpERKjO7j z`j6l{N`%+JjE!qe8J~os$O{$pvxBVnSf=+Ecb;ByUkn*k@`e;e((-%x7L-3%Rqxq~jKA};e0 zKSw$o3~b&nG3I#KIH$|xzAne5;qVFB-r)KkOnbPyf6#ayOnXyhd%Umn%g;rk@#dpF z_a>apx|2B1)_s2(ZOSQId1hdh0e7Qtz z{}yda{=gjCAF1hgPD`Ez!&wo?1yc;7Hl`ctTk;;|rUpZdW+}JVr)W0O{|BG)X~=%< zo{N}lHoqHj6EBsDss9As@Wmi>1MWn;u5S1Q`Q&}_{o9+AJo87^x5apa(432NQA2ifJ>tn4R_QTGa%nq z;_Qg~P5mC-e^hFhLCy_Ujxzr8n*P(Y`%SJ%cY)T6*!Jja_&1(+NE@_Qxt?(24o}7d z+eXcQDKx^jAS;P+!RazCxD)FcLyogQ>F+n$G+bXA{vpOa8FU$oed4}MY)^*$oq^4( z(O4#QsvCPY8omtrAZ+vlaXxFXSEH_Vk8n>0&Y>3=`#B6a31R-d_|Ch~I){xe#&7av z2CcXBqaDCrlt`8y%+To7koBkKynVI0AIZAU{6rhi!1|9eH@@G)sGDf63>q?Is3s3@ zJg1bkTlF@LHb}?BgYh2Urjc%xi>DK|iQfkToVnM~lu@^To7a|0)MmBbrqPDczwsX5 zrjc%xOVsAQXfvJ$h`V^1#xZ%mL|OXXg4X_XthL);RjyHVg7>7vx$Ao`ZpF zAU=$({WP14dh7GwM5koJmX@;3>OA^j3lQ&Q=sm6p=(pziM*4{9 zTjE|4pY+)d(Z6#&;LyLT`jdC)Q9rXR{Y-q)M=t%mQb))9w!ad;5=ZdwWBmIJ|E62+ zu`IGYZCPvif#oeriZVvwr_J)d<+qlhg8#+?Wd0e?48ec%75+;T{HK+RmC#BKT&{n~ z>yIQm(w*7j&Pn|APrC`}H;L#b%keM9iOA>AB!L%_!4oOq z4Hdp1;T)1I$u}8Zi7fv`f2BRbuTD zzEL>SYfdAM*5KT6(+&44vamiGCH0mZ=Z09j!F-J-R8t!EZU>|ZbBuo?nz$xkrwIXh zNjkIpwBHaQy+NO>T#kE9xgJe;FA3J7%kcXV(ytBKtNC>@ie$_a?k>T(BYD@tuOTnx zxIl}>Jec_evb;$9&4VoHLU)T{Kl^`EUdpyYxQCAN9!_^x0C?u!gE8N7j0R1?XKntS zjq0kOrT!QVyG=DTY)&F66Def-AZz;NAm-@56jrOr#!@10K*jR`e0)E-InFl&>mqmP< z#D|H#@w-wIW^+AR<_5e&8>dUIYckQzTakKUE;@h^80n~L8x#ZUkqIu zz+QV8d$`o6m+{+yp*fl^b#-WGT|H>Cs?qX9m}MF_jt;Z$M$2R2 zUoKaUYiT($?M+KY&qc_oUAR{;h&HtS4OdI=Gg`Z$^;qu%$Bd!ixuNbk+8iCMwm_ba zDvDM(uX}bV`jK_5`lhzWr~Ys4Of-H&@geT(H6@FOcz->|!#zIt+SJjv3W973PmPl3EGmiv_oX#)7B&a`6hxKFqJ|LnaBd{ou7_)_Vwn)NA@NZWYt^<1+TS$~tqs=)NHGCwJ7lmL@flhPdV9@;+S@8o($-6a z_TC8EmePmqz4zw?Y&%JOG{|GZ!})*LKIhDw3=)t)3Cl~E2=Uib1^~;^Kz5IIk0kcrn06nvc`g<=Z>VIs4dH-fPahmeDBefYj z&MeK}UWTt_4=_FC4bSu{c_{VRuy^b%Q1^Q#5Wk`DdBDP_nRpyF ztxCDa)uxr`8j4=%`=Un;)<133Io$qPfd7m1PsKM9b*6tKQK#S`Gzh>;!XM~11s74q z={FjI55zBXj(x`4b*f+H8elm6GL>AD_E`6t2;4J)Yt!6^@2ITl?e_q_uJcp0c`Rk( zI41dvw!i})7caS^+KH3MQpRT-k4oZy{4LsU*MTk*$GQRxcJB6CXHR;8<|5z zhdex1yGZ5>o1aClYRnZ%zS=q*`B@*enmT7WqbLPX|)hc|bWD9+4o+%w({1RCg z*kwzo&n%mb%rj%3s5CWia7Pexm~-4od&JgeuGJEA+_b-Vjx+bE1g^QhO0+rdXU5vZ z%lBk|nx*PIO^W=E7$ld%yUF`|$>aB{$k$cK*RP6?7Cs#Ic^ZkWZ~}SR;D|xe03IS= z#m7;`ZwES!5c>H?q2AUFP=C^}hUMdOG_s0>6lT*rd1POvM?(kLH@F#SA;W;(;6`TC`70$J&`rz?6ZxeGs?0j|{0Es!Ur!%%x?%LK?-eaCE zaICcg#0`*pxrI)4nH|Iq*oqEVoeF-cu|t~CXtqK2FpGW@TRLZA{Sp~-k6`2c?fb0# zXIv}$dKanr`0TOs?Qu{yW9v^r#;64f? zEpRh_Vi^)!zw%~$+Di1Ls_j!9Z5KSCh0_00(4pok?yp}ozOnm4t-pKM$j0jZ;~SY{ zS`W?ggsQoll)&`FPw>CkGnel{xx9Uc>dG|y8#cDl$&mA{B zelP>QujXX&#!`MYt4D2;`}>N}>+o|~YU^+^PIfXzdPkm7xb&=yO`BatFE%##z-Vp$ z<`%r7syxR}{0U=E{>kEf!au#l$QIpl01w%6Q)rIN68ebz zH0fckXTur9SP~g|p7fE)@A9thO?@qq=EwG@@|}@LV@>vG4(HaFu^%n5Wb$}AVKc7S zS1e+UMBSqQQJ2_)x`BTTdQB(By3bLs!96ygb!P?*?y~W+=HO1#+6e282xkeUjgb%a zcIM!vi^)^)fdtC>9A^ryr*L6$}(pNi)&)1&AlJSlSOv0D={PDD-xdt*!4MB(lr zlNZD$Cv=tj@sisy08e5XC*yhG7yXtEnlGS^fT|dqHlk&|A3AUs(FvrPUw9M8;jh19@#Z=z`f^L>JBaB6m)Fi z{w&dXj;zZGMUHFGK=hUA*nlj4gm=qpE}j?J$hULMSc<~W2cY9S?A0}+*hXVb9LO?7odJg+oJC6 zqhFAj9h_;pm~>(VY&*=kds#Dy4Mt-4cCx_so^Vaqqtf{u5mzN6+l77>1r8_LjJP(6YHC+gA?FM0TQIa%V|AF4f!ATh?a9 zf0!!r&#{iMbRTp-b@oZlY#3|Gqm|#&`Z;erKquLXZE1i$0xTI%%wNO-Vcamkd!}A~ zzsxI2UZ>D`Z5>DEkv+sNH)MPcf|JyrtXF4zIZ3Zh#sMACGj-AZTTX++DS9_}Y&d4= z^}2&T;Fi*!`M7ni=y5at?su^d$QoX3qoXHmyB9PiyQ(_w6p`eJncd7Om0H^+t(-c0cD*B3m`iR_cw|&D$gAP$z44Ij88o z&VAj&@3?DA;6;2K9;v~PJAi+DHE~xB{NvGGe{Y@-dU## zt(|2g|M4dmoi=|LI;pJ3q^$6~cg6GxIq-bGUY}jCa@vHP!y{@xFLojaF5P8|%=<#v zXI~61`J-j5R7IsexdUJlXZ=oxV`S@+(AIAew~YPfw_O=E3-oVgON_+WOz->?*Sgwg z$k>{6$1jcb-u&>r@!%2p* zdE^<2Uz9D{0Y}p7$8)y`F?e>kjB1%bmH!KCP?47{=zCdNo3nQy1N`jc-7Y+quJ!!~ zwvl_%jJa9fadQu6OqrWCDtGP<*RlYmNRl2~LU~&+5*yw!_wem^vd%=0C=^}hu-rjkEPB59geLrmB~A9cZNE|B7m<@a z@Jx6Jo@rk9*=QKL7{GV(o}>$}H@hdB`?2e+y(#t^WlW)uT_o`rpu-$H{(y0E(MI%| zzMb6ZEjUTO$n)i)X5yy^-`@X6;U*XF7 z$&S17D6pUhNBgaq{)$HCUYy9vHP}tmyw}AXdr1MLSp|O8Vo&Lm zInB1IvxltKTEu=9JhQ+dL4R`{4__*q`9S(7+Psc7haI@e*i?0#W^Qrvx|4ounG0xjXXwRmyI$h_;5@OSk8&)5&ywFA%E{9Dy?K&%CwbSB_r|FA40NgI{UJN=V&+yqbE|iYwo)5k ze_7;qXthjljIbx)EIfn$BKl9*ZN|G7o*0U^Y~E2m9`q$^&PT*WfuZ_QV8W{tLYzZx{TrP_j-a!4TCsF(oj11A*ITv~zpUHP8}MO}aUlBYaK~2* zZItm98tje?$9T$SE-gPgqE^OA`G@F`VsAT+ABW|OAaa>l_w9#}JrQJ&X(KcD?Yqg> zvi0tG{CmmMO`d1bePv#h`K$$=F_;s@##Tl7yQ|kJR3A#>m>dNz6sZij|xczIN{4 zR~&Q4?ZYBRZY7`OVUNA=9g8OgR&qI+pPh6Snh9-N-8V#gDJy!5(4g0%?+p6NNnaiM zZh^is|D6_&cOaZ+k!4Oec0Y*^xD(D6@Yz3h3FFiBACW$+dREEMcHhd%D0Xb+!lMasC2KsvRlY^&NAbIobb%%3m;_$)$ynR_=o}K0&K`62{ykxVEU3aKRGU4C1={2;UB46*5^`}|5&U|?Ej*Nip;U(%|_;tzA!x1 zLOd$b0ob!C@C`ABWc??1;%!A&D*Y$Vbv{e?T!!9Rev_-#V1L41M{i&qedo&R6&t*x zgY~SVg(gLu?GxO-F>(+;r1PK~>nqs{@VY) z_NC>1Pl*%%B(YMR`_hNm!;(8&dmMg0J?JyCFa0QOD@V7@RWW5Jx3*%J-F;o+j@ObM z=tiscT4O~bMnHojK7jbKNk4QotyTSS7X2XpFEY1_EoURKkK|q2ae#4pm4`Ocz94f; z4ejf_UTatL63?>ZuIuW~GiqhL1c*C)k)EC|yeoW5?8$NGuB;(m+^FCtk9OU>sr5^~ ziXC_=d#r+k$Xj!tExW+>^As5=?K{dIVGHdIT&=a;#Jiaf`yG7Ke4Tc2;Y^}cv`A$-9;htMP<)Y_T8X^`d-0)vDmg^)pO=W@WF%L>Rt*N>jzlp+H;D;qVi^<7hT9Y z#4+w87h=ON!#>IQG56&x+b8d0XET16XlHmXex!BS;Wmjs>9|nrVR?=X#a3xbR@k;n z*}JS6XSPxHPUL=wIm|zoZqXVSU{}*t4!%zjdH!0_@zfctozO|sSu@vx8|5Q)=3ZTx zJsf)-V9U-DR$ogr;E(-uy{Rt7$5Kax37;L7^I0G`AZUc)+3@YLZi+XfLi=eoGQdMoG2lpY_{ z`e)P6YVMN#XZl#yZn9P)cIdG5_8lK-p&hQFb@sZL7OHb={p)A?SJt~7`udaLE&4ih z)Bt@Q`+-f@q4af`8(>DS50{mR@_8SmF=X1}tQ zRB5VT&9qoH`}p*Y^sCqqBFur_jQS;OX6A3Qbs5Iab{Ve=v0M7wW~{<3!Mj6Y=1A$k z7WZejOH9Ho!Fxkt?2VEpYYaQRWrlxcvx~FlGqsg|cl~8U(bnc^*_;2?NNs%NoNE&M z(I1-o(UHHm#=>pxM%mkxI_*BOX}p;=!X9j-a#lZb&Xpl!wz~IHcs803y`~|f7s9*C zgm)PuI_Wm=!Z$T)U;P`{qs#p5+VAe$zDWAESlJ>9q`uRx)#x9=-yS0dci!e)#yII` z&ElZ3?Hdxo4%bb;+cd6VjnRcYa6f*+Hk~6i*y^Bj7q+?m3rV+VJww_j3yi!{0Vu z-7^z*XS=V(j#$BbIGBwyneI;9BJ{QBfX+Po!9{3)KlQ4bvcBe>wZg<~5<~mKph* z>~+7;R{X6tGo}NK=?=y~SFk)jrXv$AUK$XJ6h zt}({LlvDja(XwU7taSl?5JKNneTpy1_*7#!c$l*fv{Auh+)Mc|JgeTB6V*HXtKOMk z{py0JdCWD^A_w3ef;wlz}QF|MaL8!t1`*PY5OS7wR{vm)?U5CM^V-j;-@IS zvD{fb2{|6CA!_(pNWr%soR;hH}~EEy4}T=Znq6T zY9Dkw#+bPo-XFM*%Py4uI%OT_^}jIF+i_U~=jmlFm)=2qan^IL4cZI3+^PGMQ`d98 z2S%v%-1{H0PlO&hS?Q6Mj)BjN=yTiRdZgSrBlo$PXX0%=^6l!2POC>6=#Zj6V_%%N z-l0cUo(WXx=A1VtV7#_+#|-`Lq0#z zL1eFeuyY~jLsMBFHb0m+cTh@s`>cbsX_>VK|3@2F3oqoZ*=A{<)t+zLdDfWidzyE< z&jglDd!d=EXXPBrQO>pon%6F=;%DMJ_0 zDr*vUmCxCDsQyaeL1PvDmT`th=y8pWm-Sv6FDHC#^3N4kn#4DfGDX&Vp7nm2^{#I+ zzt890N&l34NYKXKLkgD-wA~KYXTO!REi3Rbzi;S1TVeHC_?kqYHE=JE*et|1Y)JgD zOMP7YZp6MaT>S2^@TrQjgEExaJMwx{~mF8N_nK1u)F zpVuzo?4^ZsVjoeyMd6(ntZz1)x3KrLSZTtawqNjf;xOclZ^HLKN^Ge2NBze*>z*F`>{_Y z<&MYkA4s3Kfc=ja?5`Ro?3utW`J_KzY~-cq7UheLykKQ@bk@om)@FA^#rL3;A9l2U zZ2L;TDPbO{<~N7mO}e4_U*hzb`;cbbgN0)=msi|RJSarz1G62G^TSf7eaqs@)fR0^_+ABVdguf8higOFV;ATRV&7J@v%jZ9JNfQ~cJ}w;T;h(3 zd_+eQ`l@VuUPl^4GVsUt2A z@og4ePSTY8IJkDnJysk4-70&zRaWLrTONIxJjt{do)SM9yAN#M>ZXnbvjf?Mz?p|0 z@de7J#KnQfTgc|?$=7u@cPp~)v~^d-U$pCO{33;47Pt8G%h)UM!Y}E_14HBid?vC$ zWPG5)2lH4d8P zS?$h4->~U8-Ac3RKaX~2S!qR%vJJJ-- z?bLgSwB-J^`xQH5;SLMFUFLJZ`BPk;51iBHfn(V5Z2&%wKHmRJJe9|1#jn1JilwR$D`wfNNAYjx((Q|@h9L%CGv38mk+P+s;) zo%=7cZ#7tb5p=`9ram40GPypvi{ihsKH2NdF#_0LHcSg(uh<@{2zd|Y6C z&llO7;yVF7)SkEWpWr9wJOi9PSh+u=QEaUd^!*TfEiP-%NPG~5=I>y?Cw4}wlrjFH z2>&3?>0xJ+vfX@(;I}!joX0H3zD&H_IOG+3A)F`1FJVdzvSMjBd!_S;8#o<#p3dAf z3mI0RYwa1YvmgTkoA4{bEV3zuDN1MqX#^V$FXbPjZO1DY?}9A=e&3A z2+p8th1qVsaXNbf*Z}%-a^1gPHgo!>F!>cvTw2t=*)^p%;4=3Gx-yoARP0>gms>1< z=8VshX6^+_JMHumY=(YphLIWC%CHNY;Y*ec?-fn;SNJ*W{dw~}f;~lFxhkcd)0PQh zuXfr$rH#k2cg<%XfwQW6>M{boyRgCUI~tp;i`^f7bdM*#BRpd3lF}}*b4r@bRnBx< zX1>CA6`O}VHg8FOkzGz3N)9oRHL)F2kMKA4A>|Lky;@2aS^^w9zCcS~O!muJL zw6-zGW&6D|Uu(ORcl-Q+@6WLTaR7X*FYe{L6EC}7;e9uC=dZjiT7^A+26`BLpDDER z;JYNaufbPV^(l5Au@{T&CxTx0Z=4ZUZL@4XvL7J%Bu)M{^>0%K2z_$UE%!{-mY#qX z5zB@oaDI0R98+f>2xq#2ExrS0`c(SUv{_1>vLB@Ca8Iwv<6OqKSwlP93;oS<@Vdeg zK3BN&Zl4tsz35w(-i2+f@DP0yJ@UZ59WjY5lNnvX`Z+>;lmPbi8mw;z36V6^R&Jmcjlg3X)8WSty7?HkncHKM(iU9!Z`e`%8WioAVI9;DhM~A{YKrUBvb&?|dW1Jr3p_1mbUA z^hRu{ZF4=0PfjIuh|job!yMe^`f2G8bnFi9f)F_-v3RN}Z`)k|Guj~d$~^hnyja{v zzH(mdA{+mEIA=Fp{AJ848v*@e%W?Ixt`Ks#}3ahwGRBll%5>Rj?Mmt}6| zcNV`~ey1zf%()OLr)Vzwn8ZO5IzG(roBX718{f5 zj8C`2HM#c)Yc3U^4j6)y=zoXV>$;o2rH#^$!r!7(iGPfo?+`fwzhugI68vQjY90@r z=wI<8Uc;~6{zjk3{*(B56LYQY?@6!WCp6;@O~p$kif`b(Yc1W8ehm|^=`-Z{GQT_d zUC6JHpUlg5@r$5uO5Jh3b?BXbVsM4gJ8vPMz)&;>rl0#tg_myPm&0!{zY>0u?@E4G z@Uz>4-(y<^?@Rez&u^^tP0r!j?cw{j@Bs_wpQB3>*DSoxd>22N4q(i+%Ryh{W}C=R zsYCHDyk(vd&QfQD<;;0UQY?`j#1M?2e@iTp#2I1wh%>^{FK6?cY}Y{>6;6)x!;0_e z7foabI(ReZh|VX!@Y)&tY?+X4!8lAmi7&0q=h9ZeSNboN?+?6|7$1~thL6Wsu%y0R z_T48~@1Nl5gs18e8d`g+VRSi#f6SsO<<@FPXuAK}b~@VT79{MdXBjKiGu z5PC@bMcLc6?_3n#$0=}fo9hRzd(v7M4ja<`-@ln$v9@Pi_dob;57KijR{09D$Hc9I@q}`|A2Pc`d za<;Tc8~mSNOa3=_-l4xF!}?3#?V3(4FJCsKng4gT@&CrZ^Yp|&=~bJ@FVW3^zto2F zZ)nQca2wK|ukZ z)bn@U?fi?l-*Nxe{cq}TdH-ww?RCHH_Is}MlzIMINQ0OEvwMoCH0>!@;@|iIZ;5pC zueU~iKJ80sS!vg#-Jf=c%K5J6j5PhUWs+fhy!RJ9OVd6F{KmAkX`4K0X-#RHJ*glZ z_3Zb|83d1)JwF`q<)r~{$-OtGKxrbG$iWl5m$MRq!p)CdoCIAkmr*l-c8FMQ8Z$a=j;)oG}nl)r^Sk0+$rzoz5);T z7Nl{1!3gd#7|A_8+~wnTHGZDE2Z+DeFZaotcll&;zR=am9VBYKH|b0MP*z0|`&sI4 z_*OXnu~?lRijCCzyLKHKj=KeJ!OFI?`&FweF}_WS2|X0X4?ofHAF zXHri3{TMb4Ge2kKc)wrHRFX&PX5W{+F*AmAJdJZH;*&4-UV9%__Cf>(dot8#`p{PQ z6!%yDvADnHU~zxdk>dW9z%6ADy7YJV?JG^w_P*+9dY-ECtz!VMyKGb=z{-0ZK?#9 z8sOQm-(@c+gE*`;;Ie`J)Ee;VbqAXoh=W@SPWil-d;NU^e;2rE?19^Gj67{`Wskdm zh0rPcbak71#bUQh)z{ha_}U-0udP@Gs(t4Eelo59Gw3Y+_urD%@TwnM*eU&Q^YCf; zRqiD+`Bm(><~T6>?H*~bHAccCE&CfXO87uzYd60f&U+RiUrw$nLH>RkIeaDZ_zL9m z<=in?jC|!>HTx7D?(*MAIj7xN${a_P9Dac6#*4jXJPh$aZ(=I3JW6FNE z>}8h7SY{u#inA#BXNcbkzO2|c?Y@vRD(3xIDyBoLi#+z(5%$3gD&+i$1>5#>5`PM_ zZwKBbWP<|D@e8?alZ7osvY?w0i za?08G$sW-f{H)~t37*nE`dQumVdt^;>>kJNEk0eck0ASIhuz-R5HSE2>XTF~s}Oy* zm>2*v_>TWhO)hkheCye7d|mC=d6oZtq7A11f?dy<4!oxEx4n;Nuy^U_ zFJ}<5wcg=VW>81vTCIN#c*wqoy|+ht+n<%sg4UYK*X-n~Vt95D<3V(coPwhxFORA* z;J)Cp`g*?>!#}D2QmsE)Zji@I-gNjo1O9e3eh%HmU~JiU5FUZoTh>j3FPM++F?m^d z$$1B1C-|v*&>Y{z&r2=~XS55e_m^&0Z2ig(SQqK6t>Rh4NG)>}K_I4l}rV>j%KlZ@B*U!}2 zCY>zWX!{UNHKqo|=R@KhhbMB@iZa40{pe`@GlV2)WY z`p~v8>CQAGm+_J}vUUq|R`<*+LgFhliP)MKD?S*QH&@+LHZV<ZG$iLEMQIK7v+_w6&_Ux~vV znW^=U2dBvMS18}Du;2?!ug^=Y#A4 zac4;@ecviH7dTz`<_I06oa85M&rHfonLNsNU+C|T(JwL&?4%9w&H(&H-aGO4(ME}7 zDfDy$NA9(Y)oGy^^U6E4>ksR+M()-|f0OtSnMx-8(K@41W9d^Oo2rpfHM*hn7tvkb zMRzHqotx2Vy1>KMr6ix^7hP(Wo*ujdIko{gHmd55Xbo}K%{Q@Skq>~`XSru@}5j|ucX2Q8iWNPFI6 z+~Ie$w-vpslJ*$rVCBbpTu+^0^cC4}R5FhI&DLI_Df9TA)P`naU5Na( z^H<1sN1NokoTH~4a@~xb8FscY7Q=tRYP0oS=5Aw@@{FOBs$zkIKkew4W)&9CObD09rQbac0eua0`rH6_MN z0rOJ1p4}S&pT))6_;O2z&u0ovsx#wyd-MNEx|E|^V1Ro zN%|(|^IG42X&Y^qI{@Z#emdgT2HXQMMV)Cj*Jg$l8|TP6Ekr)xi|muNtEn53))=ei z9suS@7yY-0Sb{R<53D1m;BDqwS8$l*%s{ubM%?>&xeKX$td`Qb*6c#tP)=sF`pC)eqX zH^SGl9v5C#z6HoFA908Z{=rXwYs)iE7VXQ+TGMo^-q2*@^b~X66tA{z>PT&`)O(40 zN>3Pi*Wtf>oU#2Je^;iz)imwRDVv~I=B4h54FRRUtcsT4myxLxlbvUa@b~xpp%5|D zM^TT|_c--jtOuI{)RCi4>@AYG4Ct}xql@Ncz)OqCS5CfJ z3H`62A1md*xu{ z&EFg>dGyG^S+vc!+St_Hy5X1aQukeYd9;SP_w|Xb2S-uwd$hSb`ul@-P~V-j`cRA){{U}ech8T&e|7pMWaMrG+`04H!aZH#E`4y-oYkRg zuJ~%`+M)+SKFS-EHz;3EUB%!X0mjex8(nXA6>Tl^XnS`;Z|$qbCNFJXq>T!W(#GxX zrtS5w`gfPo&U0Pv;9}_Tu=D}A{TUkfLDO-h&vc~+XL}Y!(|L}2@fRD%(pUfM5BEP> zvvk+SUfOW&_jhjm0GdC??;34%@cUPIH;tyQ7hb)3cQZ7_hb#DwJG=0O8{Q<}=-@+I z+8&XyvpH+=0I`isxOb;s(FGN=6g4t|HuQO9{A$ZdRh><8JrE=9`HK ze3r4Py2#ihe3DOk0r?lx$MU!EX)aIU&xN1R`j`V+cgfm8*Mk!K%|M3rxb?DGyx(!w zYfaU8yPIaw_ZjqksXnSTgZ?jpXL{*-1Kx)ZcbCBP^0)B5JT>Z7@W*L=#R@j_Bk<(B zrSM^X?HSh#FXodrTz(8QRy4*(1>+)@vA`Mu+pQj)b)slrIx-L&=DhsA@_D_Ct38aR zUdGTY#!dPeD_-&$-i*bowM_~~a5KlKrfBft*fXOiSLvaX#VUsKBO>>;DYA~>hyGIO z()#_#LXlk+V@#W5#RRSY?K0E;TiX0_;Z*=z;0b(zBlDXLH?~XLd+1tl zTZN5^IeDqg>(QE;m~)8Ai> zP1eiYlEM0_>P%vi{bBW^WmQ#CvH1qLbD&c9HI!84M+HZFevtL@$yJM(8;U}-XTV(0 zKXzI)TCOu^xcH6@Zk2~U7QHbu*B_ELX6c!GwsRLP^F*Wf_&QdhH}-r`N30f| z`|>jPlzZ3r7BdIspDfxacuxiIrGHQn z)29TFq)!dv1KwwRTHB6~FLRPwBcdmn_RITj)k62CYyB7%x0!R@<=|Tk-iw&)ibDM( zudw*w)O6tqxi{kv*mP{&<>aazv{T^}$L-Ly|4jQ$J`{b0yK8Vo)gBW%uwGTRJRKd4 zKEdAQ?_b2vhG*ut)+Sb7Cm$-F29`ltCto}HR`jXEGqrxF4rTLO%eph7hCwXsDMoJ< zd}HgUMQPDje8_y`QjS;W>tZXTYg zhq`C7#|0g_p3@rl-)8nvnDbuChy_={d9Nu6%v(UOP zs5RwliqA|P&$;^KJx`6!2##{62S<6d{@v73#(Mi9ep`{% zbtkpHD)=;ma+`I%4;+@(>6-Gd-9VlV&}aiRs;fFz&KqV*zN>_8&`Z)|uJoF_(O+I; zEx^_yGk%l^Sr zO*h4^+&JgM)%#3)sERA3=vVTm`yVyj#vbHK-(#+-#wU45`!W-DG8u4|G^TUTZd@tr4B0O|xtk&NHzet~T zihMc8)IW9VOLf=0^N#s^XgP{s0sWQ1FCX1#F>9`T=(G?z+=(6<9I0LOKD6vX7u|sD z|GAz~cHKk%?F;p>y)%FCaMNho!F;{v`+0ksih%V`XZ^hCC;IrZ_w{iNb(*L5F8+Q4 z+J3WsT@&+n&BJ^TlK1b{Jlr&k{10nm_IxLAZGt9v+wruc%RP3_3(V0q`gsj+ z0&BxrZ#JP9v}U-to7+9M;9BxayEkB8gU0=0Gb^K92~TNf8SRrczvs><7)SdS!k5zS zF*Dw5%3%HRXZQK7eZc9$c3v!SpbI+G-i0T$zAy3qVBVWe8_wF>^fhf>jfF?=*t7RGo!ha# zsh00!wXqGk+NeF+*&R)IaW$OpI=`V2{ciS0#rtaXQ5n*oVQ@JQ+SM>#1ooZihd|-H8bhGvVYGsCO3i_KKY z?-YAQUTcoB?7$m4S?i^rT)nRq|NCm>)gk65^shZVy>%~^kGAKiMQVT7-rS&P?fLHL zt9HME9$QM%qG}>kp-m8Wj}zBKr*z_pW+|7OFz7=0cn1 zZr%1FZ^jQ^){}>n+?2ImVh=+09~hJ9Km*f+ZrJl$f9{y~j@|wv z>iDN-{H!}zLC|si?+3-|GsJ3ud_F~p^Ka|+T_k^sH7i^ zm8+uYVamqwE6%@0k=+sO96i`Mx*c|oC$V$Pi`zLkKLLEsDPn`j?lo-?zsClV9k)Tu zpbkTyu51w4p0I6YwiaL$nFa5aST>OiWfPg)yM?|^*hJRjQ=rYA%-KNMTWDa7UwVaq zenw5zJnn(55xWGokVa*1rk`b><`wYftTuX`8S^ifdvL_&v5mD>6nlmp|r@e(QjA}RLtGoNu8GtTtq=AD^_ zd@CQT^_3j2+xHx_T@1|^>e)Tr+zl&Z5IbIB?v&g!S%bHFwftuU*C#mVn>RbqWb1a) zXC;(_e(}C?(KhKX0~mrgeA+sbzo+S0n29(OX7yne?eNiW0r2u7_hin^|sVB{bA$@ue^b~p4tXzT@{1w^640n6;6V72J{I zz4|8~Yg(vf_1lnjvezQ#U?w9|Kjd1Rc{R&UK4mGmY1bp4e|UYmNZ z?7iKM%#(gwxY8GuzLNW;WnK_|m;ygM#hJG0@YB<@`FwX~kBr^T?#$lXc&^X*RnvmL z%uNREr~pPC@cqD-Hq`<53#5O`J=Nrkl?$Si-TwZ`_$GX~PYb>8*7}b__w(VeI)O*K zD}gudz06H@?&-avyGI$5rNCGP3`wg8FKLGt{>^8MNBCRL5hAy@{dtjpem8y4ccttX zOm0p82pg-5Jp_Gy(|&jQp8d$eBg7>?hK}z=mZZbevydg|ddsVkPdi-cy?L_!g~!U+ zBa*VYu7)Q0z6@LI_vLPD^rLR~_}0gx z){BSShSlh`}LyoEV{C9k8cJ$coI%Chp7<4lhS!=JtUS5nJ z3vD|@dxfXOULN4in@P~?_rx<%dlWZwk7s|~qnEHwS?r#K&Yao12%h*iS7tEZRsU$U zJ9|&Qo=tjsukuBt{C&&`vaiO$&TT&Ku$K36yx)gzyu$(oE0UVK!b@KP@ zO-(sp(E8Rw<0y5Dtco6A_2LApT-Y^mCR(N@SCpd(t&$}|``YM+;KZ0#GoBT4r z%inTtQS3O*eG$&lx4x{###F|??7^D*A-V2>@XK$}`YO~IHRlV1{gg`j#^;_ET=hpa z7t9yAbaK@d(DQQWS`2*`A=`>V$46cnHFY3!U7l*qKRo+Kv1R{Qov?qP`^4=ZNxEgi z{&A{q*^i!+>(FzA|DxzLN6>ea{o@;2G@;*!&*6WL{bR6pC-Wh^G52@y!9rw)*m#7G z?uCyo;=HHuhR8DE%lYu77v7iH#Psw0Jo1aolykgN&gNV3i4eZ^!M74$!&vi};@fB8m80M*>#U>jt<1&3 zd(Jq+Hvh7Jsbs{$IFDI-a>OCNdq27be3nyl(L9sC2I`GsZ*uY$=bU?Ge)3gl^K+TI zdYOy!vDfslZYz1HXkNgj&GDhjj6$|-h9=G6ISRS<5Z~U!M`tv6jzUJBi)@v&_tLaE z=sCUJ!0bYXvTmC1U8c)z0`xN26^N8Mh&Iq~ufUci&Qvw&3ttSYG!SOQa?0y9Iw@+w&Azygncsi%bR zrOO<+kx$_U%yjY$8#n592iiOT?;G#Y@*g7`2l`sdTyr13cA}H}n1AwHWDPj6 zRrY1!z2)~Zm*2qtYy|o29ldD49KM1%{B8DRcNRX?w4Z+M!7eRxw~Q@6^S9_E@c10b z6XDLG9QUMNEpPM9jN{tK^P96Dd-2Jpqc>MZ=W=h4ObTKr5brQV010gFCS6u4x~x_DWR$Uaob}9C$1a*ziQcw8R|c4=3(Kfoy)XS_ z#l9MB3f=69)vzB{!`@#t&q>I|QugCYd6&Jp!>reZ?{DP&v$XAX^y~tCl3LdZpNW3A z3)=Oj|E6ihe@s$qaM5L=E^k8(bKTu5S44kBzdXj@kMRuB{yKfKT4N)Vw$mk;*^9HPKZM-^woddm|JH5YZ+WNxaYtllC z@9%_HzPoZ(RP>+k;>UL`=@Iv+R(U@cd*MUooW5;`z=a>a2i!N?GB@qeGkQBdiY*n{ z{sQAi-u=9P8F(L1{ue9njItrO?S1#y)(?R7Pw?U+=nZ}Ra$Mtk{ph1((G~6@{|kMq z_kB=xXH@e2oHT*)Chy@22o0U1XccHIZq^w)mRv$c?X( zp4cD84su=2AN1Nlu^RLE<7th%9rx9lJepJB*K>a3Cx-d|_Oh1e`R_c#BhM)OJ>OfDf3ID5Ehr~W>_}4`2u)*s1_2%K%alTbY^G_3Xl>T(+ zI_7+P_;pOT>ZsV2s3U#X&~-fCH2gXyT6Oq$ChF*UZRk3PJ2mY7NVn?9eJxSP?vA1B zxZ&~P*P&Z=;4_QfXvVv1-7$0>ZI2GWj%b?2SO1)-qv4+ub=bUm7};o#<<1>i8+(wa z9TNxnE@Ly-f-7U9^HqU6aBMo^8Xa1jwE1*n?T`hx!U5M%_?mDlzi!@*Vg!lPL|uZj z=#_`jZI7_#eO=D^SaRfb#+ID(ISR~$;MxI9$rl3GDqu=}xo0B|bN%pPO8W(-wBLsL zI_*CN<~N29leM>kS^sJRW_~J|4-Ow@#DW?AaRTQ0AE&@`-SA-^uweQfFuQ-0fZ0r3 z_$!g^;gLCom-F-!w|EiH3Z8zRmCNx7TWwsQwMW!=gS|z&R?$@ex1+Qb-v`N^QAusn)o0j>nQLz3oZ*W59S^HgFE!z<2DjwH4#_rIJt0edG1` zI1h6Ma1VFi?mVW=wd-)|1;#ORK0adU29r1oXX^&_tOYCAV*5r1GPJ~e{1Na5;Pl`? zoVN2lXN^`HK4Q{9a0(nr$R5|x)VP!!N$3VX;)dIJB%jZVoJ^e0doLN6^#gHf5?sJ9 z_rnA(od*-Rgt0TNBahuDa;{;^!9;&JX%*>9;K!a#;b8c+^e6BW+7F-=XCRz9)O~^< zJkare0>8@l6ZpmPngcy!3B1}`Wjvd*^$7hQKSOE34_UJHOTZT%t9Vz=DP*<2PG5N6 z75JuXwRxiL?~>tJx>olt4K#(}hI6Iwl_)z&|e=v&_t30kGX z!+2tNcyyv?SFSbBsB$OwKpsoN<0%V|@S_Pl0_Z5VE>I8ccLF2Kvx8@HA823UZl)CJ zxukDPk?tq`dnwW@NN-7zUQhb7Dbkxs|5l3h4$_|>eb{rx67;cI==lXh^A4M8YM#n% zaPSU#hs`^~t@GEPfnTXFG>kegvFrSXqt34<>P+qrn{VdKWnOxm`Ip~NV*-CGbN-#5 zsH1fL&~;>8Jp4L-Xw{KBH&MrK%G5~#v)sDxEBDKZI(FYVbRCbMF?@c;e^v3BmYb-fHD~BL?wLOPI^IKX z7GAFBeoUKI1>k7YD*V*iCAUCN?di2kZsHl{d8534d+m}Nc;@ncJx@Q+>v&f1yq0G@ z&#QSh^TgLVvxDbiNyn!2X-VgK1g6C+S^*l3pHuFT^&g|ehl4qD_8c$8y z#WRXZ$_T;8;TCUw{Xn8C4uAan-e$=R>z$D;n(pmHXS~fsH2qoL~Xtq ztd1<-@auTdZpUX6b?oL&zM<+keD?6`c*btW^@%!4uTRur+dQzJ#_gAt%y)z7-o{x8 zz36PluU)=z321HXKgHqsYP7an9q*O3THBX-7u{cAik_c; zv(^?$N?Tl^wQWmE3$4@Ib|j^}PW`)+(z>bh*QD7vmn?A5jrctW70XC1B#W7ssj6 zfl~w>Z?N*l@I%s0dOSGxwH03+Lk|_T*NBNeE6Xku(mxI>-=|uU99r%~Pm-cuF zAo~U@A7DJj{1GGhgaUHN|e9S zQJy;`hgE;)?TPXW9OWy|A71$Y>uQ^Rg_Oq^cR=hQktxekq>Eg+g>;FTpg)*c_YbfS zeNAhdY00Db9?kz6xCWiXcYI@No7bB1RctXO=%)7C&z5Dr3u4h)A%kpOd=42Tum>ye zyDU-uPtNjR9A5p%=Xie|gx`N+aV`IC#t=0vY!5V zi!__Yr`^XRzs+|p`r#D51J$?Z;6zVjTj-BNymvpn}u53Bs*MER>6_^&^Ac;y4=i9&a& ze~F|1#ZGx;?Z2kNzl6JP?eZ%e{A2utvB=!}IcJ~!G`205G`UaK=F`r9iEZ_g%7u3GgXSB8{R+`8*#$}v;BG@PflRtq{ zlZI=g{~hH^9OJ)|wfbP?ODz7A@+FS)k)lNXrz>xiBCWo;mJsrjCK zEhl1a-QYBU4*yB*%B6mLZS%Kmm%z>aKiIAc>gU|n-@LyBZjaJ|{?GJRJ@vmq{eNpd z6u9{556y=S=!A0ajPVuU$6_yvwfs`CqkAjZ6VjTO6Z2+#4mL3HDb$npe**A$#2TAo z8{W;&9HX42W{lQRPR6MCikETsu#5{Cqjh?EjXg%UGDd?*W7N-n)PsZ2rqhz|sm5r@ zR8v06811C|fN@8AMPI%%MY_zDx2H&#`Epr`bPc(8OR99{(i>8w%Y1rms&wSu;#BF( zjm0U_WzM`TMY_zJa+g_hdu8sNot*wL?ZLu3i$^Es)8xHm zr%q;YPEYi~*C_K@+HTj~@*`|d@aeA{^%$?B%P_agxo$gOPS&sX8G{ZkiGf;EO`}l=oCZAt6b=J6Zod${nN=S1KDY> zC&oDVr_x~$jUa>M%$Aea1Mqqz1$_jMIi$z=3!Q}+E`^1p#dRF~RR_~=Z5?L~{G3Y1 z5m;vc%cG6Z3@x3Tg2rg$v_gW>->H3F+pKNZ_G&$vTc4_5pkJ=vq<>jor$41P>EF_y z(VO*G_227ndync9U0JSqu8BkZyT$bd*E-iG*FSOJ-%I3eQ~6(UwYz?#{(9B5!}XTy zm}|QGOn0vPZ1=hDLiarPr`(sjOWn7-zvlinw-Eip-Q)In&h*UlT<59wtn)nR`G#k` zC+K;|^RTDUv(fXo=SdGSkND5UzfGQRdtUbZ+_TrS&+}`~Z#}>B{F~=LJa2oVp7Ch~ zX@i|Xs^qMKc|Jie5dZ(3oM|CGbb+CN@)h5hd9N5_{jWSj|8=@Q`AW-#d9PGX^uOH9 zdjMX3(u{@PE`BYq5m)(X{EVJL&uvHUR-!8}<|q3ZQSLD4$3LPVC*k{Az*!UVeO<(N z*`p$MGCu!PThkx*M|ZomZIWO7^Q4|99QAA&tu1|udY+^n?BxUMIm+3RDCN=}^`u+% zTxZo2c5zmZd_BzDoP*yc`K6wI(&YRLvO2C$%YLEo+Eh!Q*4$cuU@dvXX9*kw$WEOy zlT;fgw?^PQ{MJt?KgB9f-SP6i5oY-=%3NU4NYzi=+A#QtOsuD!bnasTOV*(k( zdH5R3SseLx031D9{RH!D&cp)F`4mWc%Ls5exbWqAXy;}>O7aljd%$00q}D`k2pQ~8e)W7Mn4q)SXT%E%cOXBo-ULw?C8 zWmp?5wet!*pZ>X5BCd*8T0E7n2wynMs_(J#mn)NS-08qk<@xCLm*q@Ba@oq0x4#@g zemdKiTsERrzA`>V*??a8GUs52O&g(cH)qqNov(qP9Vg~+hQ!lN#0GVqBk^hG86=4f zDrdfoGvI&X(BxdD)h+{u=s9D-tr8xTJ}}NRzZ0XZ-N@1=h%LGVdWxL)GM5;+o!PI? zYhDfx)%6O8#CeKAVN@|E14GWH`tmxnz0lhGuO^HN!2#Vw^smYp#I?t7PVf@_L-emW z%-2l3$bYfKw%+gjmV`5SUzd|+))_Bv=lO+-y?ar3)7m9_fg!TcSX?rn`Sqex@*>9# z;wy2FMBg&-4>j1+>mjTXPr|J-?<;Bz)RqIp{Gq>iQ9G&II4I++?U=$dx_gK zzlFFLGGA{6Mx6ddoU=R_lXGY43`*`zmD``=yVNCmSR7}&U;X6gtg*%!{-^nV%DJh* z_CwWLZ2GiQJhXcW?ZGpBTJ5+6wB^W(c%BQMlgwsIGh72iBU9}`!)z^IjR z#5}?n(>(AhdCj;8IRyu(Ut=DL@)WtJAcqwmOmMBZCxSG;Sw545?m$PsZ zKi~jul6JtiPe#sJ6betq_ZL~Pi?fH}+onO|($ejsB-XagOE_PsV;7%z4|8H_E_Kf2vh3cb^{3%f5RPG0QkB@%ai zGBF1t*Jl-WyPKCECH8yWrCNV@U0^|Y-8UA5|1|Qh$lnt;l$c@Nw-Dou`8HPP3B@*P z?crJ4$=Jpb+hhCm`LXBp`H@{|(eB%|_Ei1(1si{>KW7vq@V`#zAiOalh=T=VQX5{Jj%zmohdtOdN#T;i@xJ9+s& z7jTXPQ-kBj%#^NDXJ<)^irFn)_w)z3IVR&cH2nPpb*L&pERP+6(+D zSADzCH2=M??$fHOPH6sH&veF)SNv=B*RDL~07oCaNgoNkGB5lFK4K@4_YCyme%{5- zqQ0ZI^4==;o4=}le7T(U%X(PVXTmS2vFjUa*1tMl-|f%r9;Cg4we_~_fptA<)iuk4 z{Z$Kg&3Ln}Z(8qLCz@?-w%&WQ%_C(&`fyWN%NVL2IBD* z@JNO;6*yh^+dE;PLl>CuQ{(c?3HLVebkg$X)NrF+*wy!=4+t#5%>frVcPhTmagUP| z?&T@rb}M`bftwQF1N5;I?)fRV!KbCEV^6UHH>~9DHx%enKZ) z;9;}PrtG%^=nPJLf0G)nqVFJZQ_|Nd<6i@&vyNBo zcWXWr9c{nJ7uIn$ZxNfYAWU4f3bBVU2MZ6%d|$QD)UTKMz}r2U_0VU~3$8^!xCTAp zYV?Jxh_zN0LVr;4ms82o>6R=N`J7UgUai#<$G9NyiNx9B2FKZAIa4e+FLX~IQl{!| zZGzxFj(H+^{7MWg_QK}B?$zc>OyR4Q?3iBj7_fWcd-Sf><&HFwL86P9GRVwV!?=@t zUw7myn_%X9+)5K%gN%ET)mt3-W@VcB{(-badj^-8c3b{qK>pLuDR!A(IO)zmdA^JX6LGT2{>+D^iyoR=o#kL)XMJksDHnX-oN1N_b9rXvXR8qO7AG3K!W= zNv45w&U0B~qAW$etSaXmF?bykuQRz0=)6MYwb_o8bXNGCm%8ls#2hksy#zo^Rj;D6 zIZvc4+baDl>-ZEnt9pmRS@^6HozT`DMK=0>8*BR!vQ%KpI!2ynQHSuQ#6LiPoGbY{ zlzq>>&&lLdC0n`A=^XOQ9uPn>#il1~K(Sp<K-Z4 zxdj&5^foCcwjWtLi49crRo39hUoGZy!vD8@mO--wmlJk zNb_qKXw$T_w5zox+UKXD632#s5u4G?Y_JniwDHF0OQ{o;~VB^slCp^#%)X`*sxj8$J1}1AMJYy^R2%>;paXiUqMdR=;h2E*pa6f3LnV)D10zf zS+OY@C$HZ(7rRnCuWh?Hm$?s|qUv5v@bYRC^7#gjUnl!Skqe*7h9BB<1*cDPpY%xW zVzKd@7^}4t8?r#1sUDv=Q=O-5#3r9_`nqYCUxmH9^9jxw@H6f5(}*LL-dgRjmshi9 z6}!B&s~o$0n07|p)0ADlfxeaeVlS8YQwDh>q&)?^DNQz;{PCB4$&m(s#_v7=8* zVMh;8-nOI57(s?AySKoTz7*THz=sZvV*frdmiXr{nRbSL*Ho3qH?Dq3x!b7DUNL=w z*mabhZ1&>$vaV?1Jo>b(&DnJ$IR{IuB3Ylc>DnCph37zzIg!b%EnT^Dxnr)q8`^Ux z(((vr*Duurs*Ko?7E$IneJ3!Qf&VGqe*|24m-;SI-*e3G(CcD($4)5Uml221#>XJ; z@RRh#&XLJ-b>{P6e<{S0Ep_KcijRoBxF= z6NoikP?@f^udn7F;A);T{QYZPMK7!w(Q#ST46XlGm;S=C5%rg?rwsQ6UGEz`K*%1jPVNS@ECLtjKHsRbP}zYJGOGSn#6xM$G|iNPjrl&6U4HGha|m%_}wp!pf7;2 z4EhWG#9zfbn)r;|;WLA}#BYVXnPwmU_u{Kwx2I6(xn6jR{;qj#6@J`8e&ePL zcxP0hj0w>LD=iusRVJTGoniKSx^tdc(tUEra`-IW(5I;Uq6Y@FmWz#*=@X=U9k?a? z0@?j*k86qfl`_p>tX!Q5E>j8(Lu*(0a?LxI!|bKV`ylZP=jR*dJvhvZ%P%6vrjs9p zKb-u43~OzMCqx&Qd}=Mp{E0kO_fhU-o|AQ?%sr7w+Pr(2J49#bB#ylqb6M_EGVNvP z11}1^m)B~c7MH-Z?^!bSL0L!MbH32z)VP_lrj`1&PolfiHtk&NNt@L>dg_3u-@0qc zdK%D6JI|OXdDP#RjY|A|^*HnIPatow+l#!=@XJwoooRfNv~&ajqQ0oSZA1jEV9OqH?RYd-Fum*~!Su&Zli)j8%^ZhzGJoZU~2;@aT0y379gVq{_ zkgAgt@DYNv^6-J$A!uis5Uqn&B~qIJ)0seQE7gu2oLhq2sV7l7GZqS&PDhZLPK4>q zIJCCYnT`RR=}BTAScL?kx!>Q~d!OtaP88eT-aGdeKXISE_uA|6U;p+0|JQ&0AChP4 zI6pBHMlB2GniBkb?l)zXOPq!t;<2)xCQe^c9rMOtQ8I4oeckARy?f4%&2j%eW4m78 z==a<@=$}7_%p+$j#5AEU$&@;S4ff*~s*AOisV;}PGD}=s)Njf7$Tt=K7$VFmwucR+ zf3c}JGGS=FI`AyX_1&|)@q*7**2gDn*s}?gyU0Cv?OEBpl)O&GnkUt-aoKkC?HtNY zcFWb1t2a|QKNh)gC3SXwe!Q_{MzMwanRWZEU7{m;QsM50hJ7=`ooBu$N6xs3&ILsi zOF~oEB!RP8yfEAUKG-kSvmV(eV?CoRPhO@vM7!Se_fDMH(cZahhVL`ZvxoO>;3_!k z;@C)Y%X$mq;E`}BX22)?X`kZ%PQOOPt4Bc(L=&I|+z+%s3(#*4EYy|Q&?TdcUE}Yi z>_~ZZ9yVErWG}IjoLxUc=dQduHG|hYt~@b13!WWv4rwpHazbn0VtCn;@Gf$P9jczt z(wcqdlZRK2CwEa+A+h`m5B2@9>G`G!oBD1&bIs!ikjG2UEO^|{uh&Qp9?`!!j6av$ zXPYR)zNGIG>U?%$q!nJQd}my=$PZR_aeJUeK7E37NN4HH#}hA->!TSSB{@d%q4i9^wO1SXN&NX{@<`113Fm!0PXe14h&yX0 z6t&jU-ogdu<;bLkt)l0>ylWe?|EgE1FFtzxRoF2sk4%WzTuQ8U^3SM0llr>(E{A+A zcQb|`k&9_3V`!ML_)spn+kQm5ZJ}4M+F4~@UKtwK*F1XLRqLrIdqR$_M{Q_a&Vo5G8+xwGWQ+pPNkxx0Zf+j5Q8Qi#Z z6Fwl~g;D18z2KAPGl)+^^EqTgmJzld9)nlIWfEjX`mp;~-G`Cvdh@(Ib^ovCQaza= zH(!dDcsf5|7_(WF3zIWzfCl)$? z2%o(6#Ph8U-UZ}WMyALo-?8xKE%uqIc^{!~>cd=g-XpbNjvid^>czWhXLDA5tR_?t zvpV84b%)94K5==d(CW9C^VoFCs@!VIZ_6@k`jF9_?>un023wi-PlcA%p${T=5Aqwj zWzNZ+37fFLnADMn4nEGeCG%X{yu47+<;}kx|9o(7rrdv`WoPNB-o!o;y=xb?fl(80 zYzf87dkSS6OTLXqLdbcM)ji?O#j6>M_9|Df&yI%Xm0y8AR&XMR7yZveR(JV@?i`3*7I?b>QnwYw4$fAJuJUp5WQ?Pdh|g%CoEUp%b@^LZ3qZ zrFG=>+Zamam_?@-i+2i6I=gny$Xr`$ z_UxJ-R5bf+Y@KLZFL7&kn9$xavP`h$hImUEu`>g4YBKxYY z>Bxxi@#Tf5=RcnO`KJy?kzG}n;}o{mqK8nvy6sQL+ojJa422F2lIQUd@X(o%pC_;@ ztFW~WSt@a1yz>NodG)hd{jdJqw0CVN*_-(C{C2;MBHD1sJ6(o9l5f% zKRv%)x{o~C*p_NTxu;w?ESZ(pT31XPPsbbEChohs?rGClJF)rd;Cl0OhzRzoUwzcI z3*437rbVzvepWqt-pupq;A$;>*Ic#)%4s}9IgnkscyQxb&IOCmMNdX2U5sve3OG6y z9KC=%VPm(v_F>a`Y_=IVy3%yspMf#QRmG|(wbh31JrLoFO$k7H4X$%^F>bwpc;AZC6 z|L*mblplXVnRDd9!`bW!H!W^|%DE_8xg8$sW1X4x6SvIgOza51cWey5{Mv!6EzgE0 zTG_FvDBfB0r)Ey3Hr8Wf!8!0_yR*>g+&OJalJA3c$ksLC)f1|v%!?PK>esvN-aG9v zBA==1@4cKHv*(lJxisERZVvQ9^B=DXzmKNM7MDH7^AyYix&igq$xW0y7nq6C zX(;Da$qcjR^jPMZHKsjpCS1_D&oSb(sx9I1!>M+QtrG23cPHOPv3+&OXPN~6G!KJKPWxcfSZswN?StjyssbOCx487owTE?<@+`KW_4K1> zrr``L{PJYx?1befC9wxs2W!Feim=&o)eO!c&}+QZyY6r?XD!wA&l#t+THGOdWqO$X zBIDJ%we(A}1#4G4Xgg~wc~{mJt)C-Y{dMW)E1GO+oYs`q(9k>Ch`R5b-1xv$;FPKU zD%l7^v%zm$kJ^D=%>8BBQlBH(O-CB%?)^jB{blNUDXVai>ap-D9fH@}qJu^8flzaN zXO`J_bvJa1bOmP{%qw^{2pddHu+)XV$YV^VZOCSUnM8#+nydwcGb3DcFx>+ERlT#XRG!(IP1@E zawc_Y{rgSDEa-zhb^O{E^wY33;hG z+=zQDw#+}=99^M%VK^w*y(z1kh_FQQOWSeu8wSEjZ`Sbl+c#8F(sQEdz{?Amm zw}mI}Roiz_Pj@(L%XaWtFodq>b?;zZdiQ=k|B1{LtZQCcJz9s>X8(HECoEW}VEYQW z3WMwE)fY?q`u=Nhxy94`p>@E1r6S^B-wtg+4!`fh{ATiVX&f$o_kjzd6Ls*#F8E@7 z2A&vPS1PZyRm(W_%}6{EKv;e#{+GqNo-e-0Gk=Wa#1lhkSn|@n{^`E(ThBrO&c}fi0FuPfZ$h04|3{4e)k|VihgW@ zMy&2zcR0U(b$>LCR>;03gsw2T(WMo#D^kCYaPRk7V^F_C9=+&B##EW~_m*ZfuG{O* zuPgsF-)PDcqEU7o@=SZDz#2RPEVK^O*WkZ@sNel=vgXwL&YM%s=S=2PbICba?5JnY z0$&;kA*1;8S@wpm|K{*=wm<9@Q}tpWB%2_uRcjA~t;(^>TZ%J%Yw^r}i@d0@`1{gv zuHVy$?ve{nfnM*=2LAND#U#rUrf5%>`DuC5Oy6^ielWjzJLGT2^%ybQ#ha1o zAJf=pc=K}X_kBOr;p0@D3DaHPWvcfi&5gFc%Ty1xRhQ~YEcZ*eo`8OQmwp9hpf2Ke zYW)wBfxP(SNy>^(s!xiO-p!izWuO-1WnTue&nR0L@L88`zm8Z!QR0VHa=u>fC`N)w z#j>j7d+h`F^IfL>-b{Q3GtJ8ojT(**3#~us@4k@)mf_H*k>@mRU97V76TD@u`}BRk z)(P_Y3xj3tFR;F~wzAlh3x9n&*B-u)bN@)6flg?T$Q}rK7wHJEt=pTa-)*z*Ye(LR zLDwdfhRmUo$fmv>><4RsL)%7IhHe2CvOn>8Ji6L)@u*Soq;01w*X#rS$Hte?PTKsl zwjAi1wW~wcS2^`x{SI-C=dY85>L0#7JDo`0#F7c|HO=s}Oz%fkO; zRgrru+EH@Zhu+xEnTKS@uCe9{l{*1`>Z~la4$nu<9&IiYKG}NG-X)=TUD-9C?+MpD zFP`%nJoOm$3HC?7D%$SSoFx11UY>J?u*i8Nfvtea(b`^#Utuw}1BNke4=;sI$>zE^ zW}t1g=oG6f&4l86rcO-o&IuLgsJ(}?`pfSEUxVY6eU`qFU1Fy3jvBb{aQZhYZ_C~@ zG+x01T4wz;ozV1H3%=6H*;Va*j8F1UVs*T;9ovV*#-hFKlLwy0rf54hMWr{HiNv!R zn7`iatm2%a4SOKQJJ7cA$*U6V`D!9HpC_-jh0hB+=C&uW+i2f7ac?3#xnJ;V171gf z*U=sDD*E->v+#KQe}iL8^*4wYoH2(g#w>H~k6rzN*3~KKEV8(@XS@qq6|BdH)md=D z&aw_YuxQ*o;ArCtwKdzgLdD)=^)Cu7Ydo|IPr0^D-W62uYyD4u`7kjmr zWD`jpt>94?Wunk3_Cse>|?hR|}$1}>O(<|9n`t)ip^a}sjv*^_k zzRN_fHu7zzb-!{J@j>yaNN5Z}82<&li1o3Ncqy5_I|U4G3H!9VxWmef9t@PX-QTZ9 zh?C;OKx6V@pjb>k3{<|Fm=G-<%@z#oGwM%=fnw+RFc8hI3ZD&wD!$7EgHRg3I%~`y z&^nlYSu=KL>F-AIF3ebhI3?UXS2!rXekM35kH9Yi2gUIF-v)>0+__&c!rZ^b-0xv7 zPg-4tXP4^Dy=&v@>MAyQb1eK1&V7Ag?yX&__O*ez_ia_v=e{m&?y=cA3;(x|fdA=p zpIjCnST}aK4BvF1wC_;I;Bv{u*1iQ_&2sEx%M=IoZRmt( z#VOkO;O%aXbYHGX1Y(;fBxeL{g7*brl#o5LC(}r#l1@SO{nf3+BN^-JfhMCrD2W=I z!%4Q>-TMB#YX+dL*4DD+X6iU^6tpKk@O*~&jL<==4|nZ*#n)W>UhQ#O_{Qo(;5}Av zz+T;dX7x#P+~<161h~4B3ip|0Xz@u`&US5)b%yGHFMnj!DPQCU_^SWh*6Y2~y!mx# z&TOBsVQQHfog37_Jqet;$dAy@-vBTdE(}8Pz=V}JuNY+-p_WOYS_DD2t2J*NsgZOaJ9@4@m7e8F| zCjSbIS1`_p*vDynC*f}c@SkW2G_cgwF{(Yu*BYPflQce+6TeC@K9zUl>bSU>q|V^@ zqVQmi&yTHRacP6QM*Q&!k2F48ufBhm@trlEJXh{N>-qWE4Ui?aN|0@3nI%mt5osJ&Hso0$2%NkpPxfB1kJe&I{_pOz zN#r$+-#=#xj=u%?X)S8}>X-H-ndY;F_jb*!aOcnN^XT*Baq^khnSd*6YOY**giUnB zE$cs%uFmce4e)Jrf2%$1kF^eRXn!&`Z0T#3GIqV7i%XpasXwW;nbxOb^d1if`c!TE zRLq(k>XZNMT>4Zz-vpPos85ppGQnvIcrTwAA5L|)Pg92V$$xe(eVTIFJN0Qw zs!#G8@M(<;KUY>CMhDqTXE#e{;d#@5JKmi$eK_nySq4 z{q*HQ*27KweP@grs0^6_;pBGgjOT|!eYaru)kYbA4pq0>YM)rx`V!^+Haj@uZK3ZP zhZE>`YOleVj)vX6hWy!5@LTMy59v@M!(p!d8hgPti?F$S5FOs+N8*ncKk~`PGkz;t z5-M&jrw{V|@z3y*b`8rOdT1T^&&~zs3hN*Cd?s~n8T6O2=a?z@yZlY@x8$ed`o_G# znXz#05b!&S&y)HTe4l9?71+2{VrS?u9*4GXTVP(!er@AH5Khs`Ni`0WK@;XivfSg_g6LsyAT06QN)_EEqePUkN(JYAG*2|giP0^-Ld z+52cOCO-Ej;~&YEAj&z8<2=ZZR z$X74OBbp^|ZJ>-`@5un``9?faeX`%b3y*Zq%!;gTKyxn~(ERJUaA4T{Be%APUH_#J zFvOUk24f1yC!@mN%l9IBl{1$6BeN?)w zG`YBY$92SWF^8Np*IA#Q+32%Qb5@an&Uj}{9r-$6G6k(>9OogUt9G`Huh@xRr2px$ zAKWQ@z4#RPY-0^6X42yR!6#KOXEj@1$pYuR`UhW(_8lVjP%U(%`${t)deyxEzv1Wb zt-ap8UwLM*Q0*J!8u5Fb9o2F!r?Pbg*SPi^1)~OTo$dN4SzN!##r5wq55TkIHgIC- z{I0m;6g01z^E<@^+5lXt;W3h%#xZ9lp`yMGR&FY`a#NH!Re8xxr@MLmVmYAGzO!H>PJKx$dcF6A08&^;k5Pr$l zMB~<(h2xc}14h~dSXqiQ!;~yFf%DODr0;3QeU>a0Dz@;DY!sBG-lmN!iJ|DrQo8^8 z*x|C2o=xGI4};NyUluU?89H5PN;m0-t9{zSsGBIdLna_mRts zKhXp2p+@q_ypZ>z2Z~#%atEOY2jOYHPo`*rtAlc7FzK?>Whl`so@JbmJDCri7fWvQ z>Ght|^7VAj|3xQ+6aGFA*r#MmhyDlm4*LRhqeb|DY`Gs8y7-V;wsd0$xP31OyZlhH zo%W#zKjkcwPP7L8w}>9&9A8T&VHl>YR<8^{m6ZR|Nd$sB0EaT>kBY2cZpf6SZJ@8f6PaT+{n(f;El zcmL7its@5*l>D75=c}BrFH?EfHw&{1#s}xOCNr&yjb5PYdtu z`Uei~IGZ)j;|bw9_=TQ)%dEz_y@K%%p?#t&e^)bc+277Tf7yZSCMk{x;uWIFi9eb}+(36fE7~)UdDqpoxpC!k?Yp!_c=3+03iM4I^s*bcc9-Kn1b-0S zGZtUmx_lkJ-cKhEg7z(}5!WV*XU#u{Mh0o7?me36?-M?4?ldjt_spZ_bLR8rDYM#q z$*d%sW1DLt!sZ!@RZhiF@OD8kn9r5_J12X{sh0VJ=`VR z{H9Q0Uo+olQ=fbsj`987kyp01?ksq!2|C{9&U+p%qQLxTZBWy=eM0&i*?hru0ja&u3iL!a1Zn*AFt5F22D= zrB{6xJf7w%m}uUMLWP?Jk0h`u0yg#ZGYUMkE=0pOK}&FeVXr)?BYRwxWS{|%g);N{ zwI;fNkM;|xZ`2=Iz-FOW@E9{!P=ZQbLXR(-E=!)wZ{jtJX4t*uNpaPAs# zb#4Bb((U`Bqs(!YTSc4Ll$L>P$Vc*R2=zAeOm!R9li>dV@Q@!vk9{tC5w$zyuRyuH zr-Atkz+7WUSlH$F%Dz|QK*ovHdvi8}`4a36aEF&)fxhW@7@ToNnU|dj`@WwHJB#f6 zKm+xy`hab2U+4o*Y^^l;eRq0&=!X9X`;hK8pt0?T*Jw=9(~lfZWSia1Z#;5X_0=&4 zwW9aTmv2X=Grmu-7ZSWH8>9V#@iy!|0+F{ ztfgB6bVh4zHT_ziMrSsIiz_`k6QRD99-Udlx>?;`@YKoxov8^qn{_Wbvw5Q8Y8N*6 zbY?N*^JSw1?Z`&dqc!Mmv)Zu(>wMv}q5hIPe*N@DaA~K{|6S;f;HNom@zztzMC0xq zJR0&F8ub4$4MHz^oIhw#!~Y2y6gAjM|3*gojg0i+`RHS+(8v6(_3;$F@?{*KK8@rj zmft2H2*q2+J{_HFrL(CI8E^R~pnJQs@(%6&`TWNt;eyuKnNJr0MyU zk(Ry%lylBhJuVru0vU5My1XcU5D9o!kbi#r#HXyioBURMzlVhU9*`X_fL9Hij6Xm9 z^DWoWBLX?NcQAb$s6daju+6MXW=13aU|S*>O;4g_D1|0kSCFS zB*zW+f%WqOWO^)rDN;bJLBDZ0IkVugWsbSC`yvDv+bmZMgD&G90gv zkIUp^)`w_rcMf|$>aGkI^wna2-NHNzR_gDFeO)nfUti=*`Pb1`LyX~s;@>N_19A7` z*rl9P->){ufk#F-AH}v%eP{naN3eC+vqxTz_Y1z&_>c@X;ZFs8lVMZQbIkO2Pinqu z@bYdu@acZKf~b6jz&GU37o5595Xf~WI43l}2sor%wWc4^}7uiPhm zaHgZv5KcH|XUSvd-rsKYFy{o*RU`NJs28v3SJ_|Dro1%x$~U*x(twhf_EO#K9km{N z#%n#ferIRa4f&k)uUybRfF3sJca|QTQENqQ)yW6lTPOZHavqKMmrgfZN+LCH81N~^ zUScyg*}dVPme-8xF7Fssv?qJ?^gXLbe_+qS(ew7i#>Dq*9#g%icg&4@YR3Nlo{q82 zd$OIDJ*%C^_8fG+xF;5A+p{^6*wY(XyQe1m);%5BwR^I2>h_2ZsqUIH4<4?L)O^)3 zWH!J$=96FM^g7SZ_ncXj?{hcsdDab zOWkiiRmuH|)P3yK_1xc@x<5GZVeW59-LD?Fh5MUR_t^svalbTm-_id^+~1hGuj&6B z_a9E(_nv%``wyk=H=o?b{o>Sp?Bp}t-;laLc;e5wUzECEeWHo`C8_)D6DzsDDRtlR z*2lPCp1QAj>t61c*?Ym*k4M7#Pwn%9{@mIxbz_4p`XHQ;UO>M^r@=S$$MJ#r{Q3Cd zmUn5c&wGRMM^uNtXZ~#bey0jsm@LIA0_qZe5q%#j6uE(db9vxHf zt4+^~hnK>eS5Ds4w}3r6emsx+aXUy{17CjlaKhcQr^Y+*L-_6wA5QVzePgP2zIa}I zXR^4cwZC|BtL3%ww-_DTnT5~ANIZA#FUfP2A0-9H5C08*havn9b?)Qtz2qC~+~e}6 z>BM2!md)7`I@NY!Fh+^fxQ#Qc9^!ai!SBnV1$CCEah@7D`wp>YQ_p>!t!HBu8Ry0$ zoGE$6%g53J49_YL4_A!Hm~7pZ1BAR+@bcnGwD~5_QRob{?YBWr5xq+&c7@+B{~h&} z2I?veJyERlBc+2aQZ#-7qapm%USnN|Ah)^+}O(>;i0 z__V}dAHUIc{(q?J{6DN`aCM#W|0{K!zo9X|IZv7XoAZ=k{ygQ^NMp`T&LyUXm2*FJ zIO5B>=$%q>EYvi(+%)}C7r6tZV>*FONiwc;z1f>lw!PD|Kln?^ zw*MKBZ3n}Ozdr_>sj=wl9CS(%&YQB4cXQg$V1KCGlrQC(CC{;st;D86aRsnM&&9Bj&7ztjx;=i^zWQRLZN z_8X6)*Vswijn6hVtlb$ouk}=TbgV5@^2#$4%-qsH$Z}&RqhERH>G;6x6^;F~bIq>1 zi8WJ;{5HGWS<>`!XieAq-?^?5;#MZZlgs{|Z*HMK-{iUyzp?rW%}ZnaJtA{0tNC4s%^2t2c`92?Z1?B&8~e~M@<^$VG5QGI-&I2& zV~wl(7lFI66~Eix^bzzz+ zbr07sawT?7?7Ml*OaIvW{Sf1MoZsbK**w|zdwBm@@ApZ5qnxyDB>rl{((&H!y033o z3jFQ!B+t>?*xyl}>kLxxspEOr`<>u<;pmp)hq!+oUF5}$clSTa*tRjQX6CYiF>79= z?-=%e74O-vEaH6w?@JpS`b+t)at*OR(2*R%m!L9~)4+T#uWZD|-`(4Eej6LE%0I|j zBOgV{nMa6~?Ajxbj%lxYCw_g{P{mxky}XW}(XPc8aI+eHRSvj?&GD8;!L579zx8Nj zTx&CU^(ryn7ZRI&GjP%VXmdgHQpIV|^Ln0lc+U^=ynyF|LxkU&mu%uiP4J#=qO6|P z@XUwfOWw1CJkzgaePn|sAJOJG&c%1q<_naW z?%~HhY487$xwmCP=QSAS{RZlIlrpOSTfDRQ6&lxoztr-c`OpITdKx(0$r#kvYQ{JC z+gTQm1~1H7qxcbhoW<8uhvqJ4@dsP$>3==;2p98Ab~IW)AJi2)^i{y^=v`*ZG4fj} zXO{5l)DP#E>NmM2bspf&OL0tXDQ;DyvEIdB#-*4O5yr0iXM6Pv_k-}!xE3<5Qr_#^ ze_&h||3kSARlGZmeU<2d#?wn&(o>U6XAONO@aS&Mo%Zeid*PX$<#_YiK(2x&Xip39 zXrFF&mD9#3=2T-Wq)yHUItQrV)<@nK(H(uOK3II94{h`z2bz^>j)QaXIyO9;LZ#V} z(fFK_k0J=8*Ss7HcMii_!7v?fhn`)D4N4Gi+Zcn3w?kzT(wScB=}f2TOl1l-zKh^X zHSni}@TqF})%Do;Ue^x)vNpawW55&q(zNy*>@;2nuA64ORQ%jT(V5)Uwb(nonPWOv zGbamyhv=0*uLI)+ugNiV<^xxNyMl>u$uHwDf7|XfYw~%gb###TRlJvNQY+^=tN0Dw z!ERD9&|G}dT9S{4)A-5$YRV{1nrLn2GL8KX_P4=zoDZbxI+Ekk1;1|po$U04yMu$| z%$#Wk)FwPQ7NN}`?g{Toz5EtQ`fu^yo6BQfKB@EQTcoiu^_|9il)NU&jp6XEcwH2n z(YNY{|D9;@V5RAVSI(hLOZ#;HeaBoe0Bss<%4#2+!gDr@ZIzjr3tkJ1#x11vk12U3-jVC9orx zXi2EJAqh-&oW$mixjf1@{#*)v)6Zc|i0=*c-<|jFnL6vk7V^KaeWYK)h0Bobl>5h= z|8Xy0sOXvNgCU>95cI)?b)n6dqHlyZq8UED$sRYgRd%(aAF=-!-2Lz5u#&x2w6V_S zN-2S#XkJ8b2A<3+{VsK$V*L!jL++)lp6gkIm-{LNoUGo6{?@V<&gVY;oWs5cer>V| zrChhJ-g%)9Pd%^27StcB|9+B*n(vz{O_BL6bD^1Ut})XY*6@GpL$l4R<_1$?t}`DZ zb@cks{}2Ba7}li8H-B&b0qDGsL!zh|Z7wyJ5w2)F$Cn=u{dfOwv8iIduQxU3Mq|d9 zF}V{iC>Y$R+|;@7h;i_W^WYid;T`0qUN-?9{wO!6n9d~g-LrC?jh`g0r5`g;v6%hX z())t>34H%I#q46ud`0sO_(VHi!?Xj7#g? zn2CzJp*Rp#$UCl$wek!VT6&h`%uoIFeO}hjRNVR{jORwi^MA;!5FUU&okE~6|j zv}e*QpgoUdFDn@xTC;ocIJtfeE<9cSD4(YxKTy}-(me}Pd+-Q*7UQ>RV~N4v zY+vvp@t^CwM{y>s9YR{JwKu(7Yl;yo8SUM^m8_>+Yggbif2!PcCcb=YyLd}8w6qxB zlK7?rF^V6LdTTLuo@>%eHGS}=_13BuP&^TgV=EWTH)+Ih4ZfyT1@MGSDcakUIA5T67 z52=so+#36li{kC2Atx1sueA?33SOYR(e2D*&sf$`{U`eUc^1qSg8;Jg#E^eqp`E|C zJ)9PQ4$h%`Q2hDReCpdwb13}rX}(}B{~q0^&eVtpC*C(Bc&^4=dNw2(=W!LVSI#_t z{%n0CeB;lba^>}3Ieh+#g7b%8gcl=vcHr0@lLLa7_BosS+Mz)wBpb1&9~|T2hh&PTPnq^6^jW3YXf4DK zqz8RkC3ajp*kieNT$B6m(tZnDFZu6B(5Izv0NZ5fHvS3)hl+_=+LGn8R)&lF^4D+J zx;HDYuZ_8NX^8xOUAbKE>sjY-X64)1w~N4)TIx|g2Hy^>j(cp%S|_rmox%B!cV#=R z(x1pCtQ?y#*?0*ajw!UdI&9n96~nfV_H-t%7^~8SsZ3W^zO^Y!x9{?E9}I4k{>_1g zN1)}|(DWQ=doH|+9GDBd{FffDa?jor-xgj)?#n3fmhLfy|L8J4A^ie=P5v2O9dsZ2 zHDWf`4$E_wu)M~#9~dO(+!0``vdV{7%{+;pm0-W!4ScjdRi7_Mx@*(D_xT0u$mY6R z<<%>?t?|2S)@^6#JJ;7!?XDW3UF?LGzct=;E~VZ~?Ys0MFU7CaPNs5xzx{p^M=>@7 zeU1BEbSWP>xF~kvIkw}DK|IbKgZSjRw4452=6<+5PJ91fq|Tw-f0`S2Y?^~^;P{Yo zq_WRqUMya|bw7N07V;1Kn_8{Q+3uR`hDO)-8LpVs3WSgie>XifpK>;;Rcm)o;&?G&5avraaEf!v-&0bJo-{yWV_9XT_ z_aC(HOWgO+nz_0sr>EYpV$J*gaER63_=j$6`bP9(!*hBnZc27X48KKk*4S8IG4_yW z$EKg0icPQbZrqfSb9(wQQ`)l5_6Oh2{7JX`7Jj1%emn2t4}OIG{?PhVUQahSW=ak9PCTG?yhF;zP-CP9ytbvX$L>8__79Pr7Ie0*^#3%Evm@-o+JC$#UBff4L@$ScN zxs5Z9YVck$+eKp~zeK-?zGg;bN#zo=<^ZsE8Y4?eeuS==--<)=(QG${o%pY4E;gW6 z&d~S@a@GHQ>qqCy9tqZ1gk19N>?gADb<+M9dWyP_Jj@Z{w{+d^I8}%J-m`zzo;m%Q zl}o?jwyEES_8sa|!gK5!}hS$h2j ze=7TIgmzMEn7BTtJ%6>+!1IOh?`KS}nR~m5Q`{XMy_0$BY|6nli?!Et`KIC?_G-x; zrt|0mHx43mVCkK05BT_fuw(LInp`lyB0A1o(Y`f~-q6G6|gHdFj!OZfp|K4s?vMZpy_!7}|X};>AIvUcVjLnhO_HHYqqT$5!5OZMKQ` zAz8)UCuMw3p9M3)$A?SunGdzMZJc1^4a>LR#tD81I0LWbiNQI$koS-60CrDf58ilJ ze=oQyow3$zH!$A5BmA=Zlb~Es58ZSRvG|}{t0_O9^1@}w2+oQ-`y=QLD|s*ZS~!;l z+}G#2d{=dK19QPI${N!iH9(GbC!IOlHP z;sbp%N7wv5iFY9mHIO%jpc=_Jk{qy^G9$3D&WJ`GO zvm5jGE;9T6CC8k8qcoJWxo_}KmiC3)?puA6xx95C{`_;ROxX(u^5?w}&Y#y2&fA-_ zKdb+_19^L2c&4m9!MH5#TFe;%@|Ez?##LWn&;ekR%)Usq_7Z6hvW&&TMC^rpxc zSAicr4f88Xv&cHusF z%v4DC?#7yNbw84Kdou znJd&6=_d@|_mrFsn^(+Z0F4(DR(@#niL zZN9(CJ~TxW!4vIK!=fj%hUiHLW&H0$Y2OnUxG)GOtq<*yolLx;Bk-t9I4RhwZ661_8`9SGjy+A-;QZD8M$d&b(P2z(LNeV$h%- zV52iT7Z*I;E8o2`(fw`}=Z3Dbj24$auVwxf zqh+mRY|1R;PdIP_T|+-Ib9O++&h}*NX}n+Q#nM$d#c0{gI8K$u~Wp$ ztEsz^*nIPd5284#`vY=z9pC%$Q!>Tm)BLC{)mz7Tu=u$z8)z*Z1FpgWKR>;dQLY5; zZ?Z3>9riJKN$BlMpSppZWW^JSr{CFfzqukE9)7%(PcB1$aQ}v-Jsv#VSSi^Zn*;FJ z?7`zc>J~hvf86TfI(ike<{q=_vsE8cFuDTm72fyFgnoY*x>C)YgA?g= zWj--K?R+0_^>OKAuR?C{$FH@bu{W`wN`iym!B*fX`fK;xZ3sTXz2?5ao*7uh`^@g! z$rJOng^!gB|NS+kIy3Rk>*$x$+`P1oT!2ksr$M|*`$h4qYW%8_x6iNWMeae~Dk}-m zpJnjPQ1+qTTjp0ZjBYK~vxd;roSMMeMKjRVB`i~hFR{U7i;KYnOk+B%PV>%78S=SMQE z^CQ%gX`L%qNf4)^$jH6eZ?uLDws<+&+K)hM%A*m^$iWZE_qu*9(lWP~`B@z?SLhvQ zEM>{BGH1+H^%s~k>a7P42a&IcK|H}(QNLF*H~fFDeV1bV4YkV4y^3-gb z#GapZsdFpgEH-9yE~0;PA8nc2bN&1ZA8!}VV;tZhXWwO#1$!2m&MNX8W#WZCZAkH3 zubt%SLEGmDu!sSRb>qqP`(5DGxNdLq-%Mu(@~8Tc@L;CC+qrnw?I&ybEc~`{g2C^H zuvMyi0v^Smc$6FWI&*yB>Abf*iuzQpLp+M_{WxMt#+|&J@jesptbZDu#x5WUUC`O4 za7waGLcE4pSvu=?&pKV6+4b8FXOif;yr(dzA(t^&%M2AztDH^2{)IICu0aU4aC9}pVRsg-D%*Q z+VWlW05jn+huEt$u~&JWy-E{%l~(pD!~`m94Yk_%M)1U#>@)uh+E&T+Ke<{S$=ZKS zzu|w!W^F6hndA?lZ_3f*uDSeJUk)@NY%EWZt(49S*K&?ISYXzmmrI?SG!8pgc5!5g zk4v}i&a-f%E^v-3xwXza$2|gW_;xBYmW z_au8U6Nz_DzKlJ$zyD<~+s$57>#mzTKbiKQ%lX!i%a@pDb|2-QGiDoGuR3aWUuyX* z`z+C-G+GkHmtM34Cwogv-V2{iBJV}uts0ALI~PLxN}+v`74`iwXtb{*;2FM@Jf}>Q z-^wZDRGB$X0>6{_W|wlu4$)#SU*ZvW&!|3Y&-g>eQ1Sz8rmu2oaRORgca>ei!}OD$J~N445*paBO8XY} zyOL4$O|U$0PU(bY3n=<{G(eY6fY+iS==nPfKCN?hVh^)tR)3_kZu;m-I&k_WT~`m~WK$x0r$Q5n zNuQj2xNzcK@RFC{C6(}!UU*3*yksG~q!(Ty9{}YdOrS6PeQ;DZi}rr8xk9>wLDo`| zbtD~v^k3L$4Mao3b%WnEA1MD_e+_wbwmkO(!}VX#HLXd1pV};1mSLZ|gnDewOkg?^ z46pnJV7NO=a)N97kO_AACf~x%>fj$PIA@rV|1br!il0~|7$Aj6NvF`#i z_;Mzgm8R7rJ|Z4+OO`WtB)VvInHk{!@20x^$KbK0hhD$#xVoB{r!MSt=8KKq>V5RZ zKWCN9kw8~izI;PPP55l)kRE`BbUcJH`rL`%1`6+kzr>F zp58|KJ>{0Qy1m)grgVGaeKG0wIA5^3J?8ERdvehReN%x>P?7sE| z3ds)2_afOLD5t&Cer_D=WF>l^X6Tr|pNpZd@b_~;dY(j1(%xpov3d0T7ukcYvu7V8 z)1oP6ihM9q^r&v#xzq4v%!g0Iotkr}NB;&rg3k_H_fKWLGd=2t$7Z5O>3c$d?cdJY zFTFm#Hwj{HS)^iT) zIk%`hUY>b9chAK?ERA+ab`(A)zBD*TcKyM9yd4XD!ya$RL+Cp+7U?{+N4DpE!E*?& z{{tx*Z{&Tr=!Z``SjX;OnrGd}CelgOB5O-0t@SNmA1li?49*b@BFNg6#6M}H50&T? z_H%XG=XbWCFOlx*Ypb6uU-7nl8ITjXpUeGC+(QG(EdArGl$;*mK4+`YI5X8OKOdO* z_xmm({~`BZgXXLJbo3+0{&~B(SNUf0Q_By_zmI$Ll)M3M{mhkkA8>W+pG?fr!2Le< zQJeVw1bcMVFFQVeZj+Jp zPjb%W$FlG8;=H@@_A~Fz9AK-xnfhsC-UC~34Z7;?&HOm{XUTJE{9%6vJ=T8aAd`+a z$iK8!($6o%&rl`E> zTcLgB+ew7}={K0nQ;Uu|;+caNoxx4?a^rF7i)=SX>Kg7$3g{AAW+ z2612I4tlsh#P^2I+T1g;Lida;O;_OKzR&aC%Y2QD`}w~T++QWT7wE7L(_cn60gaiX zGi~Le`2uGbZy}GhFsD&+CHm(wn$u*?1!Y0q$@&cVyFLwn#Y-G7*Pdwkz6oac=U6{) z2G7g?bNG3=qxFS8MC(iCTDfhUgyHvmG#g1clBj5RWv^_vWtC6Q#ke|B1 zA)VXSL(^*blb#`o4{pu{*oHwXpQXK=5Vrc1Q?4}SU1{QMpqb~oKSV!T$+M<>4qde0 z;+^xHU{9=jhkMDQdav?&mQDkFobva@|2N^(9AxSsoxvv3(^I-RnnYuSZ`h%wWMk2y zP;~fNs_f3uGgw`w>&N5L7wLOmOX)b>b)Y;sMtTNYuY49KrPha~6U=R`cz-}2VeheH z(|6T{_^a@zy*By?^tk!>4F3*xo*%*9^A7AjZ^!=gHf%#zv||ry{iO8W-OLmIzIm(p z<7_jpj=zub_j~+lZ~syL?&9xG{#Nlvn|Ukw`yKv1!rvYI-Ok@_{9VuAt^D1>-_86< zmXMBe8Go{4*B&1)HR}thXF98ty{VIp@6>|$z+&&+4c@iJyH<0Z@BO}(Yo+(we-`IH z%3lS4^Y|<0Z!Ui``MZL@%lT6~diDYDx1LSm?_&O>+tB-J;^8YkzihQ66HnsrxA;>% zdjCGIqA&W**^XP5`5;e(%~hduJAEhIFW?Wlo~N~?di0I>#dOwG%GR8^*w5KBBApxQ zJBL5XG`bJ*XTOu~iE{E$w)bhcz&EM*g$eBOq^n|{c6EEW;oCagY`$$idXE1wf9A%} zxtBk;dT$90F37?bISek20w+g{`Abb@~Bz4|Ks>q%s#!;EG9`RX@?UHpzfTg&_ZwVq!MF13y64)dYtFQ? zJ@$P`*=}927x^mJThOKdrF}lF?9aKDk8NJMlj|O?@T9zxg^DjpIqsj)mA?F$-gDi- zHAG*&L|nxo+jUKARXax@T;E%(W99zlZtS3lIF0sl+ED-b;i(t-F47CnNa> z{DAjXkAN+l%4L%`Ha2C*?g87}HC^m!5>I2JJOy9J6?eJ*;;XO|{)zlKT^}pop1)3U z9z2@OE_Hc`IS$dsd+6gT`rN?vAz&gJeRAxyGSTQg+}G(or=(0Y8r?;iXmmNSy_4%h zTx+>L$yGFZ4_DFX?{XE5K1u9H(ddVWXU!VV+rw2f`s5^2CK|0+BS~oL$0oKiAn@%UR2!(c3TGuyhvpA@K4dJqHf&0cdGy{9M;97c;{%Q^A zStdFnIw3!YTTTDmy(boQzGmr)=*Ex_qQCx`$JF}YKwJmc4omr2UA@4DR7`}SXBF6; zY~cJOiF~2BIBn3!^zVXrw?0?0!enHHYUuFw(Btc%%hy7miT!Zzf_CV&l@;EZc9^oi z)!e)zeJLsXI%TSW<8E{*tGLRpbvtzBFQr>4EGheQt^@49M==+=if?M2={)Nc@Jz5L z_2qDf^;*LDrSErRIMYsSK=wp#O~7Ll8_Yn6@6zjto?{)+KppaZl-%D2-7wJ1#Aez- zmQQS^jntT3zp@$h>lnP@lN!@GepBUrBOR0K7ahvtkGk`c@B#7s7U6C`X($#1T|90dNS`Lapi%(~1xXTD-?GJj#7CzZn2%q?awu>LEv!u++l z-TaODh}mcU)^wSJ#G3d=(@Unc;qCsj`4{iWIHFHv`tRFjmAT9Ou6f;j%)Da0XX=US z!MRMvvYEbb@an&3Sj+!m?nRYXV}5M9&Hd&mF+dy-SJc0Wp%0k{hLs=Q>wMmEMrQvT z{sv6tAM|F})qUocbl;rI|A*J?*E#1M`j!60P%r)7X1cmxm7D8A9}d7ESl2A0|AJ54 z-?xTt8{vzy%l^OeWLyR~{J$}_xOoU?r5ka<{pq`o@xLgMB&tsO$giy8J8$n?mh_#E_^)$EdxH zvqWccS*~4&^p1ZA&+&cVCI^1+_kRCYy!|BKxiKmh9InK+a5j2*#iuaDvvO2NzE}1} z*@ttEFuMwWGM&qFX2Bk6gZ5CIA&R$%_XhVp$@j(E6-yyiKk*Y55lgH~dLCVS6C%IYaEBjLKzmL3!a5#|WfvqENAQ8I zJZ{#=pU9El9(H!@M~G!t64P1CV2SCRDV_~%3~;uv$L=XLf50pCdxrZv8~t$vJNSC+ z;Hxi^pGu_RZEQ7qscW@qDOcUv_uD$(qi?C^4x0{gIWMreoLf1cX<`4G9FHCxd$v>H zh~gdoE57m0)y^{JzY|^F(&Sid`naMWd2C%6o3!wd{fYWveMB1{c5y4>jzchVDuBsF zp*3~nSlLAU$<+;Y^GYMxt<%|8f1iAa4>FFGh32^OG_IUvjtf@09*LOc_j|x-R*6QuWw6BHrto8koJ z5?>}eroL$%-3ATx*V4)Z(Z1FnVyo`Qrh1S5`1IBLck|8nPPqA9|6Nj8SXq;mHEv2I za`P2g<1U&oX3WhukIBos5XHdCsHs?azG*}!JK*56Z|Tz2*neTC11zjwY%^#Y395_^pv$-Ry{TF`?mtWr<;lkm^)kMeD`_j)S`*HuMCY^Q=Q8*@QC=5YntuV zSu+D$oKV(d<<*W`K1%u0>FmuZzwiTQt;&~pmt8x`d96> zZ_5=0`p9qpU6gjJZ=?-xTw15LyuJ^P%d2nLGu7kwnR1GU~TKXU0UM7hM!h{fk7R z+zGv+(G?fvj-PTz>F@krcy`08OUvetskpN8n#I*im+}d3O2e~xXuPM?Fy^B0y(ez@ z2E3PCFYB_14T1j=xziNeqXoS})WjQmh~q2X3!hruGq$KK`;jrru9&c`czLMc@`RaJ zz6*Q8%NeU;f?dY-iLCsx2iZ5vUgtsf)H?SmOFXqf&K7!l%MsuOI?f35z zivya7JmTgaK5@$do6B!-qjcD#(2MCbJCOA@A=gA78?yxc zHTuLb@=1fZ<)$r(m3)i1;3dQ?#pYt9b$ZhU%}eDkdDApER`XlqrCGX1+LdGu_cMp;r{!&)PA2K;WRmD)6mNC# zQe+%#Voq3noBR^E!-c=<&wOdC%zYdIX}$aBBgh`RhWtW{tS&c5v&9e6^|;9mwl9`u3;xpMica~uU?)Jc zyECo-;Q8HQ_xvt7tIEo~arSP#vx#Bi?RVj0eX&t&hqWB9j6u%Wfj zy)!|4ZYD;yhnMKwXCuC~C9I>kuB@Xf$4qIL~^p2lo3h zi+=cZVDq=Uhw}cr7d{_e!~8DS{=)VNUafWImzV5rpMQ1u^N|1ifcsqhAy`iJY9GEH z-f$EcXzi(9YhMBlXolZPCUnn36`wReCR+u!jEQagn=w`f6h5N|uyj}N=qu&id!IJS z*0>70a(8{p-odr6Ko4@3o}fi~0%CAzzN+Y-Yu~UCzFQ6dy&gV%9sKxO&MdAW_SL!T z3QW$JQ4_Py&nqY@o>pL{dUqxN7ycXS>AB@;>LN&!(I#$ysK=X;TcyP>gf6 zj=Z)IF^fOi{}yF>(7V+!*5NUU-92!02V(>eoyG^OKUStP!fAictnzNW`*$xd`9QF= z=X}=QXG-jC>~ZzXuhTE1*mi?WVH@9m5wt~ZNGJ3b=X-;L=nl~#o|b>mUC^s#?tC5N zw`)gKz?yT<3b8}7eRb`S-1ZeKUi`y7ACx_l>yI`RYklb16fZ{mN|WEv#$2a=lYC}D z``h$G>+?n4PZ51ZzU{^*r8^bBWT=mNUJLBIC%OCmKgHjCTezs9VSpI%_^cj1Fr<$V zJ(%vbfA+cNP+W@P{dQ?dH@ZXH4t+7eHwg`sJ`{SNMoVhIrG?;BHMn&>ICdShb^IZ_`yWS7nagXeVi9b;-^tZK7cSH&r#O@EBGFN)vp^~HbxPC2bt2&b*y*ws@? zFPR)Ky|J4IS@oC1&0oHV{3cyy$sOkSCoT+aIm#TchuzZkaLKarQ2hC1*i_sM-yBE3 zyXNCt_oGjK-uLZs!tv*|u1{<?3NtVLmkm^RoGj{2Udpi`+$kf(c6RUspqmW#ICS!)!^Xr zP0*A|%2ZK?{lGx&h1a&L56)=wa^3sgxl3%2AETMuRvdSAM7-DdlgR3N?&k*~M2aeDqbIM4zP$R8vcF$0UyBPXasXA<;hdHZPSHf2|W zW9=dEfoBQo(wbA;tgzS1NGkk-0gjByrRT}`r@JHtv9SP6+10F%&t~&iuF(y<(YI!tS91< zT~MYm)Y0Eu+eS`bAG#lBMMHm%p3$d!c>V%BwHrC*ABgXwa(B~KEAO5q#z+q1XyE=H zmDN4pmC!~LV?Dw*aq54a7#&(4Dt9;Ka)}+2%Xg~hGu)5kKKNa;?0k7%{r2FT%lJM* zeRos7iR)*m=N`tpm~Ux+;2zrhjCcJC?_Le%^!+%zdFyla@9!s{%fQ{dQ`;pb2j9=; zt##C+G31^a-2F293e~N8ZGR{)IJSEAjZ3T7oi}6W4O|(x+p9N+{?t)c^(Vu*9cu4T z|KM)fnDw!)1ot}H5Zrxu)qkdHUIci_Pojr!`oO!`XF~Iu_=|;B%CBRfhQ3r&?>NTT zOBvzB;&GvV-MeFT80+WkSX<~rE@kHcuZC4-OE&n)*tSgOp1I$p_UZ=*E!;D;xtTt% z4wdx3r#9)M+N|c=*BM7Pa~2B$OU8OP*9gyJz&kjWZ2JB>xUn{qYQSGvn9!4td)TlY&c8dwIvsr zHK#FCb6Ea)+INP|Pe%-u=NN(%G@YHN{8cVj*|JqQ= zEAZ1b^)s4Nxdp5F9U}Lf&KC9VrNFy{_b$hOw+216my~mq zG0q56cAn$~T7~_m_@-i7~=xNb-YxbG2FXG;`{IQ;se6N9d#Q z;dWg;zdGk9gS&qh+{*|%VvvSdW9egknD6&9r=Q^Z1nbn*mANq+MH{p~IEu}xzLP#e z&t!wJ9lSpVF6p_RS>G_(Td?PF%W8i#UGPip5!y+fTx_@ z>tH{rb5zOXzo&lEW)0W%^tYO;50Brwl!!7QhtyPNY**7e{HQ*jdguwY^9K=w{w)2Fd( zv}<~YyQcfO*F1~HE61AVNN`1-w&SaX#`t@rBzQV(zs7z8nVd73ciyiB=MY#7!wqO$ z>?m{WFea1GJD2shc?x?a;Z4 z_J-1{jpI-A!g_J-Rj7}B?6CTPnLQ^NR*rUpF!1*vciwp?&3^QwALakQ_j_QQdEjIJ zBf0JV?Z4W8W^De<^J2sPZ_K;-ZTS1tdCq8fs>|Q~GcUU@E#XWWT}70*JPx$mfp%|# zc4s%PUF+M3biq%)4_}PJiUt#UQ8 z`=<>*&XeEoE@C>JYrkLc`dy2?x!>;y_U3-S$&YErU(Yz(ky+}djYn@RZP`(ti-4`cqOH|FVqF~5Y3zCUIQ2aT6~fPbc& zz&}8Jn(FnbHqfUe=V0p7D!yTFW9Lv~a)>c0-xZBnFwnT`t~R?>#_x9*@I2SK>ht;? zzhG#tdhi?Z`yHICP4p>AZ0xhvK0Y zUp{_qDjw>ycJI+u&Aav*7xTUZx>`&89F?oqUgKI9Z$(!} z>La}HY}}s^zX{ z;Fi0V*)yFDKlYq{-&=s+=ih6;;4>+j7MxdbX{3Hd@p}*UD*-&y=au!A>Q@p!vAYBC z-W2fPd8c_59{TXse$QWHzn1v|uQS3WGV*-YVUrMqOA@?Fhf8$;*Q%MX_r2HoqWz5h zf;WvcUkP*x!G1-#PwyA7PR&=8eu-cE_7p*W-GW^2&xz!iVQawCA#{lc6_9WF0(^Wu zossNcOC&$Cf2l(T%R#1VKz_8oy!C5sj(geC_OSOq#r|Y(sq4!tU&h32Y@OIwUqpL@ zW#oOhq2#Fykvcq zPjbJ|E03J(`cry+&|a;JcN%+FjDEa-^b*Ol>T`nqcDAR}V2;pf)LWefwo)U8OaL^PxYTdU#M?iLH70cneN`uwWTraUx0ti-5UdJn{>`4v5zAeAZ`CsxHWl<|s1A6G z-5X}ABkb0(2i+0-ORGE5SZ#mM9r3$DeZh9g)g7HfUD6$$M0ce6q&wR7&CzSx*gtMN zINHW8+V+p5*X&0}mk};@&o~5^X7uqX*wB}5Z(QIv=WJ(>OSUkX>m6tr{+_*?au(JeoQ~Q3tL!g|&|w7pE7)V!YX9u*S?yUEdvd{UKYCDi@BGfbo^}m^ zr)y|azi$OsKkofr%WwH5>-iV?UFZGY%Wvs*^t_+ncY43)f%_}H-?#Gn4)6C`ey{L; zf05red%wTO+Fj=T?&tT7-tQvnT3MqwVJi%n)t&%oObu> z!qv0RYtvxm@3U_TebeZ__h3sbB_NSOz^)yG46jGvNHLnWqwxm`cK|? z>*a5M_xrPE&H6!q_p$%#F*EWbQ_mlj@$!!sVGo?~jma8yp8e9vH^vVifTjLR)S|*WZO7yYih*GUsoR9t^rN;Eb9-;IK!& zc;~18rS-l?4(ERC8*gm>dF|ocsvo@3fUfuTum9|ghEVpwhDUOrTFtfQ8;cIs@H@hJ z@1k$i9E^pWUcKvPAFH#D*NIQFgWq>Yy0$*L(|JlX?qc#n-Gd%_XXD-dJK^^`*$3al z^(&ll=uB%n<-fvt$*ZBfz8Rb`OYX`>|MDvJ-Nn0qqOKozI#0bC%I%wuZI^K5A48GN zx^IJCKfp<0DFV^_*jRmZRE&)@>(P92M_f`iRMgu1e+Gl#h$e`+|q zdg0NpA& z&RXbv59|GRm}8eNtNwHyY2lELbk_WKeVfvciq7-B<&p~YNpecC4*#3MnWjQHWyK3*FVN%j^uV{0m4ooqw}NRe zJR}8E>gl1LX2Dc-_}|QQ`|P)8We4UbmG3Ih&N1f9wKEyAQA$2@ZF@I%Q2Opg)~D60 zUy80Cc>y|L^`zabl_MT((rt*kIY+7$@0;oBYn8*I37ewU*Ihp*J1(z}mY>oGA8-Dh zHFX5vt)tYherbJK9q??gPWqu|)xe?M^Y^I&2VH)81M6-P>#v4&xRCW&jqMOIlot%; z;FO-Yo4SDeF5wI^Y@Xye!Or1NzABRAU@We#n6WVCUD6}lZ#@`jjOdVetFBsIp*89k zaC3FkdM_Iz4+bjN{d4ZU{`=)K*|S8U38m2M2(&r^oz7YF$l>fWwTDHods6f|V(E1O zHWV(+jyzQZz1DfI`gzMEk*BaT+V#>H^KvXy&})E^>`!#ocz`+W%YJ3++8-1=C0<<2 zUw>9)a|8JGiN>}4-v%~M@cRj_t;lXop~Ajqz8B4I3KjGn>(nyvf&+_z@CXXBFhh}YS%i1#UZfVy?&46Pd|fi7c9Gf>!O+Uw2(mKVmq;h+Nx zg=T)~Yry@*teIcRaxR<}pFU&Sr&+77o@b7CooYI~gElm_O2#H%K4>;}PNr;n(e!Ef zhjm0u>6e7RGcIe{>cjd$#=^Pe%O!lHJ_{aCa}`XqmnsSsZWcU}z@`Y;)YH!>@MxhQ z((P`_G6P!EN#;5mo0-kJ4;jkL>le-J0zM8r&+peh>ZYwe^)&*#qT35Bzr>edv#ooa z)2i<^?j!VF}kS)cVAO0J7DZWt98;xy0x+0A!dKw#9{8^jdaBX7in1fp8q)xO4eY4t-jnXIZ ztrWZ~8>9V#@iz7$>ybmqIn~+uR;(AZy+gqRAnfH`KpKGb3 ziTdNzuezJ4w~Xh)d&xh~HO}tO1y7!XMqX^;liQ*Di_tlKhWfRBUQoS^^()l-t=)M~ zy?}hQ&y#s}QjhNA+<%<woaa2} z^>)3Fw0?lRx4@S=jZdoO%04&BF$OvmK>WR@?|t)qe|-tpGnRR?3Gt^4)Q7RL+293y1ZprmzSC#J-Z8S;JeTTTFYo@`}Q^q_~eKE zpmi$b^Et;qyp8w`pKL}OTZ=coulG@`^};$lMOP5_Ydz3QWp9{L=Lu)#pWOl9xfi}6 zty4Y^zl`R|Xb*b1(;c$O4(!{W`zED-1Lprf{9g(C{8PJriT*tIL#LqMH*p5#bN^jy z_aAza`)2GNqL5X=DEL3tNvofL%pV6o=o~bl$||5zTOVd zq&$Dm%GVXYhd2uD%DXREo4bKOIx1Z+Tv5$()P0s;ujQF6Gn`Gm``t7Gc zm*N9&5PTuu_F{R^CwQRv!c=~B+0oYMm;HV@M02o)Wrq*(9(*Did!TUz^t~fxhyPJQ z_D%6K$p4^w;a3DPZu8*?>=zY!JNR;1U-yZ@@(#~?jG8Y zBL9teN^1$|n?5uqMs4U-_>k{0Jlvoo%-}G-Ghy!{jT`86elowr*+jhQ@R(7YVSzAaPONlFo%H9o?;)Pli#->gMH8@veH&Sd$j?guZ-d)Na%AWmI1}d_1&61BI~bJFk#VCyk=B@{_P_ zk^CE5*FxC%)t1B#jI(xo(0`sLCv{^zad{u+qDzn#)-Dc^&qmM4U+h3y^N`k);Ms!n z^B#7NvURifc0*=Q!vB%5&yaYiyl=b&`Fw`W z>F{WrXYr6cx&w1OowOHm557;JF84uitKc`hHhOf&LeQ|@n%MUq>iLP$quBksmc%|K z-gV&14Zr*Pw@xD6r%<+^V@>=jYf?wIC8=X`q15?4+NgsMtl#_d4fu^b+8&s*cQby| zTJ<^ds6OaMxgX_z(UR0x{D9Q|1j0#vAB?tj5YIjUJ(Zx}1HWjE)zS@Hit@60)dg8? zZ3nMD96h;X5@bdC(aoOISi@Ced-S|zQpdNKNufs*rGa&%dsst7*t1BRcz5CMBIw(E z=-oW%-(2)N3PT@{yrrLf7iue>fls5ffkWx(#9i(X?JFQXx62c|XMpF&&&tpFZ-3;> zLiqEv#`;O@F9@Q1A0hnC+mD_(VR7J{f%6_-j^~rC<2&Y9C-=2Ord0nGEY2Ny*oNoF z&q~id*tO|QsH^7;`Nn%tR@=aOv~836Zpv!kwvEWt;Mr#OQaM_(F#likC654tv4CU!q%v3H!rXZ^i%LhCnN+uyd~|7NFq zrNdMYDmHv)_Cp&y{q-AC`*&XWLTD$xH^AQse$^d%9vDimWttRP2VPShISb#s;+tRX zuOPl#QpqQU-*{Euhu}Na5iIP1Jjh?xmjU8C2LFgX8sry3)-WWeCwisMwW5w0;YfBk zFTd*`lO4B{dVMwOf8|MS2S{cZ*Xg1@7xgjhqR&O^_^E$!2)sUle#LTCpNsk%t02pA zO`mHMtG~R@g>jC39?|Dogg(To&;;l~q|b$SMsA{e>T_)xNBfQ^u2%Y7#VC6ZuFNOg*CIZIK;z&0T8h0To#p2l{JpRBDeh~*=RQq-x8=&!f9k$g zeEUh~iv6TtkL)LXU$vjquIwi*Wd2EHKk3(F_mh6;e$M&f*O{#s`$-S1vB8wQ9qIP zdQHV1uS)E*qWL+pd3V8%QlIip*w7UtrNfU~C$n*|7cG$cy9^-d1-n~%V+>mP~vaP(hKeBT{94*xnC`BA=)BENjOV;lJq zsqpJ)>|he|OGRIR`g3;sI~ezwyggOEn)xczkcUm4vWf07=7ToVfj)C#{`D9iSb#J= zR2HO1V{T8NP3;&*zMRxlG5*1An`9|(BHC!)&e}T`7P$+OR{Qfka?)xV15JnjMeX`j zw2L%eP5a@{e}LThII0up3~WW&_F?}}Kl%ebBd4&o;Sj>8UBDR==+7U#**+FymA#(2^ow|3Aq^myIpqsHqLIuAl#B)9LX z+JrCR`C@Wr&^?U_3s?p*ITDB zUyb~rg-GLWq(NbAsI#@uUpw?S9d*1Hzv*2u)TcZ(*IjTN{@UqVq|T2JmiR~59*fj; zJI2r6vnF<9uNUId*)tgThAmO=Z(RlZ^dkCOG(UF&I<^RNKZJE!Hf@^&yW+*((`R5; zdf~esw_e%x2>j_8vb*4V*jBPDUf3YAD;PI@7HM>nZAk*%x1(&-9-Om|MStZ=)*m_z zzMg_T`~4E^zfCF(wPCDo0r*0+*)YZkeIM|nUugq>sH`@>zuyM?dWd{;agT-KY&}a# z>*xE4N9WPUBHljw0gX|b)~RscJHEE`ukUPzztwVU$EocYyImFR{O{L_{_V`|6aVSI zVZ*x)9I6U{twwu??a)%PV za_4&V6)RBJPojnPi3}_{7;DYRm8g%@jUB#(61jv zoIw^Rb=^Vq?Khl9U;a)SH&15cFXu4U@-F)HwKJrUAAR~=Xde$+zQX$R2k*Ov_2&;- zzTE$2rF^&o?e@X@t`7I{{{VaP1jYuAP~V^R@gwKIpi*d{@?Ar}Lohv4p7K{^B>~e(J~nz5hP+Tq*I7e1>+WJGQR&aqww% z{HwnO-|Fx4r<(cGPq0r<`}K_8v81foBR!=#5ZhSzL|3>^e;572*7w|@TIlRK%!xhv z4R=4)cbdme#XE#IU~h8^^!q`K$G?iXz%;Z^cKB$Cc8tTz=zl%mzRd!^({`co;YUW> zx|d_z{~+cO_}Hxj=V00}%#Cw;;iK9{P3owH-C6adJG2^U(tLg*<`&A4<_yd&>>RzR z?>^82`KF0z5~b_q4xK>csn_w+(*Jg0W$|OXQFDzS%xedVZIf@25E?Jz7xb(PxX~ za~FJQnxEN&y%$P8HzH0C+DKcnqr;v&zN7bZmQc@ia)`=FX_DQ=+TsBkOE`KRA5RFv zCm^2D`hkOJ_qR@y4zuTIn+QXD{wl!3o{EO-jQq6bfVD7(S zMBB|rlMn{{jH%M$1+uNX*P7O4JALoBux_P;=Ex-Y5R~3B(AWzfdq2+js(nuiEfzE{ z9Gv^+PMk+$PfqNxB~R{fLI;xPNr#g#C$m|e)V*4EbZ^Go%xapSfnL0bd6U)nu0)&b)NPvnw$AP=4QqspTijYzp+Z{ zoGD+~vDI>A$5`~+Pg_TK^{_C7v0^CHsSh5R0Z?xsQ)9};sj zqzhPQ+L3}ZAv`7nZF$H?h^IW$pqE6a3+eRZyW+E$H<%`e9$_}0k5#RM%qCKQ1K+e( zuogZDTL+5uSu|F16#A_9&K>1_JD&ufDn1;H;nNSHOQZw%g!?pPCzSC4E6Ob6Lt)3i z%gBJd`@DH@`8_Ss0=`$QP#d z`%`hI{F-I%PzZB}c<;Kd?RgJ&iEPggVSDbNIY-3fb8h45j9QiLN$E&J8Eo)b$tI+r zt}jQw(uTU4W|y9q#2h5e{r19-{MG1*9ku_5^DuBvb$1l%!HbwzuqTf~JxJ+5xyw(W zPA-(kcQ1zSKZUu;*P-`2q5rG!{UrE9^Q5%D>_dDz@%??wQT`lyLG|EeJWona>R63? znop#-R0qC^Ixq@(yn#CK1L*zr^4N~&En_?O7D}C`RCQo1>cB3{Pww5o>%dM?2cAY9 z7z9u1L>*XzIxrFXPx`tR`uc6Aul$U!wb0XcJnyAGu}Ww4)`O{a!>He9t023~$4sg1 z_yFU96(}d2+x#Vzf9+?nKg441n@h69oFny(v~9^G$nrfp{|e^}k}N04mTpC!q(6*K zv?C--*f1u`NsuMpAG0qFvRnXJI)yB0jR3uibj_1er~to7j%j10&QY|+#yYWY0+Zz= zCd=cHCC$6fge*77qdGbu!}XA5v5@5n=mg2~IKD}i$*^f;zutxYB3UMa#|v?viuq@X zOR}sJviwKLax`rFYnCw`+uENQ)!dahY5%k{Jt9cex#WVuLX&+N(ej*2_cztPwp zT5m|QJak`bKWl4I7crhQpk8y{?1*8edfw0@d2uzr)JVEtUV zwZbCrrM^&wC1GzZe4Pr5bual6@M-aGT==HI(mkCirTosJ^L<2`dT}e}5*-{@F&F+m z(y?6wTG)HLq;a*#yB74@M!5&@?qHlVMC;yCyXZNU?KtLwSf2pxyt`gI%D3(?$U`i8G!?!(?;$GLpzSkG>s zinHo1QjYC2?t(p*v|O?)gmqh_Jn|jX7zr3wHmt2C+Ogi(CByes$CHq@&FMaXaMqut z_1$Mj&Q<&jM%Txpk3sthKR~}zy`S)Q$b1iYLUhnvJLPA8=&Sv9$=*R{3BC%NX&=*B z=nK*2$J(tKD8p+ggR=58hNDj+*|S z>o~uOCS|Ub;*$&&S$%-HEw!Ae4^QitSzlh@6+KnwLv+&TIQXIPUFj21IGqdp(Mk)} zCRnk?F9B=)u&(rOyi@Lexl=iBN#PUiwWe_cHNS{23rBFiDDO0D)8h}Y#Gf@N`%k~+ zKJY7)^&Pxh_C?5dDty=8d3;SU(G;#H2%~$Z572em14lYRXJ*sb1UnMNVxvAE-SUdMnA@U&5!~dIjDyW$&Z?nY7M?*78k!Y3DXt6PiSI z3p}AR(i(M}OVm4QQr}dp1s=qj!bMmUJNQ-Uv~nKwd(chjeCJJc<}=QIrguX0LcY{T z>V>VC%+7tD%y^DD(&s2H)~0uTD9(N+9Icz@`^x$HjXA6H@`;Y)R;)vTO(HsI4!00z z#&X&ak8By9L;h@CfpQiz^{rk)Io`62?|v8bUau;Xa>jI|Tod}dpnoU!B9Uxx-dz{* zPN{da)`ZJDc0TrFs)MRE4nzy_yjFECG+{{};;}nqW9Z%M+WLe8_n4hQ-*!fuUR?rC zu}epSV85tdewu7j#=6gB z2vh*hBEna_}ui6<5I0KEo24@ZKZgPI6IZ?9Tc%u_r z>Fv(z8k@W;>%GoELzPde3N$naoh|-`U{e5Fl+DqnLmQpdXS>+1XsKBp^Dy0xUNWL9&qdRBH$hE!I%%u}?y+|yXw+U&3L z)_IzP0p#ZMRJPRA_?p=BMGKaC*0j{E_BMFxef5E+R!@DP+E<5!7_`aT>Zz&ou59)+ zHu>xQLH`<`r>dn6*{ux28w1TjPqnWxSnH_@tnpC};jC+@biRh5r@7W!?Q8O&XuhVp zK-Fp%WAQQ|>Kj{vKIJ*$_}6$Tn`R;b5r~3dlebEpqc%(@8iMM5&9x$3X^pQ6WtY5l z$lHrwv&+A5(@o;em)7jR%Ljfpq&q*?@HwY%U6s#Q-R!LQuJhNo)H|D78XE&mL2#Pl zNtIqO6Rd1fC_+}v-ulKmpQqm2yxK!7X!2KsPikf$(i*>SEhXgfHlYBS3J03O5nq5k z^)&e!hy#MTz^wEI>U}{-MewiD+uR(iZ3?uktX1$@7FT+kTC2eFCVy2}3<4ddz>jR! zdFs5aDlHIks++uPJ&oQbFY@&@HEWXqwGCDNI*)H16@@(|6%yb|Vkr+TyluV`inw+D zDu2)e&IFNfIQ1~R8dayt=UIt@HHHK0Tk4<)U|N`la8dmYYe9z$!BF_i&CyyZ(R*) zdcYg>)cAr`wbIHuPni!CRzsbZ3C+C?`n`CWsF?bCtA>>ZAQ{LA5Cp3e5lN7A)HMRJ z6ilhFi2zD&W^&b}A3=K?0u64dCeTC%#F>?O1Ek{Q*1#ETZS;|CMiggmHhaTpk*}T?&*Iji!sik3cLtt%#b7fs~ofo-O`WwJBGWjHuKtoJ~7JAMkq^c$U zdNR$BKsA#w{p1R%iW62_vNXg*dWI?$Y-vL6@sfslD*fK(DC|(rBZ|$luL%T#u=EW< zX{oQd9Q+BZ;ZTi;p)N6W@#6BL5=GCb0ayttYg!trh&RpL4ywwiu^}s~8U!{>N^?sk zvlN~+0o2ckEl_csn!ZTc!T?yFAX7=y^?HAEGwDQ2GpeOR&gY$I+Eyc=fi(e84w#v$ zT4%7<8)NLyj?|+is0y@Dqvi=TMl1p~P+x2DLC8W!%6;{X(&9ivnXeud-d{CqzOS-n zWhrsGCR{FPo2OYsKxM57#3+t;<;o@>ns0~ge+d{22FOWvMAla46Qd9|zT0`ixr{3RyW>dnlbbdV} zzRkX{uaaHLw^97dot{xXe=Ff-!Td@XoGNcK)H_%}u1_N~S$``GxX5yr1znkSzJ`_X zdExEBvqXTaF0c~zfZtzax_^iLb#j38CD0P|1Zv<^HlTwP$Axhvbd@Cu>kA}|ok^Il zm0og4(#!b#1fN&%`6)jCiO<9MY{iG-(}ynQo8L(irH4J?Y@yD0@f%~w5-o1Pc#wp- zefCYi)gQ|H9i;t#`1~(EZ{TwnA9Wo1O_v_cFzh&t2#5Uy0Xgas;tb+%rD5v z%gD&jb>*cGEA6_vHTBM{s;q*n8eg6_&*#dj%&4jKW_zpha=aNXuQxY8t2)n{Q|WS5 zRU_$e@k&aT-R5LvX3jc+hgK+4}L2&Mwc_0*8`5ml=p1$>=a?b&v@QW1g#LynW56*EyZaQaSq~lG+mtk zl+SJvr!giDm*Fc49VFxBTAd!tY&gc(*`@G+%7e2G+4Tzj*VZYjhX|&4(-SCyB()PS zW76mGh*u>do*Ta-{IIe7YsIq)dWOr1&pjgS6$*&Se=Ms@yF{F7%G*TWiQYFve6@ZZ z6JgnuPgqWzF4l-6SVUp8(qS!hsl(Dl7}F0tqr7J8gq4agh0hePS|@CsPS|Em81ZzM z2-DI&9nW46&racYEdRJ%$R6zw@!Fvu3SIhk*TL*K9r8z)oAfD4Zx94U;( z^8#~hX*?L-wh)ck!b$6ee9ZIWI45xX1nv#06Hz>)_LJ9}Eh5fFb=tb^mV?RECJ3PP z=_0+w`%Kv7=(Va&-ux@znmop>+kguS5&Bbn|H zVQ+(9;^z>yB!#s@N;>=1b;eMiQ&{;*$dSgiS=d$LO@#U287Pfp@r>HNa2ip1n#_E=dqlin6K`~Na~$)jh>v?jT*cpTBJ2eb zwt(GOJ!hTt9%CynCh@`UF>_3;%E*9rNB={A%(ua6{``P6a3b&US0~FPr zUK&RmMl^2~@!N*t%k~r|%Y!1Wo-BVYo(-iBB(DU~s4*W=mq*-2%oOqV5M8(k>lR^V zdDMz{%r}maRiv%jBI3;)vg{Gw9~AN3M39>IxFy;24Doy>p6^$lt8Ie;eUx4Xb&hfA z$(o**is$zb{hE5?L{Ou6?!KNPYkV~X5l^>@IOj-T4CFz1y&&T4ro5tPPG)8QwRoOP z>1b#n{CV*_h44|d@V57ecup^hi?==yPs?fW0M{P!J51`26Hzvb_*mznp@aLttp1BQ zOwSRG!d}n`dqXGem(h44({LD9^Dp*oCWv z{Zr~E&vT~1GfHNGc&6sj3K6Exvr&XmUUbp3jUr4fo5ys*o)%%$M$kprgPJf(_lP=7 z)xOiSQ{veI{0{3qe$umK8sx*}rhiJEz)yOXHpH{}>SroB5q%ZnnVJVd5vJCib`h2U z3|$m|hfcg_bmG0D6ZW=F*h!r*HmHfb)cMjuopjCQUyPPCO&G~wwg@XRwA0+TAU&)V zaqpotHMW+Xw~ObE^gPVN$T-Iy@q9Bq*TEk$!S|Xxw+ZDl%0Ep!XY}jPw?I7Ks6#*5 z+gkCwpPn1EX-+)aqNEekrg5K+;_MS~n2!*}3*KIkY?O3pY)#R#*nD|k=>?Hqg*vXH z|1{>Qj13~)Y! z^4lt&)A(IH`6bhUJ}#sDW{T%V`6Y;#nzvhxw$@aY|z*P0ZlRpnu`#Hs(((5YJdY&!8+M z(?$_*3egr$gV%E^YdD=aWp+@cXC$*8@!Uve`xUz5%rAo&fy*erQt@0bKjL+xc-~Km z81RYen34|l$-*)*sbhp|7wNB1k9(Nl(txwkSG}MB6HE zlZg-0MV!}%Q6AEn-2!K(GaE&`_{Mo6{CYv)s2>%UkAZz5da`MP6W36ES>n?Q5ltCRoFXpOnK12Id5C@|k^Y#7Z^Wzp;<+BLrUU=Bcy3l_lyscK;1ki8 zPm}t%^ys7VE*H<^8S^4~+eQ4L=%ski#1YSlcyEh%4w9peju4IeM4Wj2qnWgb0heBx zi6hOXP7RYKb@e`0VBPk`1sI#FI`N>4D^NK9TM@F&tuT8QoK`frkCPGWL#$H zxt%PUWG1)TIOA=JBOcYgMiCEZVnpgwOu5HO6m5ryy9>X=bua9DasTb0h~reJ7sc;n z=J)lAc;;;d_ZLX+Q>Nk{u6^pX4Q)5KEu{i8TaD4s!xEj@ZAQm`yuFl>cs@_Fm2WU&P+%30gw z5Bez4I=wWqMH)3jCNkeuG;{$M_|^@pfMxj}J!;}AQC)M9|5CuKBH*wBW!}oy(U%7x zEmjhbE33Si7FpN(s{L5~tX3(N__EY$!^KBp$Urhn*s9iM=uuOk+8gxFs%oZH%wa+P zX)@1hZd~KaCY{5Uk?NAbO00Y@DmA1@U5hR&6XKvS7iK5`5 z6H!w#d=9G7IwZs?2X!hc8Uz<;b0anu8kjz{D$w2~?5?VUjmPGdChQrY9Sz~S7$YQ; zlrM#>9DjXf3+xHn15YmP4XpF2+L~cflH2SHf&)dR`sO_@KIJw0e5(UBHAU+{QNBOW z?4cEvEVSC+RHU+(!z7L+fvuWoUOm}0_)%O?U)dZ4=RLuqOGr1nxwWB6RZUcikrQt0 z(IgtHMnQ9JU@f-Av|d^=x$Bx&`hpFY#QlO6+JA{{aBDBAL^&rW*1U?T~V&HJZMN2+yV`b&hZRz7AMP2{Zep9?~gGwGJJl<*^XL2SLJETuOI8(k1)&26+vCC9NOtc&Q7TRvT7FL+=l2Y3Ra+C6yYv*fnWq7NriyNxy zTB><-V%+6%#r6yqm$}rwE9>%<6{y_usH`%PRna+Y=mH0Ykg&)4lZ!m-&P!Z@g(e@!wbFK zDJwjRGu?bf@jN<`0b4e2Z(zI*6P}qNdL+>iB3?|Kxp2OqPm0}>Md8$Q%a;+msILHR zQFtU`T{Mq|naeQwmBILR`%neR6g=aRE}|S4k;gDgk5Na6+}$rU9j3r8Hb zafZz_QC+ZyuBz53hj4Y_u`YsL z7nRHK7^N6QY`HcsNg0n7;a1puDtf5jhz~5jRdxp;Iy37*A378#dWW$%jZq z-sr?N@EA8?3%`Pgcg4?)gO}!4EO@OX^K?U~fdot*J3|B5W&8no> zc&Dovo?cT6Yxbkv;@HPg#xv%ztAP3f^k8I z@HAsc0_P?LYm1jI!qYWN)GS;S;bDdchb+-iS8UjbPS>grG!!$jXW|*}%cu`7Q1@q| zlF^CECPS3ksyzW=UZz1$L@6V6MKt}7ye1z;iP!jwRI&&YF$9i8$_`H=ap8C;4^C5J z6)D?;<8OkVuojkOc}glXic0D;NbyMV3w#YUh2!zp6fbXXA}0HrJvbg{t+%NS+4ZN z#bA}fqR8AEGDo11Dzc~1su&}^QvK{zioi35M7@nTBd=Ol7yhbEX(o&(jt8pq;si7y zx7EH@oD#RPnGEbgHaMN>YV`Z6d~5y9bg-PTR2aF1v~z+jIDD>n;Sy%z5wh4*ypUwc zbS%5k>xU8y(?(--fXwv##wE}_J*EF^ZrgI3eAM#%?P($^;gCfSkLQ!)q&vk8JyTU} z8pp~N)jGPxRW(^K!RmA`w#`z^AM%MNqAYVr8%9qJY*?%_7>{3;i*xzV3}{@8uwl%E z4~R7aID``?&Ee2bkGF-lBaih-A zkNgvoP0bMby&mB#6a7mWiTWbr&tTpe`DomjNQ=vEA)LM!97R2xxkyK$bWylFpHogp z^A+(9fU5w0Gu(b2mCjT3HlaDs@qkki0puXdu=lU3qD(SHc{n99*c52xixW^IWB9G7 zbvzm^oDpK?1gTO-z))$gB1!6`9A9&DYJ1tw4no(M+<&R1`&HF?dDloN;D!a)&dE)8t%9-g3(^rN; z030YgkB$kZAugqyqU{)V%2{Zfu@E2_wa|-Nq1d#CO?Fmp6;@3KeOM_sPt3R7(iEs? zzuClFA)T15lN0i$39{Vsn5cMR<*@bfPejJ>MCi)#R?)%k^XO=|5}XFCQ|yTFqNR#4 z82EG<9xA+&Yjlk0fi2Cms8OxxXReG|9BB@nuSD%oEk9kPiI$0IIFUOxqBb6uO5Ni3 z)m1OXIpb8quzwuubnA}5V(g?52jF=kV-=cp!dl8`$d|k(mf=t(K)eWLCK2b-S@6sk z8zN!`4K}j_;-grn;YfV3GLcrqObwA~+!3>oB6pt3aJv0avZa`}vBSmZ1+eaSh|D7~ zmj>1j88Z)QVr90kiPdm33Zi2#M)zn4Dl&-$^IGa#(3as`^msDJBq0=ID27g}j|bqQ zl7=Hjl~f~MC%|Vh&eRw|u4q!G@En*18DGi_3uV#pbgrOsA$jJ9Mmti%eH%etS zaa`F-q$OB;Ulp}3T@w|_aV1mJ7aNDG*AQ{?{LPHrLqu_9f-0zTwP{3>LD#1S7)Y-%LyGu~OYME`++I(Tj2BA<`@GHw#a3h)9rXF`a%tL=>b`)>7F> z&Wy3)L8NjlVaH+kLqsC2y}hBOnY>oB#sJI+S1r<$p_0vmgA@dFnxSy^2mLp zRo04#yekGaRoZYiT<$}cH8Vp=H%>)&Wh($v$+~issOAE8g{j6F_@*gm<|-+d;guME zIOTV-_b6za2c^cj^2*EV;Rx{R#s&iP{T#iBQBF_T3kiGb;XE?RS@Mhq=5%WP4?fPA zD+cmN^cY83+k}xBnvNhwc_5LCPgZneD=$4ckIh zHrG>B(8ODiDj$X)#7q_z6pFd5#pquYm-5j+#KxbYX67rRD86$sxt0-0M$}rX=0&&H zA#u!EVeF$aYNAr%ChvsAq^+$57oAX8-Bgw2ViPl}Ll>J~Y!$oclwxb(MJE;Jn5u$a zY+^&#U&B;mDjy9jsyf9qm}oQ=iD%Kn*qVO3!3HH51ZA{iUH~sofy*^ycPqYBRlRUN zN>Ippbd+-RDij{hdU~!bg@9Y=bz8)gr@B;YFzr$A%st6T>8^dR^4&wVOB3c8U@8Wqu;6q0+T&-A<(d9 z`NgCdTUmzq;VCg{SfZEF@i{&Lh%ARwfwGk8%%SFY{Bf_}Sh|P`u(+(`;wN|b+$g** zKEHU0%QrratiJT>@@Xv9<)|3(v^!9+p=t-rI3_F+<8m$;RoBqVJ01FowmU=E97r#A z?OJ?3lq(aPo6$WK1Lm=FDUps@bb_wD;s!XZ{>W%BW_iMsJW)Os*rayuA`3jo=2fcR zW@@nXM*ZF*^#DlNa7R{_Mn#QTE~Eeqb_zpIcL`H`Uxw0|E8}!pOD6M(XTaco6YKkIVok2#ig15Mo8?DPUTu&M44Ax`hL~pP@ zyzK-oxq7=toIJ@@Eh347EAge8mBBTV&DDvCwp+w|oabTwMZK>-M{M&AtLQ~6$GNoZ zhNndseWepM^S5RpL>0l;mOgxUCdQ>Rl z{6)qnqVzeZ3G14%BiH13p{Q*t>M^8vw}lZK=j9vTMyohAT}TWK84eO8UmeS%Xghq=IWj7*-Jr&1sr8FBDKRxxZ74s5#3|J& zPSUc(>hG4yl}&+`#!nH`J~7IM$1ztn)_tOivV~Vza1_1sK0dBzWzJ&`uS#3_3QZOJ z6)VH^FZjT2-_*n}S2N^UxI6b3~G zkD`HU^PX+Ge=95g9olFP*e?6UWs5F;a5Vd}4vu1w{?ozZOCL=7)D%T`SSh|*>7sSl zwO$3*+V!gNt)j&1c+4L@`iA z``Gd?rQM}7Yp?=&X!Qdk?rE3sxh7w{_(pT?WoDI})p{DARZum; z;dKa6rk#6=1_J@`Qnj-{VVe+bcP@IYL1&~vKMUP~9__FO^HYs%9P?tMmr#VWiqFE) zWQbDkIF5*7O{Ix3TZR1%NR_vba8nd}WVkj$03v2g1D`5G;8C+ zB~)w^IhZP1m{)CJ;_=MDBr1uOx|E|-Y3p)y%DiV_WN?ReDla|#q1p~tTyKfMdOp>@ z%rGAnaG)7uwTAD-!uu4cw;R1_Z{8 z=TdUPN^Z)9PJ7Jv5INy@!4x4l(&ry0m$E=p5ngE~W^o`D*DRMbi@g%7$ybMPy#J|u zS!5i*72msoFm!@z$G;l*Z8RcUHix-8CDBIp%W*?AcrK*Ibce@T~KY#R7=MI9NcDWEG; zeTb~~p{p*i(vNrMH8lmA^cdhWjbM~~M5#(#1v)2U>J>&Qdidm<7`7@gboK{pCGN^p zuVU6MoF;~-YO_k3+40r0*lEyFZ%q8Nyz5Pnh41TO7E7z^_U_Q4wK<7LMTRm$sq*-*p zHhdRpRzo1@n|15r+izg+-H~SbYCSbgINON5H1*Q|B_RpCnpGO1Ny@FcS8nmj->BC({-x6>8CdTmjr&CCSJyMJm48kIK9uF zF6H|d2Ko00yz<^^j*89ycIXKe5y?bdZS(joUUMIHY1kqCM&Pyl+amC#8i2O^g9iAX z`8?a18p5>rECf&%+WeDm<@g0r)W?>;)c{{E@MiV*hX(i+0-t7*|5*e4MuFE<-x&SL zNBz(%|6>AA@4Z%E$S&%-*8qP=;LZ5=BLn1gA%TwZQk7;J;vipI^*@ z$tL(O8{kU?e!2<%F#~*1;7^(0|DOTAdZ7TC)SvW`2K-yZ@dr)vzs~?ay@UfBP4Mp+ z;I|6=DHHl9+w|$*xR_^*$5EG7f4v6y%>w^Q6gpP_zGr|hUBZFwCidr~0sieTa=hCl z{~PW4`%P`{(PMH|1!YamT|_J)gLNUI{yl1dKeC*o+$Q*6 z8sHswa=bP_?Y$iio}Tc90o3My+gMJ&HvirK z&hZax7^aQ)tiZ#Kh`RDc2ebt3v-;BJe>FP5l!X?*@h2R0Otd3P8e04V0bIu@S14S{+S%FVIRv&P0!@3 z^z%O`@Ec9&|GEKwekRY~sm=_)we%z zH*3ER7~r?YiMNf{r+-JBc#i>ocbxbi8sMLf6K|QIPyfC+@nr`17vjY47I;*nsOyjc zUXiEr{j5R$ZwUO`nu@8_zsVS<($l{^IlTVt=U-vkwD@9-Q|aL=@;Goa#wXO57Jr`s z{^U&@pJ0;z&kXRVKF@)r>df(5oBv4zyn8msmzdy_FwRCXwf29r!1tKoZ#KZ!-OTgv zH^FZyM*K0_!moy{%P}{E)`uD#E`06F1{3i5gOx34KckN? zSyq5O__(+WdPB@JAlx_}%;~OobNTn66*`bsZd-Y?A+L2KbE+aeRtN z{-2wnpZ|_;a-akKbM>XA|7n5OkSRU0gX6Q+VEop`%Yu9fh8G_4&UwPW(ax{Ej&BYYgzag_s7qV_<{RMK1m4X4*Baor#EI`P!0!_H zk|^q9+mC$)_>*zs-!;JJcX9rk)t_-Leg4lE_^~GR7a8Eo1s=mQQI}SJ>kRO90&ix2 zb{OE>;>5pdfZrX z3H}=f_^ol`pEAH7i4*^p0p9U6FTa`oTC(){KV9I>+K)K~_?ZH))fer(-vFNxXa0{G z;Pd0m|BwNGcAWUL26%Uz_|$BD{?CsSf13e*L7e!F2KW+zpJ}51dkygG;>5pYfZr|f zC7KSSR)78{N1uPEzR&gl9uxX=a`o|bKj8RA6a3c=@V^%L%_jJ61AOf>@#TMYo<99= z$BFkD;1@g_U;fV+;P(r>8UHUB;Ip6O`ENAgUs=9>`S%OF+4$iu1N<}pD)Q%FVJfux z_Xh)f_VXM#(*(b&K%f4KA9CPq6Z~@q_#OYoffXkB-x%P}i;1)O)5Aq)KeXkqx{1@T zsiufv~^@ymr@ z(8o`CkK?Cn7^BVq`8oP{_p$is?{Mqmr~kkB=&vf&$M5?8INpr^y>s>PJ-r;C&A-A@ z(3XGdJbk?51P3N-0GeB=$pG*CJ;%RclK;OO;7`5JfsQcc{D(Gw>wJCs6Hak_sR=&A z0ADWf87BBr1N=sTH=Tbrz_*{~^iMJ2-{*?-%fI^!2PT;4|2?VeWUS_a=2oi400HHs<$u1N$6R4D{=eSj|IaVx`SaLeGNsZ&9{|8WC+zLf3Xb0w#XTNZ9rTvKYxOV1%kgIR=kvGg(?7P7c4Dh`_;CQq8d(HsA`&o{E!=(Pt zS*1^Z@L%K0|3L$M#`E#z|CRw>`Zta@)8Fe>>(k#KC;ol|{Hgu%<$u%w-+O@L#WFxc z{lB(OpMLj`IDS_c$$x0|r_uo5Bk)cW`G3~{Fa4P3Z|46c*Xz^2`#(5-pGp4h2KeO% zIexYY{=Wns(|A$WRyr60*93c1aM*uSl6_0yHO;j2%xfI4?SE+J^Cma&@@w%@cYOF( z1AM8#w?&gLY4d-<0RKjucsao7=hQ|rD}9}ZBu9eSFNJSP@FWBL3V|P`L=@jze5Sx_ z`PV4$V>Nhf`AZG(Z33TSg0DBgKPK>K9-=O7{@*jeOF!fMGsFMV0ADNc&Zyim9-_Jb zNZ_^dYZv${HSx9lpV+7`|HlPh%YQ9COW?Kgdq&{R_+M^-KNKf^jRE~V0YMg{ObgFHBPth3dPd;w z8vR#pmG2aR*TAI%|E<+19z($?@zVre8~dQZADpVhgv00Wmj=!)xiWO&?s1_D_a}6gzw!BBwoh;moV7|_y(6W8 zw6X4iG>f!vj%4e@SW3BFb`SJeZC&Yh_kdHL^H$H*(g3=O`+Da|ovE_a*M>MY$vt4h zbBUg3Ndx00$uWp{gZPbl>Nt+L$8k?-9mQ{!-Y6wK_rR_TgU?f344pZ8t#W5CezPb@0gU|O=xd#TTqyaacvG6+#;w?eEC8~Jy4B~wr z@jkDLm*pNHx`|K7zq|+euyT!e4?u?;?Dv&|Z&xF(;Hg<$lGpK(?txU<-uDvHy>R!^ z(77dF44uCp`Tr!L^Ptu97L|u&I+J*c^3(4_$loF4NzZ$&j;^gk@WB!0m!oSR#WUbT zOuQlZumSWc<%Vr>w5fQ)^hd=9)3}f$m1A&FPL(PosUqQ&RjMvUin0yAj>(RGtJE*| zP<=(5E2Uqfj{e$W+npdCvmD{|2;s@78qyToY-u`}HE6XQ9)Pa)dlEu_xZ?`&bp-0l z$k2tK$eqhkS8NmA1AnkuyFRd5X0SRlQ5rakdh@a*eI^V;G=sF4+73_WB zzbCEy@tO3-d*7T?_?t6n=PTY!pDJ|@{OIhNblLXWjC&_-Ux07_wWvcsUig{~_qHD| zcx~;=QYZZ`PLTG^xI#L-NVcEo0q;oWCs7~2i{HuiSGR3`!cHSkj$}D;)9)_IKsv zKIb0?%SkprN1Akx`dRMJbPoh8<<5BNDUofP9vTKc|20f{j$S1Ve2^*~_(PI3P%+Lu zP?5sx*3tXH|7NN4xAVZiNxW_;GU>5SWctzzxeNk72yEg%yF)YN#O{R`<~{7OOQ-Kk zkjfvCrJN5C=ZBC9=1CkceZ$?~qp~S$2L~VBGY!17*cdN+liUOCNzy+5E$#t(qO>ph zYxlmHbfMzS&5-kEIq9{{kYfkFSO2)=wbl4d@~r#uqSr{K^sM3vseC8o@H=aA*LC>) z5M;6US^M_SBJW(;)Bo*{2lu@?&V3-gHFeya|FM2e{&=w5mg63Hbu{cFl@}iyf!}RPI(6d3A^9KDfre}jf&rYFi zWB$XweNY}1*0cAaXLL_`_IucDECo8v+X+Y42NQQrru={V5AG0`!T1>y!T;W?+ye_n za-KhU#qfDfbxGkl)g^`JRF^)fGWMcuBtMeb_|{a+48mrhT)%~Ul(PQ%kAshr%{h)w zDtL(IANKxM*ri)wpNc~Lp825x*i6{1u-&J02CeepvylCTyREQYQfC=#S1sC&-Z5xf z6Wjx}Bcy%lu%U@ zGNG>@_UI=lS6|{=+t&SN!gedl4`p}sTkM-w!*&K+*YzI(zqaD{R(yAia1X4PC-$`g zpNRC<%M<#33w)jZt!*89Cv0CYr!YSQLr{*@vV9ZXzl7%UYjP{y6jT=cSvWay4tsqK2v^cP=-Um zqyn=Gc;ds8_$FRp>4GCgp16tl&O%=r9H~lL3k?nQP581t{p9*{yDlX z+&vGvFc&&ehl`L=P!ciRE9l_cjHfx z?I3>l!q4>!nN5Yfi1!lso+eA#sW$1f6}nGCgrzcI+Ne*? z*t%_wG`_D=(9nbWaN+I<4OH%POa24pLmB5uokVw!bqdoTDksrQX~{Ug80l`IdO8;$ zg+Dw#m%mc>vtzF9SJI<22yX+{1{vE5Ap^+u!rg_Tvm@vBYxAf0FIlC1#M89%_rAF& zQF^}Z%)M_?8nw`Y3SeuYFVxSVFz~1=I6@jAdCzH0>n9oSMBBXqw&Nu9s2zHgW|Q_M zL2n*pb<}Z!>ezbO(N~4{kw(qS{}(WcC>cW;}6axeVnr0q|G2kEX&+rBR+ zotSy$=55E})1I)}yWrmp%z^*<1j=i7OPwCr7ANFW3cfA|e^M<;jIUQFc5lmgIca;U zC7Jb4GoXtZcs>?&?VI4gUOZ}l?4W6^Wz;6ZdBK0ON6Nh$@)~TN*?%L_3LuU5k!J(a z90biI%in?iAN)88eob;;1@4m&Z&mA!{nz6gZQ1~q4G$zHy9fGUV-}*kiOJG{{23{f zR45gYe!nk|f)AA3SBQMiqW*d7>ge6ufu`BzU%2Teapy~G_TT061f31(&d)V`&Pgxl z@KrZE>%Hsz^)2Hup;UW9+1c-UXgcNxbo>TF+SO?6gIWle5&R&{1xb!C;;RauE)n}VFYj0_CkU!FJ5hgZd9)Kq%2y;XTR-VB%5o133io#)M|bh)akk#x9tB_+#l<7H`H(~z#P z1l?D5$#<2OES2PYu1(qzespzmsx%#U^r4H^XQ8h0t33IdvEQ-$Q^La|w%T?ihtDXN z?_#OQ3RW2tJp{)~TA{)`lKAc9M@K(4_HlE8m8HhxmNGsQE;*D%(`c(_13ndb0oL&TlcUO7qJi$OQdkrH(R4*vw?-$SUHKAq~vDb}93KHgt<`s>XoZV3G83sXk z(JLnlq-HmI{Y}Lrg*e_e4Ae!vZ}^f6G}K!MGc!D%U~N-itw;R^B)p>=Z`BI=)&=R! zKH3%pFGtfn$BV)ms#m)%weD!P4Vg;_eQ0r6h7MvusAJjC!50ARsQFoCWYIfDvmADxS zZ?*=zPTv*o0f3?6fKS7m-mi}KE;AaZQg!vCc;BQ6ddihtt zfv1an4E3eWKLyYA@Q;yTa2?}c;s09vMg#mk$s9sHiTcvwpEbb0F7V7(Q6-?o(^RP* z{pSUq`7=Y{=Ri(+_;sT>i1|B1-~$Hurv-kx3QIq=^gnKZe?#EIev?Q?i@ym0L_ZBc zsIQY__}zSUAbwL^x|DCsVX)s|W7L%~mfuqSQeO&A39B){7Ye-iQlf|RRRS=_pqu{} z1rTHAQI|IV?E){VTR3ioLH=QXU&K6MfNvCd#ot#F*5cnWz_-VVKW|X}T>_t~WGue5 z<^LQy<`kwa|G_x(zrz6kw!o)p^4FIC9}Mu4P#kT1?R`k#Gqm{#yxAIv=LB8@m#!SA z4dM4%{=F>lTK!KE_+1)+mVQ0nQ%?J@;`zOf^wpOpIjJPDa;2|nR#ju;tiX*Fo$t}&1^v3v8O5GtEQ~ZF&XswPu33G6JEbf9(mphbn zq3})2-#4w1AKZ4w_(!(ctnPwD%+J_G_zZc|HV?*^k76A}BIW@pu6z7r+b|BD_ZG&7 zY$GvGV6}Ij!1#8O>@Fz5XT6-f+Kcff8i!23LV6bCL7g-wn~3qIT#PLpMcntS6WG}0 zE_6Rrs<74qbWJ@!h;ecUqwyusSc`G}RE#CMk=D*XN+FEp4iMdYkoO)u+hsX;b9T<739P!5+sCF*f$@TME6&W2tdUFiqv=(w&4mqVkPBUWUG?B?^ zMp#adGdcYVa!L!!DJ3pB;ka?gDFt%kbIK&A0?3KzA~_8}PW1aI$q92)dU7Hi(aOom z;Lz{sM0wX9zLQ^*Q)=}cDRNLI1=(^#bI-3LS z&=vPJDT|3do=zK1i;%X$E!;w5$FzQ^7xNZ9_uoG|9k`zR@0;Co|AyJeM~#N_kj{2}vsFNyduOuo&C&8HVOOtC+TPP9WG9)$dlLw`sodasv4z1I~M)Jjrr z&yA2h~a~8djJB2IrRJG90koC@fHfIT&dg1OnpwG*o*SABz%c19Gq4R;I zA?SU0uASymK7f6ifN%IC4z#J5PLv$D-$Jy#h4~lKS)z~P5shm4h+Z{~WM7&7YG~_0 znTgiHK{}Fi~MVOEPl6J5)N79&6ahNw9%Td#VWO1(Hq%nP1t3XAETd~93|f?B`h4o zC;2g}wAr#pq4gSh?25E4vb<4-E4Ecm*dfbm+>RXiv&$3SmgP2idXFscmRC?337aj_ zMhmjoVoBHms_3T*B}wYJC`AVpn~>-%EJ*Tl8$|7kEgy5q(2XRg6j}w{shAb5I~9-* z=?=AJD9l!x)2e_iQ|7eP^Q1P+{ZKx(4PWgi`{R&o9W#(u8tmO!=pfBq*Nz_9PjT9( z6&6q&vP+nQWIEBN$-7PD4e5vTCf%huJJ8~goNT_%p)N0#NrW?6DZWB0(MPn|K$kQ% z7OOnJ3ePL1DRY6*b9m~!E;nz9uL_UVbPvU2qE+GXIh1u3c-$^{T&v=-U+~yWzDirC z%v~zHR+pQ}SmN>{ev=Fl#$;Fl`$c6?c*At(8xrQejrlm7^oTE%rfs7{zCnzPslBF; zZ6H-$o`!G=4Gsf?87&@1CGQrn)6QVzHe|a+hdcy)`PSu zFUsROIVCU2;U2hNPU;4K9DUZrF0!ZU{E{*XLs&c4y;_!^qHt{UEcal}bv3?`|Gp|I zC70$^XTXR1uH?*p5cBS8{QY=t#~Pz_IjO_GOAg(SI5y;Id+GWPTME{0T9eS0=#&$6 z<0#he&^qD-tfy;}QsMWc&fxwJkFVF4K-o@rU=86pV5vVrzUx_}-+#B1`4ZZDT32nM zHPf=({h;Nl?m1YOllE-;wp6UunfUBu+y0HMTNoeqD_^OvVDbNka zA+#wy=pWe9p<7rRothxINQS%Mr+)~a&NBJaem#2ci6r1ZkjdW2a}Zl(N58wv{+$RcVe+dC&gbaWJ&pxFQAs?ha=}Ro(=v)hCeRDPqDyXvBGajfd6s@ z{Bf*dzF+Q~13jq#Pg0!oLK9Yi*WfGKcJwE0eU#rvpnKsz7WIGWI;k@Uv=Pr1;hXw0 zX=855ua%rkA8tVy#r-nkuCRWk|Mn{BFwumyWiuq$pgky0Eo?&~{NY#O!%l^q+L3QB z^>-}x4yOT9uWz?SC%>Qg>AV}2-oVEwny7d}jJU&R^-N{{LurHA1nM?36jsy{vd z!O!wOZlZNcw;!K&Ny>W)JhCA#()IT5&kxngwvKgjV#g}k-tpKpYp7#_G_YwF>JI#G z(xVe7-*Na?3$r$DBj0SHRT{V+e*9`VCHExC^$=`ZpJhUKJ<`T`I-Qj6X58R7zm59n zsN)5sOQch2vXuK^4c7KRra6%59P9W#s*BKp+(#4L12=%5lOV5OLO1AHA;vylyhVD} zJ%a3_l=p4Olh(|o-JM!yvrAXf_``?b*;Ism8~8M9+qZfL-#_yr)^H&&S`*h9!g@rq zMQJ&YY)kzLAG_#B`WT9G^nZN!bJR8wuTt391@D6#g$;cVdIp=>MLd1+PU&<7>H*b7 z#$&7dxkoX6(heVj#s|pn>a|SjxC%Cd^w+F^tgM?tT3hg8zKq&;A%1<*>*zjO`6K9N z>=+B_$x*C;yH2jfrEFvjt! z#nEvBe7;_u+`SMVYNO|kgpEfUYat)1Lu*yCqdqWXUB2Ms^>0$UVskwhx7@IKrt62S zoty-l6B#S>d|8nnA3Lx^eyxz7AM*2S=;*Ob=)hRmjQ5~dBx^s)eF$ZM|Bz>geFCO{ zXs(6K2Un%#^Y$}(JmjO5KV@s>=ozJPKJf3T^D_8rfeo<27GV79ZrI;>a;Kxh9Xfti ze$IdUBWFIsx6SJ4wq2O_@D!{KzVr5@XWF4(B!g6Wa$j$MJPV+^n#^~5$& z%HN7{KuohZ+R+!8#Oe|s-{?g?>EL(!mu=hok*{Ne6oP$+pOPYE#QB`MIy*mDiSZJr z^_L4k7maI%Dy2@crHS`@`lb8-Z+6#xsr|d|`_Amt^>ae0_g~wO@z29MEh&A^S4xME zqHSP!;95Q_g=#^+6WFuJr}mp)MH?mMN|X-DzZ30dKV(DpB^$mXx4T7<%Y4XZ9^^C^ z@+yRl{!g${a$LAu{~7rUe?Yst7dBXtwbCCanXO^E$Zdx5T(9m^`)t%Ue+gq`X&8T? z^k|Jf)~FZspp7Em$^Ot+(MPm*%$VvvuyBNw<1C_aH11!vA#W;cE!q~FS2}zg{vSRC z)HbZK*gAgtE%$+6Vf^u(ME8Lg(f&_`&(b@O#uzxgGHesA+w4IYr9=7It|8y|>P+%Q zAj=ubvnx`iaXQ<;@@`_%v7^(?j>RoYO(@b%Q_tCP-xUkZIxU%5@?X)Ap< z#v4Hc;py`pWJ$cH-~T^*Zv$UddFA`>eNF=VB;h@81T;iiO=4dZ5uvr06OcB5ZK+aQ z9p@%sZ4-hoD85A764c%af?i|o)N%L^(K?+Z>Wu9`hxFrojN+Y7s7`OKPHX?S_isRZ z=Rj;LnVF~+an9dTL%i6 zpT?s8_F@-w&iCX!Yx-anymDxqbznKXbO^e`?%A#Qq`lA|>)G)!JNo??beITN^dJ*2 z;HbJd1`Spi8mut$sE7VkR{Zhk-Ppg7YgBK5zOcK&>s-FLu;rrp8pl3lp8eRuHI9YY zFYChh8b5tgjyqo89?x>@D~r32o7jz1OpC@Mm5_>Ql5 z1lrjbvMzK!$oWX9dY-@b(U5hK&L@I(Eb16K@Z!g$U)Y*wpqxe9EF288Q*RAdi@cNtSuLRxDK{u5Ax0*4Ua|Ub~ zW$5*OxgUheUetNkT@#2`L9VOEmans{CS=JW;w>!p*w^o}4q&6l7BZ~|UxMN?Cz>ch z&&_OOb)nlvKeQQaV}N~9ZLCIaRU6Wa`k~2ULzC`)*UtIat(=cFu@`FY>bnkIE=t)A ze1FWWN$KVx=At&j@aNt8?|iU@cJ{O8P5gU{@4v=g)Ao%GPd&BKI9=RfLBpdo4g(>_r)ybh#8Qdzy5N?EzISe z+S1>86nMw|YFUlh+MD`F@n4s2EvJnB^?7C2>NDVdn)h80u<{Ve<~mK%AcnPf%1BHwfAm)#ygGecJJLiY46;zsqVwx`xR;L z9nf-t_0sPtRs~&wLo^+1!k0TDyAh z*$aHng)gdmqgT$1o!^?P{4Dhs)&Bx8RQXQt-Hm$3-z@%Z_nu|%YqE*sSnrh?V1EAC zN5d!0douW^Kh72{>yn9+{{}#69M#@)A2u5I#on{IDw{FxF9zG;wc1#lh(rZ3L5D_6~O{;EdSbx*1=Jhu(y=Doa z3+D#|b9k}@UwS`6#6&P<^g8Ff>s&eQwD!C_Ti55${mQlL>(;LQ^tCtNyy`30-mD;x z+!0Z!K%xaMAZ~C4M*e^8s_O)gY~aX*#wF(mLP=KMdS1izbLJACPk=6;zk zOBYTd%)nwACN6g#|Y^-EiA=tFCW-Z_UiR{bm^J^{0B3 z7Tj_@(V|~od&6z-X_6P-GL|Mz4uKZjxO&w!Eni;Mymm?R$jCAx`~lpJw+L{{Pc44W zC#ui|Tyk^`CS=_N+c&Jg_NMEauLlF)!_Y4omG6u=^IQ>@W8@3(jetiSnQ8j8(CaC} z=Tn4xS#U%ly~&W>;C?jL&1k`mx7^$WFC{iT5GTAm*{Y&kgY7nuRpGiDu3viT>hqT@ z$q{m#Eo3)G(TwQh^kCBwqLYI|8tYW&t-A5XYp?&(lIsE!P0n+kYg054;KQWou}F<< z7IPbxUOumZ%}PK^!nNUM*kQwstJXIyCEi@`Z~g4bK(u`T)#w;sJEWE@xr~jDoE65zdV?n{uWVR(9%H@yqJ|aAnb~#O7!R0t zBY8o{zR_^QE$itsR|jf;f!8vdekxen?`59b%jNSM_)o)0Zt+X#JX_xx!_6w&FF_c& ze*I0Yxj5gL+PLt`Yax-~ewJFX^Ha?4Jro{zuNYG9#vg5zy~Ng7ssi zZ@P9ZJ(37u<>CO}cuy^#XEIl00`l@Xpw5WXdAEQYYpWw}7&P)ejJ*HSs`aZr@*f@U zu8?X>9u|JRX@AkQU#TCSnI!pO3g1SmZ|u;?(!*no{~|~IU#e05jD6buYW|6FTx$1AvQQyz?FdF_J$x;6vum92Ne*(hIHvTPM{TKX!d!L!`zdJ|$6*yk& zZ?yIQUpeY`dG({FmDK+-`#%#tmu>tpul|jxs^(i}{abU?|Du;GVzl}HbB_8my<8Ck z8eHHnv;SfiDBJi?V2anDw+!wN{-0U@{2cWiZEXCF#=maNQGcdaf3Dk1^8cCr|3i-Y zE4=!njlTdsmu>!6kFoxja@23~>NC8wzs&JJk)!^NW32zX9QAJ>WBvK?$!zm)^XmI& zzy2gL$A4dr`cHbf7DikDpXI3E=hYvL|A*m|*~UNF%hhn6KXC6ebNsV&)Q@`g{j+Sp znaujP=BU5bo49|roU48!NByo+x5jAjs{_Ha&Hov%{%H4&_2j7Er~_2~{4;m=*Kqnj z8$OqU#Izh>VKK=Ta%;ycCY>{H6HlOtp7xg`mf^br9X4d=zcZ-&#eD@uRi{9 zX@4;s#`U+-{Yd`bACCVy0Y0to8Dg>(B}=jXGVwQ)AABW8{RhTa|Cc%H4|w(4%qUX- z%j|y+`$V?!H+o5GMyr3DS06Dl?Qg)V@3E2OJ0EWTgNJg|Kj78(wjsZ`8Ef(fU!KlU z-=5``VtLd4GW*}1WB!w8xz#fJ&xGH<=cqr+tM8FfatxXEi8IU!|M_FAUz?-;3a|dK z{*ohczg+6oKQH6?7rpwC41oDR{m;*P^)sqltEw`exWD~+{@ZK4`kDCCHePJ?wOwqrg`cv@+di>jLP1<@g`T#0iw2wy=W5#PbUG?m(oY-zX5}rY{OZ*1 z$}N2VYH@evR$^59?x+5^r>yhZK2dlnF{piuT4&j9pNKR%#ILk{qG*=GT}5r5a0bSc zn}p|`?jy0@XCA7W)-@>XH76=)V?!6 z+}kw0Y-;7>cA~P&P84<8iSUzrpKSM5J^)P4^nl`n;`pXFKc+a+#ow%)U>zVHBC!~s|F)1D_t5mSXm@dy)xmg7+*T!b z#VDt|LtSD44|K8>>e-`w#=_I*sLxoqVonpWqRQ{zr?$992K0XDS>`0)?B>UmHzqPT zK%Igr>*b|(b}CqIGFxjr_QEcU@93?3rug^DF!DIui?^cE!gmYeI+GT>qDKiIv2uwJ(Y;_!jHl zMBGgqc&~SUT*V<`Y)ZI`tMUH2#D@FrM3gb;edA+=rj5qE1#VlHxox#gj3(4pBjwt_ z#jI^DqpfABw$}fblc+n7y7K~cYfqx?S=2o%P`9)$F_%0Jw^Y;-+fh8&2+eff-w;>a zVjJUk6q}Y0JcvyaO;tfdjnol-3O?&AY%{<01ztN7Pof>_B-@$jwe$O^JD$)LlCw|Gaj7 z?6vdLlW2!J$##C~we!5!&cB>QJJd^!Z=BcZCPau({e`NJ$`{ya54X@~OEN^6$)-V+m( zzq#Ad{CVoL<*8AY0^RiI%k#hS6m$8s>(5gctt$7YHQoF4)KKexd*yw*j5bPQ&0fwH ztNsOI=VHJ>ac5RR+hxkL5+hcYDi2{Ud0^AAXm8YxzN7ET??7IODT0aa%2@`_-E@q* zBl~dkM`k2Ox`T3wh-AzU&_>(c$ar`0Z{x)~iKQY(5@L8NP)KvF&bhPPuBF7i*D2lvlEywstSFrZgZYJWqS%$9U0?J?;uc6X@&3%{-4xh-}^j z{!MG0r#y*?_V0et$QF+c3v)&55@E)GW z(44q5iN4+rzZ7VvOa0o;PeL3Y2HPK?JeLkVkWZ~(`4c=p5q91pFI%2>aLD|oSp7Wj z4?Ek(Sw9K4^WB~I6n~CX>kqw_?02#Wh`1-Dez$}W4h)R8GS{u4`t5?}jUGI6jhjm` znTgYxZ^hHb$Ay^I<9W_&`Q(uE0!7UDym3F7&$xs0$u<9Wl+pHlXXiNUf&5_kojl)} z@AMa2efdvf5b)>e&Hqpy^Y2g2^W@jBlX-Q9ou~7yuJDtusLDZ9ANe#cdKwCCk6X^S4ayyF+Qu6^H`dAIMX#xAda9Q~5ycuG}T-=|`$iNvJblItWaL`oyGYrhi;R0pTfHcu=3v(VeEyqFzSggYg3w*!5ygd(`Qk^G5D~Oyrk$exo=4qe3;_VP? z7=+CL&%wY4!k}RA`I|g{(_ZnAkTUiB4B#smN1?H}9q0So;S~^BUtVf1Q!E`wZ_i&5 zV=oz(TAvz{Ws>&uVH1wxu^(3NrvHgLyjYRP;;(cU$iP(?venSfTXrm2HaCv< zQ>Ncu0RwtC^lB1j)zCMXYCByHeKwkHiQFuQY%q`2T=DjJt83gt6sOOLhL7Yi#r4T? zOfdY?>9Va$VKVM`KWf42E_H}RTgkv5x1E7JQJv7hc@>5d;;YLFf9dXKrtS5_-sXX@ zwu)BQ$lBSGHy%=nm|X-XIAj1~aDO{3 zB2yqXJ`)P!e)i{QSZp%BNzq_KAz)wd9alh90>bJ#vFx zV)V!!^ho8*d>)w8*@ftl$s8p~J+fdz!RFc$>5&)42Xg3hj&k^%O1G{KRrul1t zeqU?!ck*H_Lbz1!t8cNEO>?-@+%9RUg9G1sW;9W1a(uaYtwMQj9&P3L6P#y_r+lbx z!7X#F-t}jaLvoxoSM&GtEU8Ro)cW2c@-Qh+H+Lc*SVS%s&Xzj5$Qv_H`IpGMv?FBg zC}$nGggV)O6pre*O_{l?N?qFkxdm&na};-xza{g|1m$Ks?B!^3?E=af>gM=)ev zADfJ9HPf)CydwJx@WwUgfmzsT^jQNPO~VG`+huB?qo6&8G6~U7H~H&&3X~hqwdW{r z)#thI0bQ=+81VbEvXsqc2Knk5fy13?Hk+~@l~w<;+5GjWHXG%ybMuh8HXApG7X2ss z&;CLhot9x^>BojBI_-NbKS`&#=qL_u9)pIR|NiNC1bRx@eJTvSE?t~y_i^)9I?$#1 zXl8D*`|QT&N1m_^jMS!ZqRZUdjufmBZ*F51+3H-0Km{jY%Kh7mSZ2an#N4 z=HKf9o_7p!w?~Y;R&f0X7LnglIQz!kR>zyyxU?r2Pph_ig}*`Etrq{_pX^GaUGTW} zojdEntxthtp9I&IkeBb0?&G@GesL-Xn2)nTTT>%6?*z^Tf;6LY!G8UBL%Xb(gZFi> z#GcrWt;_Hj?1+2DljH6Ki_F@#0W*7vwNvMKf_dX=<~hy9pQi7U2Y7m9(1uT7_xoPs z^HxV5ykP&q4d1VX&&H^$yDe(=w7%l}>W&AM=h7xmBk(HTb3FQe!KVqnwWdP6o1F9S zEPkaK-qif7uRXZDxjBwbH>aJuy2)qTQ{P+@*BE`i`zUSuHelwHq-(YL{+nO*y(c$6 z?H9xI8(+aX_5-8hXo2#LnlrrH$Xy!0!0Isg$!8EhWALe?ldRr2I4rn1kCUI9HF}OU z6tB`V@unttSCCIR@UW(U4OzTO{b}D2pK{=1LEa_4g%-n|=-^Jq7}EOpaIO)2D&hRu znamkO6=#H#t;7^?MtzLhhU#o=h{x#f!_=`F>2tBi@5tdNdTr)BYt6X2gmQ>J1|ALZ ztQy|c%z2f;@x9|a_CUv)|A2D7@xBdS9;CCww59y|{{;VP$8NnT&2C+0_}9K+cI)Bt zhWJ-A{Hvt(BE}p|SdnP2*3jnFhw((r;DV@%Qe*zx7tf5MkP;R|_M$I4&6 z5dIT?`J?AAi$|7|Q+iCO*58|?M~ZhP$g_KFg#9VO{&Xy`KXH~Q|D#vTIV1ZN=dKSN zC$H+!(D1!Qd0f-#lc&~cz0>RskqO+HVMlv8Vz$N%%Lbdl z1M*YXGLB+jCehs;nP=%b^PYwrV&o6czOl-{I+geRC^CwF?%m8C9{#y|%**v_V4h=) zNqGc*apHzBI?l*?^-=6iKEF7O{mJJU$KV;qN8lO9;2FwcE%-{N_36~-8Q3o#I04Tn z2d2Ymy}T!_zTp{P9g$~5v+|7co~`hVw6+3c*_OdG9L6MDnsBQMn}FLlzw>x5)$mrqDnckODq_(a-x0(_$U{}MhC)U9*zi4!+0?hfkJW8)KJ+vARa zvn8JX#T^oc{(F(Bv+r>wJ<`F_cy|CtxKnZ6zXtX=?o*vQe4lggN=j=Z>poW;*yl=H zW=+f7=iGM2vd@8A#Tv`W?{~%GK{@q9gTwF_;k>>Jhr4w5Mpjw}cF_4gpUyp89)Q>F zqYdH`()7pEx$hmJzr*N)KhME`+u@-;-+i9(W%6B(O+4Dy1-FIlb*1oO-JL2O^IH>_ z#Xpb#!1}vF9h?}DZ@dIMqtnxMCidU+@wcLGS16jO$1hg4*~$;Q_l&7r`~A^)JG!gN zAA(0~pJ=D76Sj5?=#B&6+{FEtmDuM?9AGxn>TL^gciU$u13z-GFExF}N^GPKr=g~A zQy;t8+qB2N)YFK6pK0d`%45fAx`KN)fQfY3)3$GiL);~i{f+|PKQ5CFUjvsCxo`(O&>=p54;*9P0QWQY4L9$9T75%H!)UAK-=3#`z(FAbmYmdXiv&6#S1>a&OM~{2I|i{F|QbpU*dDb2hchJ)1gu4t9UfXFO9! zIv2SEKlcX`&>iQ!9eXnBnmgly_03+_8jp0>buS}^YZT-jO*TG}|9%hvV+Xgk;V7HTg%KD2UZi2H#!4JlB}uo@+F657=;9=X9fYru7k^HR+u#?6oJ4-{rLl_P&v1 zeRnT3_m_Hpfcoy*ecb!{Mz&+7jX8k#)Bk|FsqX`DI(RoeLk9PJKY;%TTc+>tDLF>C zyer?DyB_|1^7wEv{4TZbvBERwWYgoM>txgA8u4Ast+1$3MgK z&+iuGp>OZ9Q;2&YV{t(wxqR|9q9P~3fCmh%b~aH*ryT)t!{!=r|SGe zHX#n?rrsI0rkZn*jJD+;oz|vj8;apapORTC4E;%F9mGx}+fWs_>B_CeEzg06waBdv z_RJR9U23Q3`-~P_-%Iqp#I+?&$Ch-CYfFmGV?WI@7Gq1wn4>>G*^)$miT@exCgO(s znP-~0X|9@IP|m47KHLYk`gpp({+@6}?(zqY~iQQF9PKDx`ZrBNpS`r;a$YsP4!CR~@O z9Ut(S<(YhDYr?M2?5sCr7j^S?49F(N`?d_9*@Lus2%Y9u&T@wP%$}ToP|eL&LN-3- zdssN#TGv!d-YMDqfJu#Qb&$58_Fk?RJh!#!_GOX6%~8AZX9wxKiL=y(@z%QM;Nx8t z*7mv36L2I~Rir0!2DtP+Yuyv@sfdlO`b@>zI6VpEt%Xln>zEJcu};q>&Qv%3erSj8 zXKrWDZ9m)E@f(9bsrKu*Gr77vOZ$HnXn%U3{cnxX{%mW;-!a1Y%B>x@&{sRrw!?4&xcTi7)0S!vT*)=xSc$cxmG+#1EbTp)YH!oT zKzqP7S9?vipixchB#Oz4Lqg=M&YRHD}I=7~`$}td&?roo{G< zMOnskUurx{foBq4n{tmQHqqK~4egmVq3tGq|C064__TK9x870XjaR>$_+1kC9V@bS zOb`4fANdaX>nH0MT05!&znl22_o6w2E40~Pkb*%MvIu)!`uj-geLL?zmigXEy>9}B zI76h@AD?>P&wChh`ulOI_wBqtEAxGR>V1s&$@6_V>Y1l}Ifx}o`f~WV&<;NqE^GvL;(7Ajn00wHVX>D~e*t_!maYDR zm1rom){!@O<@_RRo_J~{{B;0Zm3WV6mxI>qw7V{yc8xE}b?$k&PrDj})=#wSug2Hs{J7NHS+neZHLgCF=0}oYTN&A}M*3W7x*tl04YbDSb0sa= zeK1d#UrmY5q(`-HLStFumD1o5uwDKk{c299UKI2>kj(zhou|()C3yZVc*|D#Pk(*a zpJLt?dvZMcNsRM{KgGO_LwB}2vf)eFNB@K`f9x?#&RTThD_6yrBA?V?dvIEtY!^Dr`x+KSLtHT4RpxBSnsHR3BXo4O6iPf>lgqMz~^d9<#ZJjgFv*d)yug5%-4 z!`P}@o7{0S7L_4Je9ma&T}!{)Hd^Z(Y%U+Jdg+m8z47vF*myYuo#Rj@GO6n_;#2lF zGM`4|5x1|(TE8!c`9x@UA?@w=tQMUkCEC&{AKW}|*8$P7%jOW8cLz6$!ymtOmk%^l-u|;ga7r2VN-u3E} zI+gacmVvTu71ELPPT!~U{R)Evr7uRn0oibsTk|M3xN>aL&)spG@rm4v4e1ShlU^Mf z`ZoA;(NXNRL!olx6FGn{+&gzJW)6#(OC7S}3tjHoS#yqokA)~9Q>W5X$4R*V*T}o{xg!rHqe48cfTLkHS%4nyhbN`c)66rN(~i z!ZZnAFYYoJkCF|(Zrh5XN^3tbzHOc_px~?dj|SfpH!SMT2H)yD>vNU=3O{6BYOJ=O zMh1TVJJ}ES*#p0;{$T$jmTgT9;&*i)7KYy7fVeO2JRb48bv|4HNU0V=P*) z<-{>uQD9vdw5=<@1ay`#F>mCSP(BIemxx$a!dYS0Oec?2wtNx;@EGzAC7Oe=lRUHJ zuX_@?9Hck21KUR6ybpL9`10xJ%D{K?UB?-nEy zoLR*i@{k+yksr{X?j-lsE<2g`Dgy^NS9EdU3*f*NCmLT79w65S@SrS-2fy-sy{y9A zyda1Rih&K{LfHtopfgV2mrS{Bvhj%WKN7q!a)-wwB;RDp9SQ7<$vqJ|lKmuC&Kuum zD0zhQ+;_6!hR+`)cPtF>2+lL-I5Rsxm_}UwJq(G9Mu?rMIV~@sX=X#u1l~xHxz!`N;bbUxIw3DjOdm zPUc}X||qyNoy-myPddq!mHYqoXa zbZjBF6~yPo!c*pu8@hOZxL{7#q_(LIcKI6k$>&x9<7Hp7FTa=knyRyt`h%5`Ir3+! zqfckUgv*CQ*1CPuO6Tk^E1k3Sdz&hh)4?g(R)Jlw_T#kq*0kt?%CNQW*VG#vzpbJH zU&120sBk~uw|&A|_Y(T|8oQwOUd}MLO|;exVi($0KzTmN{kg8_6V|kX`IS?fzjt3n z<;B)b8jmUS3G4i2cG;X?|D5s*`2M}Nifwh)`7QQ@g0~pA_@P7HN|pPBefehWJ0JS} zw#%yd_v^1uzPz&PLoL6VR63{2o-*~<8rLVRn_j9ZD*O%K)$eY5LTxj1_;kMed+C(> zD%uxV7gT@HxNC-GF^*Zq{%7!+><-fZ z_n}w6g)NP|e4L$zu(1u#&FJ$o;bCdg<`p(FGdTxFu+NnCa0jqU+X35$Y%_(PFRbE6 zj830sn<+)_D(g9nZ6;aY==68QeH&LDuu#nArP!G7#lF};n@{MjLHq;u)294hKkfOt zUWc!%{9GRu&f_Q0fG_O1;EeJzrrX8bewEK4t?$6t8?XaBf#03r2X8A*@(RyB=JJYk z{pHwKu-%}02;QPua`|S>nVjMSp`PMS*KUHWHv)W%dzAl4ZD!gN@$EHnu!=u7aj3KfR8a)p^ z-^6pH)9opt<26pYwoiA*ZG7_rjBN&UEXzd5CYO+%E0~bDx#c zj+^hHb3$%iQv0?q119xIbcC$7CE}uo`A#z?Y-i*lxD}gw%6~eWZ}h3sEd+~I^sD{9 z@v%rp>~hZ@!KblJg~4mtyMUj3iA*_cSTUY2lHHt7--d-fvDYt~CL_R)Be`OxX1j99 zVamu?=aj~T&}NeEPqluULq_oNSvdz}f5bkHJv7uKU3FMa`$?9U)4ps>IqjdTaPyIC zE&QAX{}i}C?dRV8X}6{2;!eLm?c1Z~;?9158gz&c>Q!ku3rzmFpSrQ{ZL3GW@66Z| zy}eodSG4t>?>mD>ANz{UemFe0y?b*CNvZr(iuGtHXF z7OdQ8+3pvpni1_a>&rSQPHa!O-1t#{+ls?4^t;Ub{>$WVSN{K2^0%w+(MF=_yMLAj zQT0hqpXXL>&RV_&K34(6m6ECz`C8}SagQE)p2PlMa${AU<$ zkFQL_ZNY1#92_p(TsVy#x6|`+oIGxyx_lf#+}^`p^q%p0lr`9Qr!}X+inIvsoyKp{ z#c{=F=!{PM#>g8!UORqH6qnaXKN)#FN|N@?hYa58w;M-5UGVn5rr~XgY@OVpYVh{1 z(es!5hr-MFdHXyeg~LI3Mf&dYa>%&w`cIF)8S7#A$ophH+Qxvtn`+)Y{_5=VKQ->M zhe?0RwukwC45If99=*>(C-Zr*&ft|RK=}h?^Gw6xh!3-JBVUY-=H0!^g_+BbPY3;1 zkFswi@F_g$ed}c57)inLa5xV+Ejt`*lDxo$e{t7xbD?mv&~%=$UA7rT1?Vfm>C^m~;b&9CDB;3H)6bg<7lCDFt& zS8lA`!{=Ub=4d#dSdlz*)UX-1&Lh=sJ8`ea87pysgVHtkBkL}`@3T7{Y#{Toi}Ab= z|FuNDZS`u;Y}y;{zy?r@UX`$>LASIap9SICwR=MyHg#6vudtW+zc<1&uqnGTXAD>@ z3_C4{;U5Fcbt5_g_LI3>#5h&*HTgXZPlz#|J3jxd%dYzTj+<(U#a%{z^JQPFn6ZpI zmgLKHm^?XaW|#c+@|r05wF=$*TJiU`bzlZii zUL0=>n~rqVh&^+2?FSVXTwrqSDW3OSbnJcHU*Y#HpCd-zd$!3OM0|X4d%U#2&SuUEeJoSZmzJyp@xoeG$G^RaQs)B2OpT zYbWp6=x1zAcUXxX*u4cK7dEa=e@N%I75I3Z8OV>#GqZ4T&a)33 zZszkaxP3I7$G+m`SNak58K>Clu9;-Voi^ey$sdj1O2T%+H3hSXQ=Qy?vDNk${QGbG z`v(8+;h%fgx0`RpwXL|{UHsk0-n^dmsGhJWz7JX>cU$0&rsBaaXlIjm$H`vS+2pmw z?xeZL_{6qq)~A_w%5B?SY9*$(&W#^r{kpt6-h?01z>hBOv=V-FdH1|^o`wD5ZrA?M zH5K1BXuSN&+vCpP`T4vTy&@aD?4T{gD9`*_^qan(s2JsA=y`{L$qZoS`x-fnX=!-+ zX2E9O*P;(Pk?EV|Lp#F)SJ5d259cR#jpf~cF8?Cki{4ecs9X5H6xyueJ~{FS4E8hk zW#Q?C%j&Et*p&x0|2pib13BkkVCG*&ylT^TKWXIi0qX3-=TG*Rrg`rCo94Onp%{FB z{)%B<7@j%!Vq$1zCLTk3=rg0^unixRjM4aC+#Gj}(4ko;`oZ7T+@GEGe65a~; z)V3K1`{QG3pK^ZtKj1#g)%4LP{x{p@e>;hn*K@9spW8nVT+ElRZ=|O`3+@p|y3)rz zwe8+>>D~d^53J#JZrk9!;FN6J8AIFf*<{=3Ihk!=K-=Q=K3ba+^z{nPJ;hm8>_N6Lh zn>v?wT6>T!7Q6FXk6aNGZNZl%kL)r0GTjd6>oUW}9%k&UP4w8%4t(oLJLB)^?(;rq zYyxvO`@A>LSsAqG@B3M0fiSW*^9jZm__DSs4}5&v-ATbncsCXpc{m^#NiO&K&vSj^R}QSK9S@8*^4^D~-t9$x*Khw0K($BxV#fM%X3U0v zCMcQ{-HLDcaMga%1^(68;2V2}#^Rq7b$LF>IzyHpvS`_t6MPwAJ9sHN-&Cu+^ISPV zICBB~ViWvA_tQG~5{PfKiKac6v!|H5Yh&D9y9t^mKYuOxP@sW=o=wp8@)F5?5poix z?yrTfu%|d?PqFRP{k5B*YstaF-|7j@=K2!)AL0I5<%sIfvEGUi8NS{wzPDx2u)iMS z(~|d(d?C!*=Ak#DJ1$Pe+6kuO(IwzTCg0pwcBX675Asd;MK-=EnNd7KbgX?ytcz$FMYPsmZ_!zM zfX-xh@#(DHqqFAmI+KI`8ne@y+Wa>9v*ZN-9Ov~jt#yyW)7zoLQg}%}@~s0c(@rAN zy~NPu^Sl>LUI?y4K5Qk#v-Q3`aPN}Y=Xs`mxSiMm(W_O*KH|~qfVUT9(!g%y!G8kJ zvhT-bgVpT8K3*-#*fSASipO%d(-GuT_0i8glj={oxN6}Gm$|Wbta+4YimPLuEm6Mz?52vT zKY(|MK7BjoUs}#Q_qS`q{DECQPrlXey8HJuYi~4uBiN&Y&s@BC2wGt-*lGTA-?Lsn ziXHl0ou7_?BfdR9g(GeZopcJ>?|r@|KDLSV6+Rrp)+atD9#+eGFJrxl1MRJ8T@x>W z=Sil}dVvGnM~_ZVdF&{?*bO??pnvti^O}3?nhoqzjd$IBapPTgU5vin+j!T;i$yaA zk6Q2e1K`oD|7-C`@=lNs+F5jfcZExfv)_f``ah`juj(g{EDTNDZ*lLR>g;7)t}kHW;1kAA%eA9m zD;r_oPsMBa`+g1Q-^!=r;E$h8#ugnkW#+PEeutUA-FgfDSnfWhGCKmfDxdXoRelqG zNBi9Ck1zc>V)@2Tc65iLck1*03J<4VS&h+R0zI@9iP8CjX6R&G3GIe=WscnoIWR zW1LQaNA98CNOq&K?7g|{c0Nw~v3}ZfghN_4pD$*vdw-g|mshR1?REoV5+CJ@XpFP8%md1;O80omn*j@*4kg6O`MmEMvp)DYz=!p8HMk<_V66PSa&_<^LS6gZny$a(^=3G(Ao>Ch2-7 zdw=d&WQ3ru1URUN2F=|t&nwtI8#I024{%R&PCHM5BL04 z-X}a<^lfimrav>HHSSdi95(2?}zHkZrUFla$Ng%@ZkD7ekHhz-ePI`QOX`3^Z02uKB8mWTV4I=(EDU>JuUjt z80hO%@W9>vnv6ID@C^2}%Lh65(J4K9g$F4v^vD-NoV}8x@J`NOIj{Ha0XIAn(m>dox|z1hgV?}NSeeFyuqqTPbM>=VynJJ8v%;Qll0 z!FqHsm~(2+1}!?49ok*@GlriV&9XYmzi8EDo*SjFds)_XUo_&nr)(OT>z*y=qt@Nk zvEG07_<;Uho}sHq zA57tcYu|El!{t5iC;m`B2Ha4r+Nr^fk^NXw`b{bx-`68$#|qjc&A#rP5&1SrhqcN^ zyV869Z_s&8i#-cDYb4qFw5w>?bh_5;BEV+BEMv<&Rg3*5H+y~^2J^_#X3-h z?^hUqILTc)JL7H$Bkw8(d;@vRpx4?yeD-$WQ|88Jt6T}?rkQe;vOAn5U!A-j)}OO~ z$y}*3ToeC`%;lfoma*UN!500-V&6ZfT)9kpwEwA3^{0LZuxb2TGUhzJPsRGGyxD8K zv&!eVx0EyCG(Q%db07Q4;?!9;=YXmwoNZ4#!$`^OzP!GVF^X4>{j=#6ZNYyy5q#ZlX}SW^ZQG5@?h+q@de?$#gDDiUegzdtCLT?;_4J1GICs9uK19Y zf4tgm2G;)hu>9Zs^W3%!-;f>j>*K}7-wv(p^lV9@Z@gO&M?9d|4luB>!x_ z;ZtC7kBi0m^2_9wMD`!MWzI{HcxKBxO~v5r0$JwV7rXJWQRX1@X|xCL_d_xU!-vH@g1& zw+{2w_3vxae05(_pFWxIqs+VdZ&R`9ic2TCrLiYgGY53FUOl^)^4LPm9XodyHXG8hcX9w|b z2;cMQXQKCUWAQzYeWs<#IMfOgf6?<`2^4-Y1OCh1ys$C~{hLG(psoTjh<{+eHOK@jo*j=_uoU~uX}ftJ?q_3_N>?Eec!9=-eOO9af{dI z7W&-c_33|CJLbFB=UepIVizqJjxC2qmXTYej((TYKQ!L!`^EdT_6Bnltu<0sw6-Te zYa#lTUwcb9J`Wt;UPXO!w`_;U^q$Fc(O!u02p)T&s|YbnG5D?FB^sxf2RP)7Z7*Z< z`RW_&p)OBQu2PpTbcU?nZ1-uY?KQ+fiAFQWueH+nwN@JcbA0-|LgUxi{BdUE4Y|g4 z6h3*FJ^$y-M|oUx$uPb>-uE>WACwGJ2JV?y*sHEF_chhB&JE(___Qw+Z__8^t(!{z z4(~3y>5O+F_osJq_jnWXN*8{LzMS$`5o_*WO^sjlu?^90Mvs2|74c@rso1=5wu$HJ zmh7^c7&z9cXMeb&2W7q3VST2v4r+5FaRs+|&%`fdcer=kO&8DCd*aS+;Jx^MMS%A= zc`}Icx8STzWhFODj&AaNDWro|WU&{#2tSk$q+~ITms}g`#IJ5amf+s0WS)}e*#n38 zt=#R3H~k>vSbp$p4|Yz>`%J_s+`KGY_+nAi>iBiIu%~U~!l#~s?{0zbinngCD+b%> zhggXN7cQ}OKF71zB;wMqx+U&FU(R#xeNu0nv#nz9V##x{m_(Bxm3sJ~@MWK#8v#nl}Ck#Ic<$!vIK6ECZ2#>3c zeH4G#yYIPp;O@IGZl|B)$id<0tCx$N6 zenpOVd^8Gb+a^VO-#EwW?PMHRQART2K6FTMuDHFDI5&8(+N!?tf}L%%qrF$*7v9Wx z$=f>T=8#hu&lv)?Pby4CV0g@cuWoVh$>gZ!k4+f^J9uFv*s-2{?29GhgZ<| zKYzDBJn%bWRQLBS5dS`7jywMgb~e%WRlwjNvR^y7cf08S2>kR_@1FQ0cZJN|n2KSR z@9ie?I4o>-?^@r4{cq{e(2jE%`@(D8yVg~1_x;iMCg@k?-FxCodv;T{W}JJ^{qc|5 zHOI+qmI&+IBH!@s>Wq8i`-rWKeFnMPhJTX#CiWRC@f>aFeobWB+H>OL=jFx6Uj&mU zFYr0!7uOz8Su2j-^7Ra3|t02Q8so( zG~t%l*k;IX-4VM2JOVDqKUzl`jPhE4ZCtp`fJXo~`simp)8AFN?=C<`rGEc-YwjV& z_%Lw&BJ(-q!SxV#UB!V@gtbTFU$>ckCITJ{uJU(U*zLkqrwCP`7PR6Q}v^Y7GhiKdJQ)lg)+65f z?6{N+7V~AWFJ-^OuMk<_2z=={u?Vj2Ska>~lZVjgj?adsweVo2c$XXR>AsH{9c^06 z8tUsEeC}l@QnGm(v6b`ek{4H*7$mnW@dTzV@=O}r%d?)WQU@=7G-)3z>+#R2k0AdY zLq_fo`Zn{s0{O4si#0H|r0=-$$>p?j#W_~um4GejICR!DX;HkEJ!ctq!sRBH%QO>f zux6O-HN(ug3EIuHB~`Ru5FbEpQohZ$4B6`{`i+Tygsgc7;SaaKAHIeDa|n7m=<$ey zz!lxRrwiU&2|o~z=z>n`;SrJ{EB}@|7tpCxt_dE|4_&Lgc*MeRaZ4Y0pL`kF&2j0< zbF6jkMbuYchml#EXwwP1yhQ6)?ePxI1r6_L%)&cXdA!5)t@`lQx9K;Nclf*%+($nX zudYbSm3Ki4l&^ggyQkjCzvox{JIHU1BUQdU>C3YhJkart?XuT@ zKU5~({g-d*W_jAl^M2xN1*~!gCIxXx^ZKA(sU|vLj4)2!o z?jLy0opGz_h54F4cjZ)sq60*vO8q1uh}=p zM|-so_-ifsMEz;seDj?^{;eFekdy~UIXkP_YJZM6W@y5_uW}(euVj1a>0LdxxwGUh zzRQPfF|bs-e!M*J>TP1b5MQrhAC`?qG2YL9*ETlKP524=?~xO?*PL&4fP}?CyTVd_ zW7Dp!=M&pbZNZhUEp@|n=$_!B>@&;QJA7Nsvi!E*hUw%8;9ViMKkRZHYlz$5ME)`H z3bjF-uI=Q?=J>hnH-1~j&f)Dt)wJvS#ZBvR7`OJ*Sa^1Ai2IGN$iKHjIR83)8~L|( z7I>$5yJs1twaOc3_A}a-oaE;%Xo7EOPYmWQXk?t~S9scxv9JABxJ!A5JO{dysS=qo zO8F}GHDH{yy=V-<{l(YuwYSKp85}Wjh)MmP+yR-s%Q_cBHZl9(M%HB&H16jL*f=r$ z_j>p}?GB4&QI3H2U~E~~<@f)F&im?ViY+T0A$OPVVfhw(&Lk=pU<}?^EG+0H2iscQ<}_2o2nn++l`() z+=M(VT5duH?gL&%|Igu<9d97-*va~3@6x^7`S9Oy@Zs_BV+Xz*LGMHNyF1kJ=0`1~ zEBQI~TwfON{%!VZ;k#({$hlVU0CyTiu1wkc3!rbECFzW#8M~Nx#CPBc8?c9Ug7X`& zkJTZMEd|emc6{0D8uF}l*m_oqFX;VR51?Zd{i;m^5ej5buR06LTGT<@J7 z$R23w(>C{Y*Z!1u&D0nFSV$Y}0drPU7k>S~7WjbZ-{%z?YYSyJoR6H0eeOQXntXqA z%lxMz6E}C-l|K_-k-xIxFUUy06D^*ry_@^P_(!g3a$Gy+97r<7m0yj1Gp^t4ukebS z`isdioZnu79j~{Fez9d9n8i3n{2rJc z?$+AwLq?QLDt;a0kv{+GB4<@5|3cC-b2-cK%|H$(cwYnQm&aCqm=W$=up@Q!+T$fw{XpG1~h!d-KzybY39Z2lP=qz6xpU;X!d zgI)L=-}r|9M>$KeBH8?Q{CFH!?y!*iT;FKLZO71GW&hJzoX!Y(z}vzl(Vfd%TjDLE zY3#!rra=49gwF7)updjt{Saf)9$6l+g?9zci!W9-zqwOse_YKRk~tXII|~@6 zE4RD%*7&*NCF8aQ^6uQi9&uXZwR6}Jb>=scPszL5n-)5P7a_@R?@^9))k1vg{KoFZt2s%|Cvm2w71%u`I^16IrnVT9N(u5Okn>bE8$( z4(tfUvQ6k+R5Vg)^|FVMqYZlnvcO@^p9BZ(3kzDmx-)WRYrL6xONQ5T|D1IhV_e3( zWdjoIbCqde9*^=~FiR{))?oaxzgwK7>$s*fX1a z{lJtvGp96!XSA#?Cl4Tgc=z)A1U6spihXfgVf)}>_MB%j#@T=@VFSzL-o`$sz0Jp+ zyBVL(9<>*9VfLW*~LFwniN)vT2R?nrhC!lPjob=fO7q0c&ihTii=X;_ zQ*U^@U2yGOT(L6<*FIoud2p57GyqH`0|}0g-fX`tI1a$$1n9lN_JZ7`LZn5nhIw61ZErYiK^#py&fA*F)-^!@6tY153GuTRShz+ z&YeYjMz#_ia?UPUpct6cpwCNZ^7jnqtHm>d@cBIOLDrmmbduG3M6sNdm3}DP7Opz2 zt??%2V$+B4G}sn7+*=;{!9x{CzrU@*hwXM?CiwdBh@G>f`=5BG{pBv;S0?xY7X!CI zxi^yQFrEF{^}%^BYkZ)*Q;SuaBM<*eF;!h#Gza}m&2=Dk4z!Qa$bk;yMG*>OCD2v zNZ3ch?mhx+dZaHDz>^1gud&19b)QIY;gv0M{~l$|vxnWIEM9EN!i!a2yjX1o?@}J% zuD09Y#j=|Rd5(Cdc#dQl@to)Q^m)!qZ@&_snJGG9OqqN{^0Q!!e2YCmK8rIrkC|cQ zy-lJA_VEGE=j4wjo+Fy8=KSjOd>5S*cyuD#u9d$Fv@QO%2l*-6`ylOqM>Mao!!Jeq zwsgFpADcb1 z`=GtSrENE!CkAd+lIOOd%v$+u$X<73l9gD+_^ip-b6zF5xN(g5hQeFE@;AX}+H3Y9{)>wff5GS7?H4Ehn$KOEE>8RdI`Qmi_X+mRW9Y)i(UA+; zizGYj0Y4T1?{?Os0RFTexXX7)bfIT@r{~(^d|#q1tiu-e)oq?Up?<3=7o%VENx$Zk zezEBnukqRxE(F`y##(Nq|9fY-em-H91+N^9lAp z+4Kg%Km9(J-(~#Hq(#w}+G{~y6n@DM>J8sM4&U7X-xdBf9v)hG<>8^ZVRQGCa8rAT z>)ZS|<0u#(O_+P7z@KG|d&92U!IpzVE8nJ1!MqUIM_O-<-$sApC6cXT9~o|2Z2ORF zXP8g92tI4R+~WjvbBB7Fx_Kvfq5XI|^+Z=g8^*)et%Q6sHv=odo-=Z6!qyz|$=Kh0 zO1VU*a8Ca@?LGVd%<8=hoGZ}YxzO7?!L2>lxH62|d=^+NhpxBbLo_s$-#v7Zm3V@6 z$G%c~M0?Z*WFPqb;f2swn7RjDTjCphcWGCC4Wunfw}nf^K0aZbHO2Bp3{D0c)C6__9M}dc!Ezm+4dvRfOtp@+^DoC zw3K}Bz6$ZCI*%u0t~kqxBFTmIx1lLlW*@y*FsXg{|n%^;r}y#V&{@HUR%s zcV4&?JKW2vn+va4tBz+w<%2Ew+YMyETzT1E4^<4_x!CGB7hWVB-1m=l-O>S)wlVS+ zXVPDEf=hp8z;YY&^5?x7`Vj4Cj(-JAj_tBLO8GnvY+O2ZX~w_;9_Z7lWP>=i7{NpM zZR|#WcS(2oG^=AP_hsq%0MFs+2G?WY;kIz;;2`vA^akKXF76)Tk)G=gyuCd0=}^yI z8k{jA4JPS|zI?h8Y=!^yzeD(B)-^X>0PE?4R{_t>*bil6^XWrlI2qbF29IqN&3W`u z4-R#QT^-#92VH-=&mljqK#u$@^5kcbD?g2ldnxx&=b5w1h00a@JAB2xa~ttY*=-+$ zhbL{b(IwK z2#+oJmUsqo=?;vI#XfJ+JM0BXxS2A@cj7COUqt(nKzjoLzNWgJw4c-m_}v&-17D7J z?K-QH`M$e=hxXp!xtU-jc+S$N2Y(-)(#?ICt%45Bb7)C6p0Uc_7Q9Y*Z^Y{?WDkAM z-0v;g)N_1I=IB%O_V29oXgP2MYu&S{b5z!Vdk2YAE9TsYJ707!ht7okdr@SgJVbdL z+vKD8h7c2M=uq$1Pjz{F6K6^)6G=pSt0-qDtlrfHj2k@AyY&^^gUJ131+CFU6VKO7 z#OIRpyMhnbcVmk;y5dsX%6>Og*xj?#j@pQ{;?smZYajIE^OIm6?aZ7(wvP+QLmH32 z#>#JX82vrheNKXnWknOKD%^Sa@ECEf%xyjQs{xCXy3@(bjX7yVhE;P^W4sdDRB zds6qm8Qh!{#LaY{*^~B{-DSNTysv8|caF9*X3=majy6IgO%s{V?dYE1?P|`=wMMHa zF6!31RoKoK!~d@FaJrdK(c`5nK=PkIZM^W?g725exe6 z@mszeG0&G{AaL&V3vl@7_;UOL{t=r84np5Y@w18z%M(1^`0mvXyW7*vp&f%BMDNYu ztRFW~+PYv={?VPmKe{~r(dF@v&J6w`zl0$FxNsEy@rUA5#=pbkQ#LZpsfe2!x?4UT zdB~~x$gAU!TgM~6I@mw)^H?0}2>SIO4v+7VPydl{zMD%O*@Jv0_(zBEPq%tzAcx@h zx^55WLjQ^kbx1bTN%CK-ti6LfzWx2U9-RUG!pJ9eVaX@1Z{`VXj$Pk%&uOI-&jjwm zN%8uwaW3E91CLTXv+%WCb|w5Lmt)(DW9OC}nc0so2L=1_cubFPgZKTQe7cbhyxF52 z?Wf9XIuhOdl@-6J3*4Oki`KZtkU(y!h93-||D@3pbfdV3nkUltvugAR&9NF?R`@;Z zZuTbTsX0nVOYl61kDLW&-_O3|)ya(UMmN!&%^xFX%x=D8r^cnW`x$dL|I9d>f4EaN zUhTcXG5ci-c;CeMKZdl>WI$Hp)RV#Sg%=nHq%3>Kmf zD{d@44ZH~Q9)6d5abtpCr+5$jYmTM(@0Of%dSbT96|<#SRr+tskX_b%xh~PPx-QXj zJ$I|$R44!B!DYX?;}!gtUVbZl?<2K#;pT1JXDQvfac_YctIDmRyy`8pBb%4M^T}6Q ze(|*jo#vMKva0BVHTZfJx7Nlb<22u7yZ#n|{6_EGxfI&1hlW1|Eq@Z4UV`p<3A$&> z*TU>SImYboKkgotE_=JrW}dV>?%Y_Hh^(yxry`ppjeIiy0_L@hdDS#?hR3|Bz&ov# z&mZKAIOh9m*?0bscd?F?W7n631S|QNN!Hs8pBCLX5&m&stBFVCzE;JZe}}af-w@pG zU#vGU(C=ctE1&+!>Lj{nwm%@-1$B|kdqgA>{+hdc3(K|=F^H%FDcnN=X->&+Q4lX=M z>EJFs@eFyk-uN)|F{Ww2qJ0st1{Up$T>js-HwBB}dWu&F_P&0Zxu)9d{I!vtP2(6# zJf_AOoI{B>2hpLwf37li1b5#RUUmiMfb&+O%bP=&H;2x^9EAUZjqDT#{u5bYO38*+KqYb#=Le1vb0+sXcvF! zK)de#$+LuWPO9B9+I1GYYw0X@*V1|;wU*6ahqvDWkN&g-rD$Bp}QwgPUTgPTpycj-?`+KWqY(IkgsEU^g*X2vbp&4R(I*2+uco+ zZKmuR$`-O$RNKzx2<2PuwG%beS=x*(i+y?!*+e#+IwM1->$-{$b!c~1iL-gQ-dom_ zw9}y{ByDoYV`27P;gOGbJ|2$6X5+N8N8ID>5x4t$ggZ~OM=+jh#)E%`!JqfbJ~5iD zYRvOy?-1R*ALi|R72IPDBdlowYpPrnh2UBXc)kUGEgmiYe6L;bBDpj+3-=rByaSPT zJ8?JocyQ90@ptaD(LJmV;gjX_Y-q>u?62F2ckZm~J~)0+T=rAt;5qh{5b{p$96acY zQ^~`C?*@Dh9ogwy)LL+LU2oyay51r?T%!Gn*uA$tc6s+Ld-FQV?b5+E zw&{_4a3f2J5}QgwYC!nkbn6ckR8;%$bupnNj<{ z|K9#RAHtl+UVE>-*4k^Wz4ki$tYC);p8REXKGkBf54B>x^{JWSO9`p;PFv^8WkU{v~larAP;9i^ERe`=2fJfWGBbt8=j54qOY(oz6 zl>__HfHzz>E5N58v?94`p*0EGJ3`V&)qfVqm=!sv|8LU6@FfIu8 zGu+R=_nJYpm_SVLleJmHAmSqvG+&|<&PtG=SAF$Lp$obVDt_K^%Jz?If|64ukMlFH=cD>T)vk3gD(M& z@&GFCM=T9^R6tJq5i@&~u_Z*q9rWHI?&ag2J9VwsnKQNx?{e@lm<%{K;K&Y_t`l_K z-pPh2=ZUUQV%?T-sQ3wDG?00ce~N>tao`uhE7h;muUnj3{V#|I37u?8%kDDaT?MY2 zsXpM-g8X{Ir!fRRq+fXZ(jVQ2{e3EadaZZeMcG{>BOQ>-3h0Y6;AlmjG{)pXteJI* z_pSMRbVCYgNw|}Il%^}-UpDj&_RU@W(td6Oa!toSM@+(K|K0B*{$7DGPW$tGL~vvW zroj%B<}Ian6kD(dMGNHiA;{y8O=BtM;7dZz9`W*|75WnV%_9EdJi*Ub%GJ^Gm97Kt zzxGYReio9iCcNKEd~E@LC=ZFo5cx?IOQY|k(|Dr(?F3C|z5kSXdf`pV^e9?;)Y60G z+RESIi{o-lvP|-usXUD3RvJevHIN@f@9&EIAhG67*MuL9gTT8Tlv4wnk=h6Tzop56 zq3>v`?`j9?q^0%g0{Pkp`D!8C1U{!qJ@7F4hH)L|fqkI-By~@t z?F!rUmdP^%<7ZPLY#4ILptEi}+zL7r$~>@r2Si>qKExL91m1<9 z?Wsv@h}LlXfXB&&5*N{aFY?dYs7(iQqUOPt?Eo%+LOG&~8Uv(!>$`D(Ct}t4P340r z+oFoI#wwfcLj66ENfTs}>bGFsn$Bt6n)r|Lc3&Aoo6&-&L<6GdyW=l`9d5oz&|c*F zQqFfM7}A9VM|csec+WZ@PxP)eJ%9KjrEA~1u}i5=x+Z-h^s10WwI0f8pn8b6eWUQT z559gW*)7nH>PsfO4<7)25TB=0E+~C-{V3jxUTI@(l+Sk8+U%}e3tJq8bF#-|14$R? z>r(9>jk^K-(Yi0qH{k0a4>))aZrW%0bHq8ddo8a7kLTgNU7}YM#-Ex?TLB&U0mjb( z?At)!<36HHJcT}#R6;gB!aDjsxvo#wE0HJhXWXM4P|B;NcO0_lyWc3kj^1&wvNM0e zIprt`KA9lj7EWu@HR2w9pMv)O6mv=HKhgG2(0M9v)jhX~?q790{StU;eP7ZMs*V-< z4&NpmpF{DBIBhv=Y<8D-GFwFX4^*CXh8H|df{eP?o@I*rV0Fe=>*daSo-cad_v!&$TxC#7W4fvNsl|x2Kg3h4plzzJOvzAVh$!Vz$kqeb{P!?z>+cc{;RKj|*D zt!B`M=&hYcsXRRiK2d!N>YL5Sg?JB-_y6=Du0bwSL_q*NS!^ z-roV3RLpDC@W9p{iarcb&TBEly26+P zedd2yw&VT)y>>hpIM?>S<)=4=#{*?T;n8yWcf-S?Oi0+DULPJ7WkSL3m}>93bDi+x z{v>Jjz+>4%56zyyaWxY_?jK)|P2p&|VGdxS;oN`Y~?| z@H5`m4WCgR7xCa{C*)im7yT%|bM^`^twmVCLz2Nl`1}2kVS4BPE%0Lqd&JGa`2HO7 zNaK5On0be0vMvY4H`YlH*fG8rBR`X5xns9-{CSP+Uo2(+4k`POzI+qjJrn+|TK*9! z`-M{WpMvaHn1khB3rFy(Z1rLNkjp*d7IsyCV0{qd?O-3~NDTUe`bY1#t9=}PDcRSH zcOqJTdP@YnyCo#=gzu!v_xHlrbNTl|*33w>Kf!b8C2M6H_`f|S} z6@CTwUz71#Ic_G}hjt>rmfjhleJ9lV-hqAaL1*=A;yWi%&uBTf+Bt;By=uP@OWE`!Xogq}d_M)e zRPCLZ*H$2=9csK>xLxEaemp*x$NoRL;RWP7ATD*g3H#B|dV$iZ#34>x%GyZBlbjF_ z9)wMJK-vV#Tg5xF+$Ov@+urq(&L%*1xJ~$EgiV;Lu?bUyY{FF7grho}pyK+;4KK?W z)#&>baGx0RO=F$*DX?~29b{8_VN?9}K3A-b5bemu+?W#Zw^SSR8NO{XI49VLT&CI> zyvO~(w19sVFKx_b)yCxBe3;@WL_2O{sC*U;MbJ&uH!Z zlN-#CF?{p)_OV!#QrgtLj{0F6Eo%^;#a@>bf2Z+6@~zGd=it2?b!@A#E)V<=8sBkE zTMkDO8}9!Z;+%+a(fs00j9-c&_D_;J0Q^zoT(llSIv{BLfy^U=M!;}K#nfOlS|i%c(OhQ#N*2{_VXgwKY_Jo?bfe&BS5M#beA(geZRhpsa>ATS66DX+z$aOm<{p>2(E#LMi@2OwlyLq=_ zF1_QfWl1~k#NQ6=M~!`}WvuVTi!dj`HSzG!G{p7zGqGQN3%*TEYofGQlJ!FNiFrzE z`@pn)GkjCo!R@eP!`m(1;X*dlI~Dc}`g;QKIsm+Gzp!tu?`78ZzS-1v0C-RiEXB5O zXC3uF##sFT@>~rP#!qe1bBI> zck6}m8GVI_+g>enIKA)N4}IG=sr#ya&_vA5o3Hu|dzuV9nT_w>c3sJSy$jbeIsC==QVba zeHab*lh~J8l{ro)z($I@7FNir;Grt3H=Ac7_l?y@Ltd+t))^$P{2lZUh9RT&p{>}% znfOL@Lx1D6b?~?umw!>GpB`0`9*8UW>EVzzyiCx8#;6+Wf0XNn>oJb6!+0*ixGu){ zUWhv>E=qrr(0kntpYVUw}S!>-_`V;#gT9Rb>R_9kGTDcJMBv=un%_W4DdkHFD*VHX*J5+qm<}| zxreqsb#25bcfo?#vYG>gHObzrm{#9T%(*thZ=Z_2tpDSS+})YxIFDs`+lhYcgP)9h z1HSFgWld=D&7n9yV*ZIrf^WvcmiB)h%MRwF9M-)l-g+PYxDLXY8>#^9ksNb|@;ND9 zOtI6Mp!;VZ*`Kq2wCx1pOu2-86Q_IbJiF}##U+O(&hXHE>wTAwH{W74v$majA}sV;S#s$)PqXQW)N z&tV6R^10MK{$S_%+>YV_$;`eqm9HBJeK#w9NBcV1=swZ6Jr9E)308J+`gnGnaQL=4 z;Zz^!yB+V}e-7X6ahz8~z12SRwS>LohknOArL_ezVQIR3Fn>Hd7>Dt?2*3N`2XsDd z_hQfCwixJD(ytGooeag(-hws~l_|b#`1k$jd(?#N%;>S$XBy=kC^rvfwkz?zNAcW) z`8wSzjc;jhHM1qx!Jb$UpB^w<+_Nk3OZyU1+-3%3 zfMk)@F0IzL+LIqm*h~IE2d=p;RHnDmbvAVH9`q&d^I`s;{KptKB9Bbi@Fdt#>NEDi z>eR*x2#(@&`uB?{59;%1*!!0QxlqJYM>9LqgSH)Z$UWc7T!Bw)B7Vm?m~ti``+BD` zlV?@-cCT;l4}Uv)){&xeY|)Aqoz-TU!-;F8yNBZts)K$+}`HCa8ojvw3oloI2aV4CDvsZ8>G_`q*= zTk#ypguh*-O!Tb01A~7!TaET=(C;5z z(f!+$l%ccp(cV4i|AL-R&myM2m7J*fwN@Y|>jFPx3a{v+_V96j}G;J+~nAIo&;XG z{`0o`t4dzp?L!|{Kl9S=4?*+C@wbXi@H~@e-8%to9eClIqaC1W4P&17%rnvtT=yEv zP4L{q#`co!x51VkP?WY=OlgZXO@#i8^4y8`=fq+S5%TjP>X~c;u6K9uPD;r3-nY%V zH^vn0xl1v7icsf|*hJ4R@3GyNH9H2^u`!-qORaks-1mL&Daggu%2-bh%GglvDd4r> z!Q;D;-|0DyI#%J?%4d)6PBKLwEkt|w;{LVh!%8;J^DbaMMEyA>FYSI$8Rw}39X%zl z?6!dp^U!w9XTyiCQ6?VU^+M6nT4mDF1L)sQ#k%(xemj+@qaG#t=t}gv3eQ*KUKRdU zzOWM4g+~i6v+S+Rw(KQ2Nx}V8lrI2}>73*=3BM$tS##N$e&{(`o3<*7Ck6Z=pW~ES zDV&Gv>dRhi$M-eb=YjXp;QdM^rZXD+&xg$Tz?J>T8UFT~<6A4FJ%MiI_T){>hX!H0`e9Q}!KMsoY|2BhDVcto z67Oq{jWqYaC4G1vEq<6!@mxXx7ApLwu9`O^MGbNe&R_bB)l zus=JIgUyyqv(PsO5<6R=PgmyImqu5)Gbvw`Yyj*I-{*zwP6pcf74W7#U9j&Bx8+#J zUPSigAmn-w^NPOl!e8jYJ@N;vR``7M9nDzyYGazOO1!|3=g5Wzzy z1+sC9GUq4%4EvO0p7RrvW%i}^q*<4aMXrQn5<8Rs`SufJrwc&yEM>;2f${rhklmtn zfuw|_OQG-ZUP8)GC?@eB*4t*;TG~~=gm?x!emoIyw7yNe!hZbN!wk8hsDto^57s#c z=QEXfm}Jb6B@f-`M>70?7T^VWAA-L)6o=>i@Ec&`2V3bH{Yh^6&R`45_JB_ovilOx zZs3e|eT2K!D)>ftLw~pOx+hpX1W$AT@6w4571(FPf|!|_j~uYYS3`zZK$i0$)8c!< z=j)J{jQ9eLOR~eD`%?08D&TK7!_T05WXHv?@XhF4ADd4e!_E+#6L`WGNT)S+@|6=6 ztgB%{2$j(r|_v4!}iAwybe#}9s?=;tS zOTNzn&xwBwyh}ztRicHRF@rZ2*c{8`?mu9!^g_<#Sv~CpOSmI{)TgBFY0qNuzI76Z zKKQj-9Ecv_bO81DMf#2l`k8!w+ll?L>`*iOacZLiyetK8K}Y!77EV9l-Ps6#p7@s4 zl#KUeS=&C7#kT`vgXAFr^6>BkcJN}z6XH9^7ntKt(b(N*j`Nk_cW3mQ?aR)@?X{pE zrKn>&>bIkQYHvI0{d?Sh#5`TdMbomuX=eM-v}ktlqZ7x-WoyZKwLs?+Vm6 z^Mkm(+szmIUc~hv#^g%WaXadudzi15P(Q4Y-xQ4Tew@>H!!Rc~csj?vbO1a!vx2^f zHmx)23;44pR(~C07Vny)dhtyol%0WneKD?}OOTU4G!MEY3w~=Q^wSZ%OE8P_ryyg6 zh22>Or5}m{VCmAL^?G?>CXH z>mlCBYkDV({DlOJQKHd#^UO}7?L*lA^uq07$CQ6=M01mm=U|_h)mR6(9k%2yrA^(} zWB*;33|cIZiv)|$4Z5iBc4Uto{1wL5aSPser5qQMxeh5~eR%(a*13ikvaVF*4Xpgn zZTC}rGbNtkeUd28$8!|#0M>749&_?>*7k0hut9z1?yH=p?yE{o%~zd7e2l*fjJRMD zTmO>^%nt`Je^TYD1@Rc~U4PH_kR};X{rQjQ1pDynT&W*)k@~|g_o^PHeFBX32vGOh z?!ST!EoAtXrUf~)_$|P1)EMkNs7&dduT1NGctW%%#vJ8|8N-H-LiP*s?$15=dlG)n z_6zKc8{;GzaQhVHOa<`W4&IS2+J!Q^K%-rt(RTNI{*FDBDVaQ>`+Z%@9gr+p`6B>~?T ztx~3W;A6K|Utn!$`^>IqJ?(f0rZrhfZryod#cuG0*2RbROtgA#oo+3(4D)#3nHkSM z+MXYXyFfPTRD?R{oeZ+kZC`uSzQX@5nTT=-`twskujZ0*IoBh551dK36uhv(5# z*+psph4;qM&M@ei#$r8fY+R>}v7t5iD^ysQhhzw}os52*G*9Y10Drei`Bv*|sB70{ zueHO+?u<6!y(;sh)YT|Y{oaLGO$^{E7qAd;`S_)N7NURDXMA%uH5UELf?QI+C(eGY zJsLLdw0S}28PszUYs$G)59osV$nmW6>`XbXe=zH{_Fb19Z@-(xw%*Ogc9!4G26NF4 zJ-eGtY~96TI;(N5#o-v%?Nj3I_hXIx3?@1yRBtotMPE|SAVwhZ@J+h>c>DbBo$Z_O zd=i_~n#5vy+2!5s6H)I1(}LDE%$00kwoAFTspI|g>)9z1&uG1&>AcMNRI zeAp(s_rX}UI8k9fid$oirW1HAwK~~S@OEi7=tFJJLtWby#fLdVNh)+qDsZWUPARa$ zA46No7V+!Dw=^-A7;>Q9Q+V%Caiy65a=_f1p z2lG)b3iZ8@dhiiYeqPAiw)lMJUF`+#d4up>hOBs|#mi23p*|`*4|P?cE;qG_x~NY2 zr8=W|T~=OK6zT#VL)1<_p0C8ZkRLacKc z%)!AB@4&?++4)+3yb{-Y7%^iD-Yv0S*mlB-n6Vpn_!MHscux+w0CByJ2|Inc=s$md zNU`{)+jh4981cSj#E$n1eEt5#5aPp0n)q;!3HzKN7W@g~#MtNbjO8EL;FB0PA}&nt zdx#j`t?QU~3;K_F1Z+0N?1JOML*w&k-2k~cBkz;EQe5~yHF076+<<5umn>*aazgaR zy`e=Iznd4(p1g6sQuMLoM~=ZGrjh%g&|HD$kEN;jUMBD$92*x%zFsQ%I$K`DpDZQb z$u*Hi_`GkTU-)hbZ>KMkb^t@~DCp+{yj{>qd!Oj?jVxq)Nk&4+0=~D1{FmTwJ*)XI zG#6xck#j}YzxT+`C)>GxBDp2~Fc5tS&$%6d z9~FnX&e40Z%}kIgh0JI%urQ`c(hAAN`{8d`^kJk)BLJUr3e#@6T7__t9UfkMySs zPy9o>Bjj0K!%^u$dQKg~6&Nd+Yh%B}9L|5W3_VZA7`MQ#V*bMInp%G{Y=DCMvOjSn z^aY-Yek+~CL!w2+<#{9IVr0%=UdWuk3cS0a%^R$NOd$rBF7o3=Y=g=~k}nvUPS24# z{rdr({-H*vTUDK&y_?=&4e0dmkJRa(+Mi3po?Ao%TJ!5cF6dwsbb6H3=~uJE{~bF0 zn|=qs$Nsl&!#|yL@t}UcBCGUUD2IRQh1}ge@VBDiw;%|5s1o*-;$T=?=q3L}@3%~Y z-?9X;>;5lB`YoTrZ|RdU4Vp(s#Z2||o1>t|;CEtAHuwl$Ys@qct$&jJuExGgG*{e( z_4TJF6dgT=HJX*US96bJkmmbGOwqn;evmjwaka+l?cS)E7!Uak=iu*zCl2JJR>GH}&i6w8{&6Z_ z7nuQmCMeTdD_%`L6@Fn-)d=Gvp*Uq6##n_Db*6y$-B< zcaVKV9Tc0PYl>~PB8LxfRWD+GNb!8kY2(!Oi2bOW)@{gVfltttc!$YL`zIgykusQg z%gA+zUqWtPG6mKletOCn$hccP0IzeF2~ zIS?((`0WRc5Py`l1C+f*M!?+d_p_?uf-(9WTWCP8ZmQD1!x;eEuqTd;b>gZJN2~$Ao@$ymNb#1Z;5*JI*)qp; z()E1gF5QFrqcFCPP`!|qr%~@~hvN1gQLwK&=H3)9KY)7Z+K%g5)b}Ca-)O2CMDowU zKbt3Yeu%n$4tcn5vc2mJ{t``-tL)I(lc2-vQ2xM~Z6`i-*9=m*-{2nA@fxnNHw}*i zy^r`k`L;bx-@x-P-WXqs~dWk<- z(K~%!#9}_-vOBeN%Q)f3(|XSK?=$aq*pd|N$Aq}cp#k`LS=JWcKzVoMu5n9mB4CIEjAb%vwJi`~ikj~&|m%BpK`^>-VMLZj;rs^Smb=ka^W2dWH3W} z-4ewz9E>f+{Hn`(6T2v}iPn3dV=l4QpG1F7ZJ3T2`!h=@KKMRjrBzLd#mHB>_Nn2Y zXE-h>wjSX2vMl({6X;_x z4Q5OyTB!Ju{#LA&&1m1DBv&eEU;oUBdJxZzt5605{Qw;G!KzrJz3gyC$~L9ApW>8F z){F9SpW*^Z+a?r)CVV|rt+V5<#KCu?+0aS6hoR2lPGYa&ccbmdZ)T|-cR2?4e=@vC zEk9tMLOFBy!FF{q$RzQB%BV1%@GsP|k<^`kPFr`}sC7Sty1%j0-`MGvFn0Qz`GJT@ ze%<*2_N&2~=osWGJ4!$w+i*Co>>Bz}Y*F?z%(Kl)>Jonpj=5gq>rg!b$3iwdx z@V>=EScjzi56Uf|HOd{+MNaZg#7$qtJ7me2t68yj9A#zL>kGLshg#ZA$N?bx^uR<* z?~UhkcX#94PhxL1+EdEXOFDf z5B#`vie>D89wyj6(s#LmcVP+NP`J*D3*buMYqwyIM|sjS;`g!r=TBhytf~Za>G9}c@M#-*pIno%QSXKT_2|$|4_I zE*^tp<+Ctj!6#jXjsRe{&CH7yIw~?!i3&QQW6odf0eR0_p_wI1lvwLF_Z4 z{>+A45}sJw#XC0E&eF@7ck67$`vBK%V(nuqc!o88{yh{6`bK^bU;D

!2EO`};mxg)_A-2#-km5ac21GH{?WbjZMldod;m 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�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

KY7Z*!uJl zU%bLhOAw(O*SX1WH~67xs|N?o8gBreg=VVZKI=ScI93m?piKz6S-|D&(Ani;I^nnP03Y$M89DwiMNn2+z#+P?hBWE2=TB zZZABao*R0q*6Z0I6;p<8M&b2{P9BizK2OIR18Z2mF}z_GqsWpO#*UUX`R8%j%8*kP zNiWFf2?k76MWO2g(1g3u4ElOebmmMbD8B~wupTJ@QbRo(uL$TWrc!g9{Q<*~hrN58 z)R|bKiej6<2j1}Tyv-aNn^%)kBpr=HN7tekMR$}?@jFVTvW^lysy7A^AJV9z*e38U zMLKH8GZuHT9VOjWdDr_Zy>2~e;;IRI6pk>P+TiuT=xgBCc=kvVggMJmdWOaY5Y6gp z&zeSyPAZ$K5vlaFamk8h5jUoH)`|$nRI?f3pc6^e+`&zCkxXJBI+_RhylI0WHX;r6 zY%tU_2i;(5h_SpFlx#gz-auP)`WtACP9M{rupg(jJt9Mup=_BF`yq{Kc0aU(ZUR@x zlq&CPBt1@YN6Ver$rkv&Wrg=YP_nqpy>wa0y!p%LFIns^oqvC6G?8_h%q)&AlkJ8? zQ_=WE_C=!0NP6rJ$zW)Vy^?53swuK-5?f|kDE9?eBFSkiJ1Nlw{Y9&2O6r&xm?RXj zAu2ABHTF)wqx(~#A!uL~ zT0H$g%WmkNSzK8p0qrLT7kCEc{%9MEcP+e&8a?oQpN+D1aqBdek_$7Iak1r*b=<7j z!Z;hNv4qiEtg+<-jy-is+;)|T8F)~w8npPZSYZQsXT3>rwr69dg) z@~NWl(nq#z;}Qy+w{hu&ZQQtYkqzBglGv@?SQTq^6PqlBox?O6$V>_%-YQP_YY8>f8B zHkQ~N=kVt3z!buaB>jp)j1ApbQT=S~%7`PIywRnyU4Q-5Vqh{lzZjS*vOFG`R_4ZJ z4KzAWosi|vF+(18nj~6H_K`L|plHe+;#-X2Sk&c;i2YHad3^ z{8VHO5XZ=2P@oyau6|6truM`8GL~(7DJ>-nkq!J968YRQnin24vrfyVevF*xEZ@4l zA46(N;}#j-=#L?^Z28BO#ctupkkHNqodFF*YDojab28$Tjcv4O;e+AOH{NcJO`LRt zt!}1Zg@ff2^X5VEnVWhy(L-~;^JY2wX>E8?NcKSER@VfLM1Ni zV3Q@V+Fwn1M08P29hQ(4{%V|!$DyHNw4NKpY9M@q5M31UUX~*?p#f260nzMHMP!oJ zh7WKI9xW-}fp|1kKj(7R%2zzNXkp=EC;Lbhi)zvGrSq4qa55tbGw$=4>Cl*Ud%|hv z_R&c1dQY`+9>{nAVQ{N=ukqIE$CEgk)i+5S=`a?6r*_lbK7Wwmc%~7@xBBNAe`6y< zzFkenhKw8^3)0bdQ|-Fiz=m2UwzhG>s5TIEHa6AKJtS|H(_iZh`uvSX**!wx23(IZ zicJH$hv}1o&NcD1O|VsXX${)c2uWD-I0b$}>C&MWokxegPH!!>u*w-0*2vguuZQj> zI;nY^yg{d*ZvN5rCY&VW0wVURaDZGj%~|8wgj$^qxO1`IX#eUaoe{Teyq-ocb4IAC zcf4x$@qt-C(&#ih`f+OoTm%NaHsGud)FL26sSp>pz34x#iftfuguCUe!NneGE$?tJ zK)Nz?Vs`i*)_{{>+~BaNLstT!F|yvOd)U%IW1}A$i%4!n*Ypb>VRmNJ!K!dIkcNMQ zr=gZrczvGrerP>v(C=YW!cAl_7t5gD3Ghy5rKgq{!0UD1X*TapC&b)oRB|W!WC*sf z3RQ$_ATtTnR&R3ZNe1L^is;VT5<1a=)3C&Ac8_6D;0bJiem3~LwN5@Epl6zNcdx*h z1f5YNO^q}P_b*z$NH@wAP1Wl>wM=irP0`7!to34Y;~FH*@URbMIG5y;%`_zTP~o!0 z^B3QbuG|Crxr6D;KHT2XuXW%a?_YoZs)1Xsf#t#M99%M46ZE-pJ1Nk>fXJ>6ticss z4i|VgR^nba#gY&IL-pYzvpcXF%LKT`4=?e5sD#4Ws)m5S%9$}MCuhct+#DySGdvT* zVZ+SayqWn0m6=Z5|AqVEK_h?qjOnwT8NOh!uJN9aeGFIaNx<|qfdHwDYs)|Zac11-_PJY3x*)wM3 z=Vi~%ydl}u)$41VGb?8n%v|lA?V0V(o>?(tb%iI_Q#pH`e3+mG)*F#4q*-(m8Fh*^~VmEn5*Z3EEIxKE_9!jA*A;eN%A`(DyN=?(9j(|R>bmcm<#SW3%=>X8eZhw0JkyplNeW+H2r&7;KD5L%;ky=x&k4SrJSC)Vr+|icB++!tZ~>*H_A(DfQFcj$e*W|mE(wn%+UB+gJjruC&T`()xcxQ!UW-XLn6_j9F6gOX(`jp(O>YQP zd4itlm5uZj1|2uu{qW-1YpNS5OU%wKTS{LkTVd>vH0I2Xd=;mJu3*xxNs+nME?Li} zuc<@^uP5&KDkUxR2Nao|jW1j-#rana$V-+jULMSIyKAe~WoPGDm!k747cb9tBkS|w zYc;r*?+-T4uPiAcWC1OjD{%(VK$wyev(DwTo3t2T=^I2Fa?DKxou_2k!o|zo*)z(P z>)G$3KxIkxtdixvMdsHuAHbf~(uI|`LTt80?BGP^nk`*w?3ha0>K~k-S>^`7GGlkA zQ6|X`S&+7TmU|GL9hAU9OPh(C7?B+|N#h3D%SxZOa$RwFe@-HZIysoZoNa1;aUi(N z*xb8$VL7>ayTVhbkw!t^Oq0pHfkEJnj7a{F0t@QuObfYHB6DV7!iR;0oyQ;t!OOi) zSyKbP#IvNfWN?i6VaCQVr(xX#n|993raE{@Z)~Htc44~7`cTO~5v^qmlC?c#@MWUe_f%k}$PD{$%*=+Ev3G1xgX_`$fY z&6znL&UOTGdAT1>T=s0kA-yXlxT!xXc;ZvD;5D9#y7=qR2crJ}IEIu@6A7S>+G61{FKbC=C< zmu0(4kd-W-?OwKUd7&j=3fCua-9+7ap1L}GCym)W$(iAH)3@I@xUI)h*0G4lk&{N5wRpZYFDE)D3k$5rkFQ32sK8RhmuuL{+IkQb_To$FTh`T+j={x)QE;=5;Fu$L=N=nw3xudcXxklV> zx^{v`SKuqPgVxbN7CK9wZIklc*#&O>!A3^4`r&zlcmDExH>@_I>3pa}Hyg0zLEnXd zOJ-ML0oM@NRHFAA#zq5c>afsF8je_HxVM8c`b+OJvW8FQwj=0kcf>mm05-YbeU#(P;y2j{*1HyK(k zIYye+#-!&?&kygV?;~PH$DPI1AI`S=H-o5&ZSKv&t7K2lX4CbJTHGSTp6&GMi`)%x+3EPu=m-NqZM>jqb1H(%3@EYNOME&ZqGH(kr%mvjA8VcDo(G&4{C=85oR zBJq0$2tk9lqNue_|0}zG8aaTa-q?cg=Ignkb>K}`6Q#2LmxniB$H1$`eq_5JE?W`z zcn9WT`W%og7n4}AFzUiqG^6G6R+Pa(?EK}y{!61Tf=Sqgt7FkM3-`RF?AF*OPKZX_ zDX#QQ*AK7y-Q&BF-P7nfH|Qz`9%!@m#Scx#*A1t;-D@`Dxo0@53*fP*bZ3733`Uo? z=$bN{j(e!y>Gv;w@NV3*#zPpVdwukn5S)*F_#eF2fYI@!c|;r*=n8*|{$Ps++3kRd zAJ3YN`f-_19Ti%B%+t*9eJnidS6crOlaKCpS%1X(%TY+A=Jl8`>7vgXA6t^bDE))T z-vBJ}i~T?Kw+5enFUyOy~dr&TG|M@Q%Tq~{2_$>0b#NjXgqQU4K zfd5x<_^V8QX5LleV#NB#qg>YhDtdzteqJ^Hg#Q)!*TmtU@ub1R?`ClUBLDMo_!oW2 z;0SR>^RLKH_n>6$&;9b?_$%Y^PyC9(?;zopAF=)earme1HJCCiy!27ze=`pMB9q@Y z0RJf5ACmR|sL9XoH*qmy{ZuaFPx-pRLH7ZzKO+A>#o=H1w87Offd0DU@OOQ~;LjL< zKOc@y)_%t!ga3%N@%SvZe_I^><0gOA0Q~vOI_;16VA6ff%oBVYH@R!8l zXa8t04#fXR9R50!e<1t&P8|L>O@6u~Y5fuPk9S!~`~TLr46cFrSH$7(YBTuhE~WKH ztiLS||66!51O4dtD~*r(zasw!arjF+45oqj7a+dN#{a0vuiw+`r~a?T;eYwtgRB2P z_K(F2Sm|dV`^Wq1r2XGz@(-lH*W&Q^46=SF5=fc;tG{Ek zf1vtn;_$y|^6U3f4N>~PqW+$Z!++tQ3?`q2mp+R8@5kX^X*#}v_={8I{Xc2)PaB~A zmN@+9P5v1J@c$|f|HSVaj04p_dZ@hprGw;uI1Yc%OUKY|0rG@NI$8@pYXq; z{&I%N+uv#OFAZ}VA4Gn49R9ICFz5%e->q@@OHF?LPOPO3V*U3Hm$yH7++b=OK!2@q z_$U6*;Lo?zO&`Vjx85$Vzs%%cIzauW;_x5(kx}tL{l9>PH&uZ&D(dI8=M1oUfci`D zQW+Wl(w`XoT?6ocD-QpRlLr4l_IDu;f3e9wko`?U1+w<fyVC{lRw8G5C41ZMdRb1yTT~_18)xh`<%%yEHl{d|1$W-Mzcr0Ltx@F zMjP!H`P)o>=K%aq#^LWY`7ynsevs}({q)4)e{+!hpBW=>e`t{WFT~;RG5N*zim(a= z(^!c5V}CZfIgtKW$KfAq@;jrnW%&+>iT`CB{`^7KKWm)4{Yy>$fyVEvarnyzS^woY z{2NVvasN=%e>z_BM*3F;J%uh92)Ng%A3kq5@)L3Rdrf|^|04gxarl$oHEKY55%nYT zH=6vS{fssF#rnnmx5nYmF!=|vzh~p{y9UXBDo+1bn*6s%_1+jOE9%`i_16uu{*e>p z_S<6e*I6sWXHkFayOxe;uUR|=*!KGgVB(0{SoWO)kR#2U(ytu zj#tl24}2_pR(?Ldgg&bv+v%J&1OGU4X5b%Z_KX>Mxw%efUS2L9dqh9w$y-Yn-KQ!M zi3UKignz2dcx|7+)H7vATt;ysXRM`#S|O`VAM z_@%f`bm85DXEa9^MC|eJbDhZewED@kS!%rx@BV|Dc4sQA^$C2X@h-nFe?iiaoh~Kq z*J$1DJ=<7oI>S5N6_%Ru?~YHVm1y;)qXx%=VMw*gfLn}$y9M}o04;4%ST zD!_{bxKx0P1=uCPa|AeFfO7?Sh5%0!;0yttD!@(wo+!X$1vpiJhYN6u06PTOCcvV- zb2v1Gweojqp4LA{&kIh+=Lv_&Pn{iu_mktjp{FrVt?!EO!n@Vs-&*PY*9>z^|J~BO zbVtjs-DN9Rl^;A*)^Q z>wjy`#H07Jo;e0?7;W|jC*lbJyOsSEQ^9*X+l5izrA&NIWo^n{d^YgI*-3mpsif>s z*{cdf>Gd2Q#@OLujvd3<(P3~F!2L#LA%ymjT7E5qg|w8D8ElU&1E1frr8H;Y+xS!Q z`Bi($wL4jlo$x0UQVwUZ^9h7Ml9FOWB{nUb~Gx?;V!17o@|8p=Ef=o(y($IN`4iPuUIGx7XqG zkr64oGT5mR)Y4NUQ(7`u&q$(aOMNb3M9j8;;LiX-5J~HtwwC*F0*D~1tk2+4FHy|?`Uil4fG|&fd^$=QxFv{sSeENYwA**Cu{WaltyK5Y4AY!xjbxA&!r_w`}NIg z`}OUtH3RWJwV8a1g7<@~Srmsa<1^&~io?ibz!r|X^tnyX8Af#wt)4R=-$7oJE8-P1 z4`mwCv7OJ&#>fXxxexC;J7Wd1u`5Y1Lc`$2L@&L9%q@@@PUlZV01-Mgy@r<4*c_#(0j?Hcp8!`0aJc}l65y2rTqeLv1$dDFmkMyP z0J{WujsWKiaIOH)5a4M7oFTwd1=uOT69ssz0H+G@Z~;ycV21$P1egi%H7(j+djuG9 zKgymj2=I9U4hb-_rzn0TOHnY=rYQJL0X`+buL_@c&Pv{65vt+E*4;y0M8NNd;!iC;28ouO@K25c&Y$91$d$Wj}_ol0Uj>E zDFW;eV4DCl0lub2&zBwnz9hgG1o*rFV|5!f|K1VcE&+Z^fZr5g+*gj0_nH8|D!`or z{IUR_6kx35qvRhK;G+V3M1T(qaGL-h65xXZykCI#3NY3|QSI9;z`F#vMS!s%5yjsu zz*_`(qW}j5xK4np1=uIRRRUZtz^ep!r2v-+@KOO@B*3KtTr9vY0iGkk`2w6Pz%vAR zngC}A@KgbI3h+b$9xK490z6!RQv}!{z%~J90*q&|M%hP?0ACW|3j%yzfI|ZOjsSNF z@LK}>rU0K3;MWBBRRQi4VC?8b^$**0QSfsDd|ZH!3h)sDJ}kg(0(?k-4+`*p0me>K zRQvV_@NNOdc4QQNivaHs;AR2dBETC3I4Hn%0$eS?J^`*0;Bo<8CBQ2MxJ-bT3h*KU zE*0Qn0d@)S90AT3;9LQoA;8lFI75J^3b0dvCkpUb0mk6s|HyvRZ~;ycV21$P1egi% zHQ`L8M}RL0@C5-rFTmL6i)!yX0^B9QZwc_50(?q0j?Hcp8!`0 zaJc}l65y2rTqeLv1$dDFmkMyP0J{WujsWKiaIOH)5a4M7oFTwd1=uOT69ssz0H+G@ zZ~;ycV21$P1UTOQ;?16U(muQF%=7XDx|0xl=864f{48Z5cEmo-zEn+NWo(PR&Q_+b zWHao|_Lb@?HHb}%^DNiC!#*4*VjFD^+?w8HFIV&JyX|xATWnS81$K$K>^`;Gw!>Df z_OLo!`&-3=>K=Qs{ThydoNTXszrCDoRH1*R)PB&86C-<@y~Vc6wnbfJw<)`A4yB4M zwfpd-;u-9)z097XG^@jvJ+>X{O8Z`0F1{&KhXcS=B_Hn$7^|$Zm)ooC6P5k87Ih12 zX1mng>Kt~^=2Q;Z+H6ymJ?aiTtG|W$?0eN|%3+&}9kCU&qqbdaH=Cj4D*4KBTeW?^ zTFT}q2UVByoUK?nX)9G0u|sN`x`!=NmMUe+UiRVtd)ZcJ584l_E0rT^r)`x|t{h@* z>{Z)gc2wQVs+8mE5%!#VQhm*K%J#C_slI7@%XSpcD}TopUH5V3Gu!hV3)#-ws+CvO zldMj;V0)Q$;(L^rY(eEU^)-B>^i8$L_LjO)*`hQnJCsxGnvL0Qc89%1*`@4OQtWTy zXlt+1rM{!?R}Ly6^^nr099D+g&!au`-v#rp0Uc2;sj2p{_M^&i(}xVlkGRkvu(+74~3I#G41E!r+^s=8a-qwUr9QalMZ8wU=+36PL>sw?r<# z*j8#=WLs)0v#q>APPx3jY?ZCtR%P?qsu3XiyLU(T?MnB$PK?BzyB3w@UcwzbRX=l% zoX57%IjSA!sGEk=`~KAbIcho1y3%njy(5vOHb$L$jf}c`#?Ou;=U^i{Hh_mS0lmU{U0&9 zuaw|EBf))2f-95YmPl|5B)Ad@&LzQpT!PD!;IbvSX%gI>65JgU+$0HZtOPewg1b$E zOOoJh5?r5ohrsHG--L1(A_7&6-sb(B)HiUT#f{Hw*<%U4_VtcMM5`O zf*U8nrAlzaB)DV=&Mv|6`$N|DePG@xu;Q*raPLZR=Ows5N^oZ+xPO=6-jv|pkl=nP z!Tnr?f61o)<+$SZtMH1Zo5?ql4cdrD;?+;nqH&a44U4qM$ z;HFA&X%gIc32u}G$L|kW+c!i)mmt9@5*+p)Vq)1<3GO`!?oSe2NP>G?g8L5%?l%(L zDGBaZ65KB&xSvXJCndNaNpRnn;Jz!t9hTs}CBc0|g8O?3Zm$IQlmz!h3GQ(TZifW7 zRf2m&f@_lC`28WP{jHPGt(M?C65J{Y?jZ?onFRNM1Xn7-&6D6hA;A?$aQyy|wZ9*e z&}B(*ACchr{UNKo2@<-|65Q<)9KSzgm6s@?Qzf|T=3N3SZ;u3bQG)v~3GS=}_l^Yj zdkOBh65PK^aIZ;luSjq|li*&E;GUD_lHtD96z^yzt<=mb`w0Rr0(nH zT>@)gdL+1u65M}DaCmlUj1J$C;C?T`{Z@keR|)Pl3GNjM?q?F*3liLO65J0YxMwA} zXC$~b3GSN`+}9-cEtcTsOK|-DkX7DX3Ee#s+$;%hh6Hz)1ou%1E?t7-_lK{ig)iCBgkpg2R`rV|>Z$65Oj2+&@cj zc>Gh0ydO(&$0fM$NpRnh;Myg)LlWEp32vVR_azB#w*apf~%C^J|n?>N`m9}hpe`?L_)Vff-8~WToT;JCAd5ZE?a`*_lK>KR-b(OFYZH z;pZo?Wo(7L(!PRKCI0olfi-YGp(?S?9!+;U`y2LdLY2~Ff5d(T<%9cgbd<)+qaabj z2MH|E%lyh#`&w43Q0WA=!``TW5@~M@9AJ;zzleTrRGzXws%%s2iGM4tZI{xjB%?iF zwv-0hCcQU%?O#*=-hNQ|hW%Ui!;tk47Mc#_yY_!lzHc9v_*wQNdurmi#L0NaMkV}`y}`yOyvf{&x2b6f z|89=wNOi0_Nu8Q-hkB=)nJ`T~qvQXGyLs>GpRTa!F*VLi$WO>t^VE;4_a?a167>Vz zzbi_xEB7ZXP?xC5%A$l%Cag&Kn}jm;Q)+pFH({8vHX)FZs(eNrrvwu=B~+?Db+S^U zel}r>lA+wKY)@!VH>f$v7WFZ;CE@exPTafulDbcwt$ZQj$%L;Y>`yqL9#Y%YrxWHV z-%-D({$s*%^~dUq>OZT6xUY7f^6iAz)nBW>Q@hk73C9xtQ(dT>Q~#`9Qh%86e8N)Y zL8VvyZ&kxBvZ2}tZH)FXZi%I9AJy){4Y66;J=$EYDzR9bkADaLZ?U#qbK|bqr?m=g zjaIGIYwNYm+RF()Pxxg*v-U>9=d?Eyp3weIm$gUxs`l>*XP~{WYv07}uxGSqwI68D zX)kC$(_X=Suz%HltNk8#!Om*`rCr3`uj|?$6I5HGEyZTE<96F<+XS1__7Pi_?PIu| zRABprZ63->Z4cO%*&ed3vUzN)b=q~dI$M+N5!+UibBFD5+ZSz5+4kE0-o(WA>>IXk z*$&&jYx}Jtnwzq8|+n;Rj*{<5I*%W(%eTaRyeUyE?JsRsYhAR)*@H_`RyJ2$zo|mDtK7{8t zg!Jb(unxL!#Gm^$D*W89QQ_x)eLrgLJ6gCyWWdd!p_oK>V~lttr)zn!sGyB8r0vEt zEV?vze2UM+beEkC#WqVU3krY!hGfjo*QzSo&}a< zz!erb#2=>ru~B|fVMpW2G-(`yObmmb*QV>w3Nic3_YTbGmEk)}N5#71)?@OB^^gwe zj+hU9r?KUChVi&KJa^BuH!Xlrzkbo0&4sFYqa(rw+(Hyqph&h&57;T(Z;@c39rAM#!i%y%?@F` z4m@-1ES~v-GY~wpMCriyL3%Tw^NX4->oRQl3UK_{Z>Vn%&T{G(PNrwNvEB5{x@7vR zxUOg6cOic9IKka${ySu)}S|9sJ^RgnkZ--y1@0XzK)W>&p_}Ma~w_d%yV>;4Jx-M-D>~&lR z)k}2{FVPX+N`uD|hwTSOt$*&)#_BZ31UMqYC?5#^2k;y17>)TpGK=Wj5?sB|PjANU z6L%&jxlSyAO}X!8^}gP|vLQWv!*{J+o4+n8WoJ2__2+>8*bC*8nbSY{G@i#r?Q*1- zPyXEdePz@a>c=kB!P0$`?*op;0PEjYqQP?o@q8Xu_6P8RHkCQoPNwm3oLV=To-24q zVaq;Uzgf-8*rc|_)V8#-c*YK%f#cZXdg?56pQ$)@W_{P4@BWffUx-{e^96VQ++(c1 z95UxV!|I==XW3}s{Q|3}`Opp62j1k%>1Nx-T7(nrsXG{PRl=y zGU^A_7fN%TAp1amznknK&Cco@VG|1KqW4m;rYa8%< zp)s0r5=X=lyF3H?BD>50&tPm9@1{cCCktdU@YrB#S3$gX;YnOnenQ5Jao5Y@@sjSW zdMDkT)+XpqhLW(_v zzXHG4nNZY2-vQyzmo%RHC|{pZ%;Yh!zja*8YRpH(9;?6IrfOkdOLgB49k;A?^@c!a zeU?)*aC(e`kK}QVMSe%#)A{!|nA^{ppy8s27eWwY-A0CZmm+ zO7bhSuFrc4cQsq@y8h@J-8Od20o=Lnt zi;U+`)PKsYjJ!k*=TpbFS)WB@*hR}3myj39?WN@pI-Nf6(=o5P-L;&HgZ~6_0zA`< z{DhVMG2l6`SjKIPVz@PzYC%rni^_kDHZ}t<+E;YWW6)8aK=}lJ##jr+AJ1|*D%Rf& zyeO{)W7>(jMHw-?pc8qiKd_H1o*VHopS)y{Ar)2zJ7HI<vKEJ@R^0MfASGlpLunPs~7#%bHXmPgJkgE8@2J4J79N1 z6F-?Y4tWFWqPR{m{Rzplf@waaLwEdpdK~8aY#c_sOr^2nF#nz&hxzyPI7~6eN{_e{ z1#|l+yUsxVE!qLujc!ZuU*sRj&MD`%`cQ6DGJEHCMz+UojX6?=r;eS-M87$Z&ycOb zT3!_AJYP%6@sa)+bOWt7jCq4NX7;}YIjy6~SO<|FblsTiCWAJ-{`zFR^_NuUrv7Bc z&Rgz#`(9FCzZS3~&L<$=CnD}U5Q~zqZb-%&S8e?i)(aVURxHJ$yk^7a(mYMq{pRQn ztQE3CcN%lkvx0ntp%<Y{SluZobFW`^Xukbu03agP60(g?7U}cVAUmE1oB# z$MDn0+lj}s-GJ#c$vkc5lDma)Q$V`_u&#KXQ57d0%|0`MsfRJQp%s zn1{mi7r9>aKCCE`>*L{~6QOiTJ;2jkNK0q+@O|O=o{r~FUN`5RRld(c?;9FT@0ZYf zEbSrPlis<$#Xft!6KQ)q8sBFu?Hv|f|D&?{mqla_SihyMaqGAA-;o+!KNb?HzHRg6 zj3d6eDwO(Fx9*4B2Urw*avvQ`x(Z)@Oyv<5+tcbJ;4#_u~8l zJc~3uM_#&#{&>bm?7-SD+KbTV&15P!+D-ipiI0{vBlOy z<3MY9Ki+H>AyF^|aP4MZX{0yfHi% z#$w%@HjmY(|950BC9JR7IC=zL*CWmjZ%U7Oh)WtfdQ4+^A@qTA(7vr|d*3kD+qVRt zM=Bfpo?<&`2e8lxq#P|CV=kLRMzN8&-KfG_*pFCEsVF2Lf_Gf#`v{q6J7B#nj^V7A_6qv8Q+{DXy>`@}fOaIJJr3j- z$T8-r`g5A~JxS!=v>!ovJmvjcKg-(jj!HfM->NF@1nc_(Uo7nTMY8Ke(zpfhy?{L| zH|G6g_`CDPqMmcwU0LpXUGJU7zS6EN*NG>_-9Ey7`u=(k;I;SGJ^81(!*krq(C%c` zJmNHTv#WrO_*38G%MK_**U|pRu8+D-9DqCppP#^563%GW6C(->*3w_B85itjxx~8@ zva2Ec0Av>;kHLNTW7H0ePub&W$N9M|C+l9G>N9M|_g<7vwMpS;s5k%Q*6FkpYo)ZL1wvgB`=)a8KRhlu zPOpC>9Gei2!m$atO;bPis@F60{`b1f{pfV8ZD7;kK2f>j-A!*GCcK_@dvr{gwaM2* zu{H9%dik7a!CF2Ib2YBsP=3qC34S4_E{k7iM)@tP3%)C4$wjPsqy0ENj^YfV)67R4 zlUz?x4l!uGkzXHH{%q3F@+Zj;CS@1uq@Bmg(1+a~)~3Rz=P6GuFORoj+;ZjfI=9CAhV(=yNh&#jy1 zEvQfTE16@X>idSpj}Z-<@3?io6LA+d8P1{43`vXF4&t)4><-o9!+Bdr4Q+_Fy@+n8 zt!Lps9M_k>;Y{xwf6HtE@1L-?E6N7m6UwY@E`mQ$oYB6=7U@$n%5Pa4k=I1E(ei!` z9`~(2q7%L~#NN!~W!5~zC>#ELUS=I5qpT~;XN`GAStwj)jrm5|g>acQJ{x6Y`>D?v zF570&ufdlQF0+n{Q8pt|X3>XHmLD#Q?Yk>n7Tbr?NLgaUb`6SDJ`A%)>WGu{IVQFueK02Q`;TVOS+%M!3pBiK?LHS6% zt5<(U9@c|baG&Gk5Ue$kt5Y5_8o#ubro9!qi}5~w>0LU%#xJd>C*WL!_L3-Xc^K>C z{qt~M@=@eccB~z-j?B8-)xH*IdJC=>zu|rg^9OMwZ)`7JN)~lKREyuHz z@mXu}ejTiVa{0XGYjTq5fJ|E3GSE`{tZNBcM{Lq)pJ^PHTGsdH7%;6P9BO18LHc)m z68rMk`f|^h_QKx{^h=yGoiX#!)8@X_Z_yWSbA12!Wu4B*?X2x&w;Mk2M%wo#WVO&( zJQEp<_i?t4mxboZ#+{GPRp^oSH^yNcXk2IqSRuk4Iw_!+MAH_(4sKTC(X3b3Epa57FlP38PON^NFdsON+?V*fP}o#REj!^u(u(TiSiSyAYnPpNjjsA_7TQ9 zOV`We5xq1gu{`WI^p++?&LX*AB7Q2Pc|~VI&51ZGM!UJs6n)l7CrFx@p)yHq3`{TGwQ_W zg5*Q4h@4T)QF7qtvxrysCEKtUXZnw{F^_k@jeBP@9fxq9rr!lL&$QDqXRmLbk3G6l z?A6_mJ-hp`cUOWv!{T=A<>`BdYd4iY*{$zo4bk_~9$V8_wi7w?E8p$QE%=}hp@;3k z>zPw=Co2^(C^a3wh)J|YPNnl_`ku!K{N9dVI)A1+Pjo&{{+-V9u(zCwHGL}9_Nfm1 zaymL6=5)9-pwp2bqw`3_=kR_Lw=eRmM2CK-5)H>+9X7G&%0mkJi1*%Y)^I-(x^j{n zN5|X(<8E6>Ki8iJnj+|-u$>)LTCXM+)1GbW+y{*HYzEe{wEsZ9E7#lyK>zf6Xx9Bp zI#VdWjT!M8x}iG@6q(;l6@zG|O)??<%w*7L3vFDn$0ULzqiV+gQ6# zWw@uw{W-l`*q94j*UrknzB$rnYA@}<@_xU+=0_M$1^rRcFZ6pe-bJS=tz=hp$A)Cm z`~F&B*P~&lKgXP>GgAMfTU$v6wvnx72y{rNq*%jAHZjNYwpxDjI<+57gT zeVVsiSw&9N~8}{3_NwXhS>dOWKsS+^;h1ML2fC08{aN zwqE*7GH9QCEOc3Z8=bcscM^Ni*Y6|NQSL!`z!@`VaB9(YI5gL@r0)!E{LV-Iz-aCj zkUp<(E`|>0L6=3)X(8swPxZS@T-Vn(KM&pN`3}CyX5>BAyTP>2-Gw_YG*?LP{5}uO zQP?c*8M%6k@XO^H^oHN$&qlsDY;q5O?;*(`S(q>SSpxN$+D-R~FD4f0c0l)VF5gA( zAdK7#rgspM-M5W4_TJmJPtwmN`nGHBeSK|X&d=$75UrUAPyWR*X)N}@C)TGUXOgwy_m*6ScqxY`-mdL0&Ix^Mp00~N zoJ*9e&G-5~sxBItYM z^Ub^1XLmfYarc*dhfU~_`Rja)H{Hjf_(5|w&7-uZJ<8w)^|@5=c!H}p8UCB{jfaqP zg;cgPt&n|p8*HCqQQD{2yPb$RorpO-@MVrMEdR@hJNi6<-x#OI9lASgti!Ou-H`!5 zxZaFChTo)e^2J8pleR7|AG#=bocuIoo`FxL`qM}4*(dtS-oz3;j&k3Y7E<(cR)_Ap zVE4Z%*Zmdxqt6G5VdC962Ye&>MC>Q)`B>TkMTh*~lTZR;BVn+!1;LYu7B59s4M3f@lfufR63}OgVoN))ha; z{-Fc8|I9}n6ZCT2p{2ZMB=T>9&*47YLdXnZy+&)cbFlj%kU@D)HLaiRxYzIZ9VcJ? z#G}a*x)G16XSv!BD=Dw+!rE)@3)8w^!MQcX;Pc=ocp>2BkB*!G-DUB+ar|B!-NP2Y zqr~4aOEHDtCng_1CB=23i0pqmd=2(8NDt(9NOz~v-z)fR;BfAT^W|TddAxBi#JmeR z#XRRjInkbmEIy{;c?4UavM7Ivak74w#(Ez*1ep}ed~|+j%H=Zq=Bcmuxb29!35dP; zUdv{jBWr5wO2n{aI``J^kUBa#wok<4JzTvQ_oHXAf53CHkY@Cc+Jp6ze#XP&F88S+ zoX2+!F??zW{+|2POpF0@G-IFI=uZh?C*~o=$UeG{3fc_hQJu&|GT@(`@XuTp*+j0* z)q9`_a}fE_ER-MkjCofTI-|R)d30BGJ1anN((Qxps#5;P_b5WpKh51s+tqeD=Qr*? zL~^0uBALCMt)BPB)`;a5y&H>K*`S%C-n3Da`cvydBxfA6Z{oOMd zsGRCGa$%NpGk%GoKZ)Kpi%3102S64ZM0q1IeLu1eYnWw5My4+tYP&77G1RFe+ z!2!r>nyQ2Ty6Q~>k$Hj*{*6we9)NPaw=x)La5h$Ys)a7ZG_l4IIvCO_|9XGbfbs$Z zDa8YQMyWNXP1JO&-eU;78!M}u8vPib0ZFU9tD!BQpZ@JvW`lo?Z*Y`V{s!pR>94Kw zZe;k^3f|+ig3i^{zF61y8{g@tTY1VLB6NK>ny2n@>GYR z#etxJS>$bObe8!%wPBk38@!&Nw;>uCCZhp~mT9Grlo~Xs&-h?y=5E~zO*P#e^w)SB z?>3ZV>dM3!)Es9p8FY8^sl=)SYy2>O>MQ@a(ejzJn`2|I6OHfJb#)>7uo}CD<*scnS~?TP?6-Nj!{%5RzjLEeT;s=4B-O zp0rvI=te@4C4rHNgD_4;Ad-V@k`VC3*yB4#lARpe2PY`klVCe1M-DzS_TZDxb58D9 z;M}<_8YjlaM$IFA|5dg3?%KP%kw}<0XTI$3>+W5TwQAL>RjaC2t*VZNjN&D1k-9`T zlqJo;7KyhsmPB(jHfy4RPD-%gLqSx%82mJ+7^uwA=4$GgwBlmHP?CwC5q`z>7?(DZxalDa9zj6f2P$iKn;NB~S|Hb@J3n&_oF_qN8ga zDJ8m@1u9Fu4HPjN+nQ#oy*1Gw&zd0dz?5WVLsVk?;!Ny_f{Rxm&lsD`SWF>?7`V+~ zloSud(zqOh#@px$X$jHTfyG)4${UksdO~dU(Y(_0O9hC^P(pN#Eola=k$6j$O$jEV zOewJu#U#pF?Fb%9iBp8B;${e`5XzOGC+06L%?Q-ff>kVCv~Yx9n2@)6>-^rPHda@^ zskOeojkWok>al|6KkeS8O|+2mw${3M1iff!^s1-(I$9Qq4E#;Y!Qb^Pls%Ho2ua9H z+3UBr(9#p@?v`A7$z^R1x3*(Vj+Ggf^gK|cEkU)lVWodl6ILwvwz$SUfU+TNBpie$;Fu<6?rfWLs5pIch8gH-LvIxLqWo0B<`Z zCd*;b8U{F;LyjQ~h~nQO&kDZi;%M^oOi{exoO}Znw5KVGa3PL=i%gs%L=jCopdQ!a zt!=1mYHr=am)BdH%wY;`u%t%9lv?I(+$ez>K}tiB^s^+F|Db*XJ;LIJNa6(+uyx4C z$;jJYz&1pvpdh93LL+HLkkSOJa<>DofRrMr{PL!Do+!%FLzF_Sl9G&|0cB9gp|tvl zY(|n1)S&XnPGOYALwZ?K5X8)5Uqpf)x4opxkXrhx8j= z3VjAzprskOyiFa<+t`R+-|FpfX*8B@@wZpD!+f>n9@s`;yDM#~6XA8Oex$*k$coyV zxA<#I(CvUeVumqAM@%lJXaroMBb7w~p2L+gJMQ8|&5s5pfP-PBGgEYviiRV*a}tzqM44RrOGhO`9I5 zZ*6W9F;%Tzu0}*uQ!^}#tOo3Y`3c;qTS+$V@}_OgwO+1cz)U&R*cb`55tpT)u;#&v zxe1!9rL>W3QF^Ed?P0v5eT?_UMl)D(D=Jy*ZHs^!F`P65vRKfpBLW@74oj>ELeG?L z=eBqYG!g{wbSxr2nqF9#xT?V`t4`nGP|2urXfd>{0`C2B*9 zHD(2jj7D6MupM)*uihHr^J;%2&uZ`XNPdhedI@VIg~HNCxw$ zgcW}8CT^wHA=Y`3lN7_6dyLFR9A`!B1h6Acf;kcDGa>T7{BuBi;MsmcftdS#bWsMy1 zDr;mAm91^`w_p~G@z0N)8%(xy7PHn`=uBfX2fJNu^;PxTG4igjZ^J$&<_%l?P14wf z{iN-3&|6n02hEw+G&gN%@?(2%iv>(dFe8u>%&3fZtE|OT-b{o!&5Y2Tb`_j*$)+lr zFi5$sQjV0%T%yq+F=}B>Gh;WWT?MCHvZ)p(3{tMElq2QZQd3K7C2Z``e%oqqTf@rw z_F7-j>J>($5mCFfrhcWjw!WP2{OX|+EZ6vG+Tv|%`Y_*cWBV-&rLMDNbNHlD<&_H1myoClp3k!W2Q~SSfS){xQ@4Urj1dZNyNx_ zM2rbjPQIm{$U`xvn(A@UkmlNoe3lZ41Ev~_T;@9KanZ1HnL+`P`&DFogLhR8EK>03 z6DFI5ZQRDft<0LjGRA5XSaSND`Liq7_f?A^76x8zPf%(b8AP;klAWw%2*70gcZ1)3{z%&l|J~6)v-It z$YX-%_M^zGnY9Vuwnz+&^HEVW=>oP#S}}Kzm2jYpXw4Qu5l38{6vJ^#ndU zHwDb;gv1;JROSfEBH`D9<~(;|lSway-p#25BInS<=3IAr+kNO=n$i)WSUE(TVIeNz zDn)}5X{IPDI4UAmK3=?3Q9(fzJ1o)Yvijngd$F2A8u_L;D#03I%~#(j+RezPMOgDu ziJY-UMm;8GPQhSvULF@ew@A?|Sx!BP%dH8CV6Q1kz{N<2G>0iaMMq%F3^F(#Cptd$ zM&m_QfLcNHEaIcTVY^=LB5`Q(E8;-jlX>(ZEoo1dOcj;)CLnJ+lWQ)##X+!3ioRmedOICv6o_w z(|BjfrwyFgHO1yFIq))UPM8L=d;RS`KDkNt{WgDXy(vSiI5W__&8-c>Aa5Fq zV@I1obyKT8eCuH|1ur>%ASw0|Q$v<|$-%@WLk-F??8GhrP`DI%Ads0}A-rhV4=+%iF=X zy~<&`^YcB#()+56*eV^r9C>Gb6V1a+w8-h0>EWQp7MWBz8QQtFzP?V5y0hL?+bY;+ zEXk-}6^790*p-dmO>LHFx#X&=q(P|poUjD@2+g1uB0YxORue}eig3N1Ip{>M= z>eSIra8Ysb+7>U2V^_&7Y-MP;75s<>qBV!t&$COthSuq+LNrmAKR za20ZRdR4Q?PWfn1g5yfm3WQIdVkJPSVg?wUf{w?^+sf)2v6hjh+bim8wr;}m!r#=s zk((yHo8V2eiEjaufwHQe4nFCp7F=iu9H`+7l-pcQ%{XEMg;DEot=;NxXScb~DcYgk z@wS3mRSThCibD@c7!X_^)o5m~IKbv6oOkx|ojc}0>$$Z&{ZT{Pm*e&c9I#K~+ zDEQ!d1Ug!x2qx5a7baI&Y}JW#S}1)(Q)@H!odp?@Kz$31JWaJ7E`drSY)!KZ4md3l z#9C>^&2=3(%Auv!@DL|M(@-$lZf|MDaT$nN5-Wx)LapyM*IlsY8i8W$t~VGVl-cfY z!if+)@A`VoZJHR>8rInr7&Wk$QCGjwivwSX(6epO4w#5A6KudxXq1f=7A)ATHo|N{ ztDs=r#)ai98U#787g*osy2FKpmaXk17Q#V-qA0n3y9=|M zTBsI^LD$Bj3P&)YU$90+3{Gbui92g)Nd1OG0mqAlokuPQtJ|o8HZ^+S=(LF&*j+7t z?A^FXkDvqy3gonYQ+;a^Gv&etCps^sZ*75m!}Vihdy+;?y|=Zo!=sz}JtQfxqwAEm zwR`I7TiSh|TAcf%b3S^K$iaveD7vw^wn0==t2&$Ide$lR;8osXA0!9u>0US2Nkir|c_0d*{M=uF-M1vF} z>X5BvYa6jhM1cT~*b}jqM8$Y?I%rFz-3ODwCLe0Yt9g&V{t=pJtgnZHAom+BzLKBR z!?0n^ASQDlqm7SlVno9n0@QEwk`T5tC?o1wx`P~-816CT61ErycS^XwAsghQt%YVc zRItZ`F4X9+^^18x3vB?okV6PN6@h@!&RTdI=%?3qSTJ~$mpYzHSd*yTu-pSHnX8UZ zAR}S)yRGQhTl|e3k;q5%31cKmpTJqG>MxOGdDXNz|;tP5BZXm2PU4l(U@ zIeCk@R~{@wXlyb!Au?~tVn*lvynxtL<6V-wk^ko8)2|5e_ne%Ko=x;sld~8}JVj)x z@xu8HusMr8-dqk`fNvg$7y6|zmYNrH>o zKMUH7EQ;_06ua1>BO{g~p;GVRO1`{~-t{S^2;qbxcmJT2b>yAP{nZdC!6v)_qa=Mg z2lXU^nj$yA#J(x1lWS;LW8T_Y^k*_~H#b%4X@dWJg~q3=`W`kUM;vtJ zd)aKw)-9N_Ht;ob8#7+HY#5>P6_{?Jy&}_2#N5f{)D&gSL}MP6P^mcMA3ZujqNL3=)iqjUa~Sh!nBO1AHC{{Y(=a05%gQ5(?)u%)LrRyg}yyef*H6GSi}8# znT8oligtfhJv??X(Ob++!5nii*Bo484(6GIOU=Q2b8s2l-7%sIEl~_hf_USR#!MlS zYKhXxWhGF_f_5wXb64Y!Pmg>@5ZoBETBm-Eri-ukqhry+K`C^ z%bQ@7V8!II51m)syqzZrEhnh6P)2KA^5hp2Tr?5-q{uEJNh#7BDK_!KRU<`JVr^CH zZ(Lu$kqMg@npnIT4K0Es)a6YqYPCmea$eS&=5;g;!ivuvVK`b_69nE!{z|^XWerDz zi+on-br81ISadXUmJ4B=xZ6kM2WTYsX`H(6=FhW-wz}C@P1+lBVaL@6TQ-1Mk1?AWM|t z1$vVk9fVNS$YJC%Vq#{ig1JrxtHJ^X;WB@FmH4>}6MwwHISj7wO`Bl! z;1(_eMzdWY%*oMh6bMH|MSd3ohU6+V5N|cS8(l6c0_{%S40&X&6ln`tJw;-9w~Yi> z*SGnoDRu06ID-6MZ)*!RRpn}wRJmHuNYUjhcohH92f3Q9{>Ju&SXuIA24)*r(>;QH z-ugQKR?M}0xICoA7!k1)uf>rZtmqH0NAt6X{nSwDomLz|@W zVfyAeSLV%aSy~hn0}b&vZWr(IRVM&Z2qcYgV%P+AsfE!EWBjZeF-3X9-pxsA>*d%x=564#pQY7e)h``!fW& zQJ{_C921l&|Mqz6HbWP}9K*wWX4YaD6|fJcnHSomjC!1w8H}#O>h^~Ev)#4+p0d$f?yuliV6;`Vj!jTO+a7G3L>f^MhjDs0C zX#zYjJz!Dm!M*~&*2favhRZx)88hc4y@EBdCAQAn+7Oi$%X%M~*31ZMX%1c2T!*dg z7zs6GSTe_BO;yKHS>oH8H@3%$uZ!H0Vn$RijzZutnmOLr*68s;wxeS;uUvGH7>T?h zG2*dU#Nq@?4=a-}{r6CN)2y{k?}Ln+i(tdhOg0{FnL-m;1$<<-}0tXs0QW@CQdlDgbwbv3o#oSK^4+=9ZT%N8##$j@1pbxpV% z8@Fw7Eva2nxMXAfGVikboFz4jH`aLbytT`gdKc$-z4--8>Xvzz*5u^W)&aFqy;ZC3 zSuN_)wyg3dTSr5>LCbXsEBtiYWi|EmDt%yn&^yDE=HTX-{#oaQg4l^2>3JTAcR7^L56EJD|nsbWs_-G2&i}5%*4vxZlKx8;KF;#2?qt zqnFDTwc!v*YrD6GEh0y5@x93Nz?x;78rx{R$;q$6egd`zaXAMKJ@u_QIon`F#2r0! zM6`5Gr6<4Y9*QVkhxeQ%Rpn&c*rFw~ML1A`eS+(Xa#L+Byduad-~r{Zd2-t2B39+( z=~UO#>FV~<^@Sj8V{;`=tFF5%Cr6`l4NUz02>4w_t(R&U*0#{TV{>cHvQ72a1feTY z+Hs-*-e{Xjw?zOAxM*%I=G@v4lUcc1DI#@@yt)>I)TT0DVzg!+r>{tJs;iG`(0q-? zNRBbm`G+7LGrg7E#SccIxb#MHjH#IlI2%ed2O^xI2Wk@N+{Ie`%}E9iYTMciq6=7+ zQz+!m3}q5R>MgnekY8_I>H51UF29NcaT54mJXJA9!{wG@yT8>d$|;2uNB6WZgp4t? zq0k_e9b0Oe8_jA%i;Lzc7$6i&L=WY`O8HuU+@D(YdQC~<4<0;qg6 zuD_OGqji2|d%nlhRM(J`lZ(}i;kZ*?OWidGORiQAx+ku^E3Yjrjf|&xEm)Aj`4FBh zG_X)&X}%Xup-pwA>+Y)E65;4wMhUq&9*KZCRg+U%n!DKJA^*ikJhCNS zWfQy4dC^VhB;*^+L4tS`o#W9$uY4y0ZNP z<{ljJihCE~Ov@sVXVZ2Z?}0sru0VwEiDw(ck7k8*tYZ;QoYgP7bIpc@aOZ>n^rCtn z9WTN?6@To5|3hYEn#2E7njW_)6bWc1C?f*@pL|t#vgONP;wRBsw zoNu?VK8REPv0DTL?QzJDwfuY_r21R&wyYFT zKOLp~|D?fN`M-FTfTw*E`LUM&Z*kxsS|gzDlY#MWg})8#@{+4?M5bYnykG1^Oap1RW4bS(KBm`FY z?`!Z@{vW?z0F9Sm>D59GI~S+?K@FboSxGpo`F=sa?$=@u@6Jpk1gLlb= z<;!@HdSS{&#WU7mN|!jXx|W`sq)?FsYk7@8${m1@E^UJbUNA3aF2PUw*9RH_~-MZHsDKS{60m>T2+ygj?1-lF}_^6i}B^kS-dzuFVE##mcO`w!Y)^J($3OVD{V>yqr!e{j4N`P z+owfBZvN_K8O+7bul;G?l^sgol@iwTsh#x?*=_yj@j;dYm}up9+1#NaduqS>x;w;_ z<-byyJEZ1_cU1c5)zW$10g=~tn|mOgsSRF*RR!!U*Ed%wG+-4Cw~AkO{0?6(3sq0= zyyMD_qP`*IJ-_yi-s5)9uf|O4KWO;k(HbNDdeeHj`6qoBHz|E19$Vk%_uBi;uT21- z6TxStr|ckjk-{D>a=l1me z?-eUO7r__Sv2DcE9u9W27wu(@m+RK0wZpUHS(OiY56`9co!YOyC3xn$#oc!SGZf`hT#c8-9(k`d$)3epT72z2P?ofcs*^GX5p_T`6>NNM0>4of^i)1EV`W@_C z5z-Gqo~S;&E*5#pOlBdMz4MOVFS+}$*6-2z`oSAn!Qf}%sw+E6(LO8CP9Lg}n;Pqq+_wKBGwKQJ-~(&_?^AgZ6{(`->Utsl^A= zPryy(aC%uf{=h_csEo0rfvGG+b?Dpu&`7%C2%bXwUD;8AdX|G9WqlXE><*#+J=Fh5 zCtM8=rH8}HB<`r)sjS#%V?S4Xj3I6UYiF!|#bt#ZQ|ge9eKzrik@IVzcXrsoOV*Q# zelTs0J0x_F(yu~q5I?ETecy7A^eLd#KCM6d2KRtRVGU>g^E0#5m-igXx_|SCKOBBF zU6~f_1nmx_r!z+brrgjo)B624xvH{<;&$kbG2gm^!c zF3FTEPvcpr3-ZEcX9hj=g(hL?N+WU6@HJ7E=xh$2Ver1rQJNr=I z*m7jSL3M#iVZZ7`+kux^=o1KYc~vK|5b;j`=)8>gI~pD<+=%Bj(5irD$mI@u-<3DT zxcCTU@WpDbrJ;K;h$`iQdnOW)f=|Pt9%me9+Jsg0H zA9&@vhb}ze8(DTG{OU8dsliUjUjVwmTFxUVCv2M@Je~U;s6uvhuU5_w$|=&ysm9TO zPByZPbn^$c8A0fYDyj$RmMc3-Q0HRQy$Cw+=UnfN#=Ftdb>8BN4BXyN{{z79ibN0> zBI5Eyx?ideml$C7qn$^`jgd{p9Qezbu4VF>E-bzH6Ym_> ziF2QYa&JQZ1WcajaZ-M3UB8R- zOo*nBzK`p|J3SQV)?i%}fhQH8DlJYggC~rBriIReXo@n*lWdH~TB3aXV&eRx-27r< zye=+zORDgPYi;#7XF%1+%{7J%@^+^Sg-d+(wG9@BdjERzip{MO{+aydZn$`jeikQ( z&eC9bv2yy_{5+$O{ChB>pjJEo!3mDsn;eTBF&rpkHJI5UU3dS9ahl=!oQe4NaDEk> zj<}9qALr8lNM4{(%D^hE*C+*Fu%mIrbsQ%gaDQ`sIq&)KBKJ0Kt@qHynj%I%lkf+* z?&E~jQqM9?rQje0l~d@!jk_&cS>#ubOLogE3p|y@9wg_{1y>X-E#;>l0Fv)1M;f5> z@K=*{A`Lm|&;$`LZiV*XPn`HkKFZ5aD(cDf50^Z0TWM)yDID>uVw@F-?y%S0`~445 zXk&Iij-{F`4!UN4Wvc{VHFK0(wx0V7c30%n0c@FaJ1tyKOpn_XiUjoelpaGSWty(U zgXi;7Ju`l-@bz)v&uTEE!T&f8{6THb#pk^mF8Z;SKN@mY`p5HmbdRz8GjYl<8zX#S9G}5;8a!W1 zU4{M?kds*adq`_|mjp|%*7`TbfhS)sdR+WF@@0iT5C{Hg4SqEF3u^FIpO5D?!174Z z{Eg~LkN$g6gV)rZNW}NY8obYl5ieGH=7Z0K%L;!VjB@mh27g~1_~T=Q|3)16%p_61 zm0oMOSA$2(brYRvSwHF(mm@?)hx7Vjy4 zujcG>0{G>}TK=s$%a*yMXS6-voW)C)Hp^m4uI_mFweJDL1uCj#U0fCS8 zr(<9D#5h*fHLiGo-h+19;}vZocs|X-LlN#YwL$DWdYy_>jD0Dr$1qINLzYTz5$4)o-vztn(^tx4(P2c^vj%$72sd#a@I1 zdlJ}d-I0ua7+X&n?YCmD2>ZgJOK219ful{7{=luY@8upS#|Qg-4M)Jo(dzHE%W@o> zN2B2=OBS+RmTVg+TjmZ8Ca|OBmF@u_KFc%M!^1PMpM&2s_+73fH4G*E>FI(xO7+cm zhdlP#!Ls=*~1NnfY?p ztg?IAKs(?_PB2HQx(8|Z0>}5z{--}=Js)D9YzX^b*w^p>jeRDUIkZWr3wvH&<7j`M zy*dl!jG)Z|c16o8@&*2;q;L6GSzo5gLW&*xiL_UVeLo-VPunOC^e)GqDrhY$L0Tf~ zDJ#LACh+zm&w0DrPx%M259~x4Vt=e?BpY!aB{k@Ve}Dt;0lT9=HKk}|FYtS4KNx-q zRG(9!a24hUsppYSVK2hI2O&@M@5)-Ps10h)o>^rNvH_om_MQ=bdGD+;55l#SXO+nF zGV;_SZWH1l7e>BKY+y6OWfO}BvXrD`>gVNu?!uUYrAul6 zWvl+Sg21IPr(+Mw_i40bD(T0lj$I8)3idR#AM@cuI)&y-)OS1aD{x2CNA(+xM$(G} zpMf<*q<+zKlJ4kg$UD{sU%Z{)SI-@o!g`d?!&T&O)%A<=LcJ|~ziT#m!h_;5`X> z@41;35==#w6qm&c&p_TtJ`Oy`dMe6`LKTX7qT)))Qx%WRIlR-B6r4Ar$;;ysZy!%8 z?D~cj{szK(rSRUQ!teYDx~F(*PXNAZ-+><`d{ncy{m91GvQw?0_4SvB#7x{(#V+QA!cu(W+K5f17skC0f(HpE+rox|3 zU$0CJLJp1f%2dQ}23`7kg>>hqSf>!rz3^Q=kA6r#%^%EyAM~eT_@=r;kH1nB+Wn)V zkQblo$5Xg2?mE3XqJvJS6n6ca6#h4aS4ui_!ERHB=`!z ze=enej`Y?wk@8z76n1Ts!rKsjR0=;jp)fEW{Kh(e_*QoaV`uPL@Z`#lyI>EffL)** z_JK0k3GVE>+`O_6b_4EL>f0uCbJ@x8(!;+G)2$N+!fz(RrZ5?KrvPRuU{ir(8f*&F z;dh+a^B`;rKD6IOJM0T3EL4_d8Rl>BZP-mCFm_B{0Y-xm+S$D7+5XwBsNd(81( zLi{UY4dr{qHbCoLbtYs+KPT}I;(ah5e(9KF&>D0IZJ&iaE=wLC<$-PEYI)QI;M?U9 zKL2sbq4o72gX1#zK>g&vJk}GwlX3Y!5564OjrILbN1q3Jlla>8chJpP$Gdmh`vR3L zp00#<9s~faA=U8TSt!hVOG=2OBsJKJs>O zK#zZjc?jn-e2D?WecvhHeCQUkEx>N{VYj*8ldhWv+g@7#hngMZUv4W7y?=Ug z&vJVjw|%tZed`;OdzOJGr{9F_1H2I9L@I0_Vm?PSV7%_{LOGd`Q}VO(L(z z7Z@M0eY~#eDWcT}xL$-`N8hjht76V`UvV+lLB3*Jh;a5IPe{@w!uBy!(j_xZwvU;l zW1!P?T|)KIZ66`%6bh5=qi7lVvfFy9(T2qLqFX?NO?yXQsfNvm;!oX4@@(Vpq?dg8 zm`5YMyhQZb4Blt&L4VtTepiM5SBZYO9)0%iKJ?2dUvTPkavSwRw^AF?yq3~-J^q!E z1CO(JNvBfz&)8GB4F`UBv?k|yh<2P`f?YB~d#6M@*(^;=vJzK%x zcy`d92Wuk+n&-!}BMCR*eJH_w7VnAs#I8&D=^W)Iwt_C=eqUh^sb>|XCE>iHv_DNV zEn5Q4a2&KHJTD*5Vklz{gD~Kub~@NQHrj~#jjCQ&*;(~IepX^O-5ar89kQ{Pl!RZ~ z*!xP}Z)|LzZ6B}_djY=}I{?ZiZzD)Ms6r%LKsm`uUHZqm+ z^rpTx?ujgRc6Mf07JF%q^L>;*=OMhmbA$73lzhWYNDbVmc4o1C>CPckCw&s$htgkC zknmE5^EE_eWa9n6T<0;AGq(!w&(Cv?+`^8}qxitQNrT|aP3q54+D$&hym#}QUxT`v z)ps)4(_d2GLv6lPhM0Y~q&@+9Z#hrRLhbUI!f%Ry(e6CIfW2)`7+k(K9+LwebpXwZ0z>cTBj~&>9vnCx}zL<4QO`pPh9%Kc3Gu6ajLZf~ag_5$`&=G%N*6?LEayrSZ|s(tpCl!N$5R3X*} z65j&~;?2`{D7Ug>kiBEJ%=c5+(+TRYQ&_;UPkAqeoll~_6L={_eJ4dZmZH9$q8v}j zi|mtfcsf%AamU9A(SBRGo%4G#8${foqIOMS?+Zu%EUzgqp~sy~cxeB4HkjB+6pmBz{?0fIIULu` zteUZE_vJ)(M4`VgIGT_*lE?xHZtyix#p_FnpaT!eorIb(e4IyY?AJ;)j}!er0Wz{( zc$pv{|8tNz>h0{N1w7AOPR}tLj^7=zryd;7j@nZ}+*$h(JEHcDCpTrnZ-#q1OM#fE zZzn3xE7Y_fCnlUvgs>(&F;2Oh2nK@|?E&m;?y$X2QK9?}C~l}th4kS2N*eO;baDnd zsHg!2HAVUme+}sAlhG&;F`IhUj=!tWWaZ+f{~P0kg7LzJaRcXXcHrD3<{7mA=3(~W z5Ns%XA1=9b{pUD$hxrB{3ut^uPf$iq6$|}-5p!+KV{$!oo(B6`7ig~zFd*#!&5@X! z^%RweyzqGm&9Jl30~k{a$HTURv7g{}{XR^t+}N|2+TVq7cxocXH;l>nkBm?%=4!o3 zG}hqkq%yO+H;G{^q;oVYKz9k~FGf9zFy8$)ewId@@zmE-V*H}@J>maUJ5PBYWzZf9 z(Rcy4Fd)&@a0dvMey9FE{OUQZP3S#rw_#pu1AaToNkDmtD0dwAH6D9qO3!9yJMlU3 zOkwA?xLDQH=iPmQPnB1E8@~Mst)m}$Og)^fOx4!Z>fwvvR0|**25I+_&M>ClwDTAND9|!LoE#m8Hz2v#L*JJ(hep_$hnkZRG3j z-}}iv#J$iz^vQB1IrtRH#GIunGqe-urjmm9<#Zi7HisQm$ES6(bC1z!^#ioFY_q9{ ze`cE%q&A~@GfQMu;oq~qu$Uhe4l=fkcz?up{Eh(e-PU;rtrG{(=F3ai%f+);)lZPV z+{4bjLFMg8ue=1l`ev|#`?0>GJ+Vx*{hW`!`s5JSlvHk)-TlfX@HzB2>%%CCc9@NM z;4I7oh0X0E)>S(j3JYGXVLcxEwBQB&dM|}Je`x)-9P)zBUNsEcUN+|Fu3i6nd(y7- z5w`35w=aKedEfF~H;!a^*}Kc_j-ZO)Q;@B_pqK0@LDbo!ObKo zzoDUT?7IB})cu2RDCic`gBjSf`VQc}jdtn!3hUd0JRjJm1zmtUkFvYI^_2o2WBJD) z_l!`zer8JzehyhG0^C;U8r`n(IcRn!)JH%_VA$|)%Hkx&|G&r`cpdE!#06cbs#+*?eQGiLq&T8 zrn7?WXbW2Zs%VQ@ye)*Sa0G2ohV~$yQ(Mq^WU;q6lh4b!{BJHO=mH;h)KYuQ4$knh zp6{X`7okna28unQb1$f@>LO^M`cd7euaQi3ji1x4Lf(F9Q@e+4>WSsb)L_7tbmBSi z@C@W+KGqH{<@gYYS=kH z+O_%{-@iQ_vXc(k*>xpcMSX&F8MQODE46tq@b&*atzlA)^N1PKzI~`h+pE{*6*zmm zpcl3a=%_oPD^@~hltOo`fDS3aoV*z8XmLK1&TZcaJ)`TQ$gj{_(CV<4FxVhwa2h@X z&w4ev8`9)%CuH&h)=?yP)E?l)(INa&eTi23y|UwH(CyH{SZAv&_S#uq^D0>LUfJ<_ zuZyMsDqLcJcf{jB9g1Sx?jEvxXb$I8vzA)Al z;k9_5nuzn*+S(H9NENeoT6>*ej`ZDZfUia7p&jHkr5)=EtSM=4Ah6p#Z~^_W*Tx2h zG42dw3>g{YneX#hhjRRYG4RJ&)64ZY*%oMhOS}Uu!_-euegL@2!RKMv+XA3F0NY6! z!U3$ei6`bW-mAd3yTHE+$Uu1?_-U-i;JTDbHZdKid{$iNkySz3g6-UQsvP!e_<)@ALf<`(dk6M_pY%H$a)Xr`e61AR8G!KyeQgKY5zDlm`HJnt zPQWmXyBD>&fe-SXcP21@@dk?QyCw%^8@4A_D9~*FoM!GU9*n1A+MYg-| zF33g$#th6gCpRE%r!q5``7!C{snE^QcTp5&uy^O-L-$dDuGH|G3f>jyZ5#To9ep?f zeHnL)?7;kQx6oUiGXiM;E*Cp`2{MOpZeSw( zSh(EnFx@ZGWyoDeMDB8gEi-_$%bXvOs}8{*&Z`^5d%7F`McAwBLRmEDikFA(S0G$m zK6N}UcVT)F;7ML^CjjiiPpT>4Df~QoF*kHTKC%?nQ_$f%mQ8v~hksp^O=a>vLFH<3 z4$NCr%nimQ-_(CFc17g-pdsH`No?736KM_`L%y-MXO-_(&^Lm8ohUwNb=-w9-CD;0 zbckNZOw^I~NRA*bpXv%+6efQcqux5-XiS9-on+O-gBa=8!Vd-Q7>^&+-{)ev8H*o9 zR5we1UxYe5mq_zc(cj&P*oW8K@9UZzJr7-!#PSTDN%8PE&a?JyYxob*4^|wcBS1UX z4KPon1~#J4F!pNKCT)z}h<;?Hdk)#OGqcn0aDU>3Tu0F_rB{PD)^x&`cDxApg`iJq zbxtc_9Y#5i#c$iwyf0428b;sCrFXJx&wyQf4(!zF=qgx8qOb3O?9%+cb_jE|iSB`} zaV+2eoV)KJ%IA87&)GXhG8L?UF(#-PtjC8rEcLa`$OFH&6U(4WhN0u(>RJ74jnbOk>o_$$Rv(LTI3zUjfbC^`78ucwbZi}B-(ePRC@ zTT-{vnbh4lm-W#+x(oW4bS>$=h0lX@ zn=tjetKCBq&tCB;*59Af`rFRVtxiMzvHqTc{#X$%d5Y{73up|m%{Za2xjiZSg4@Bv zkEo9*GftGHbaf|zmlZSEt62yOUhWCnp^LJ>OKO*yIeQKbBne*L170R$J?{q&vhSxr z-UcQ(x`)xPXl+Vsg|k@8e)H?@k%ef-J!r=dY|da7+Hw!tlIH0tIfU6O>x`B(*8i1=CxJrNv>%607mrI^X-b{*Pi@nLR$A`(D)+ezkbl!kIxT^SkG_m$^D&Q-}!@myI9XZqKqS7U;cw1 z;N1(_(jhNLz{fJszZ|xXOvo9@4$OwBA;@DVMZE51^q8fn9xmppfXN_m&wi)9{!mvIjH9&+E;`2iNO0JX#XK- zPgb1WFWQ{lzXRs0cN*;;B_&9@e=lgK_S>w{?r=J~X?;uW zwikWUgLUe0@Gp5hd$$o~d<5LoZyHiopKvl~_ebFQ4|(57G5SuDGnwN!104I%rpeBk z-Om8e5b%6tFX;bfN(yky;C=50sP`h&^LLPgmT$O6aIZq>clHVWl>Z+QPkhcoe%kBa z`z6-bjeaQRH?i$w`kL^<#5p6@`*$+YZ^-61g#JXn^E7uLdmxQ#$8krU5A`M7`kbQE zCdHL&Iudy>U(2R)bX{t|X?nC8a9tc1^6V0DWS=ndZ546oOOZ0~(C~i=dNC0ng~ALz zKSUGo>=EhJGM!r7aXZS(c8C1!tbIgvAug~HVa+clmLC02)#HC`VqFo9k`ncc7gk`uFk~X9?c!;j=&4{ zgzUf!hV>=2g|HoxzSG-)>M!P8;DI*Z5c6d*9#zBsfi+I{TGXYN^Jtp7y~MLZEUGbiwo^;#ldON$~%5>{4&DH+f$}NPY;b> zM)QRX{k}DftJbi24kGNp);yzyX%0g7{^|1&gJw;hh{iP4Js``Sim5u*jol49-NTr}ksXW6uRcEq{|g-n=oeSS9a|6LT*=NE(6{has#&s! z-*M%@dJ{IaR=rLxtT!2W54p>Rd@ZH?BlDhlz-YVIg-nfxyBPb<@o)og9?l3aB^wFh z7k74vvmO|e8(#l2;qhp);GOb+7SGcZwsch-o*#$(VKn)<5Au_)$&U^4Q*)IzrhI>g zG1l#1d3KbUJ{9d8qYUD)q2n~!a$Li@Qh}^oZ5>sNbX}z9cy#U8w8zWqWE) z(%eT~3>$`WtS@gqL za$$n|zx)zh`jqgvvW8Qb7mo_}&049gZkQ6D@MqRml3a0_LKy4MUuI5h`Ejhe(Otc| z9Lo87Q#!9Hf2OnRn)3H1?Z2k{nT~_kl)rcUk!#AIIj;Ab^7kfezoz_|_WQ0Wf3H$~ zP5B4yz8_h2nKk^U(rxi%D&0}>Ns&D6O5;mhn3Ov|c^0h*E97Ign2nPw0!b<9Gwvt2DZZ^lmB${c71JOl?8)0+C1kJUkAos z#~69F^%3?Wh0i5^X1hb-60wJG@KftEs$^?E5>EyvS>zVsuuW~qI2*1y^t_l(D*TBjnYxob*MR0Q44%M8F!Z5&ye~H=pbZky7UR$+<~zN~1}5KKK)w@!bQaqAHP*Kib}_=S)28%M zn0$2xzg0By%Ov-JV`jxCuS1Su|H;{f-|jbxN6y&iXM3O%PQf0uFWWt^cjn|No>O-| zO#2I)?`V1Qqvey}OOyiFq0T8ZKiOBvrhF9Mv!2dkc`5uQoXY|}1@C)L!*>Mh2sS%B>Z?ndB#2DpphbC;FCUL`uv@2mEJjLnsGlu zkZAIQ-ZP*V;f7sUgY5ym%TX>{8PS2KlUc5=M_}U`7)E{-aF9oS*0yVrw(kOcTMgTS z-rmJZ=Xx2AEo4&ywXEkee5efqweCXdWBoSwD`Z#LfHkAOzbp1r#MuBnuMe_3g!~jH zI#fsMl=R8&huz?ZUS^H8%tB}7bt_Yj;@hhfK(Id=54l6JIw> zync0rtPNuiZ8>CKE_1HL*Uksr9oManD39;i-QfGg#8dkXhRk*T^!o915aS5VbIfH$ zuEBai2`qGC? zef+dsS1R+r)m^_b^D%CaUcorzHq}#-*MGi#{k#k1alMk2W-9MFNsmz;R<2$@-HCA* zGMQ)e_vG}5>|k7$)8^VF9j?n+AUa36k${3t=-DKgnX1Yu=@QEc& zrnwmUKyjIMPePO4-2j_pti?}DZ6wl$ z3>&08=83d`ktUD%BJE=%O&*^`TH000a~WxmOZ*jZnMRu2E+TDlBu(OnNGmYXqU-K9 z(xU577D*c)kzIjvT_jD?`y#EyNQ>rKr;#SNn}F*w(xU6W-$*Nt;>$rJP3}hm=Mf{V zCJL@Mk|yZ^0k_>qi>||cS4peBN}A6|v$lf|{|l3eKaZoc5rz!I_g|ma5lw@P8Spg{ zy+(es%nx9HZ%Vq~GMBi2jB^Q^k6@3N){bOn{5%=|`;*M_sSndUWI8_NgN?IB`!8c( zocv{JZld4KGFx%Kl4fT;G;e_~X3x_ltOtHTAqV#8hvA!&js14oYp=Mn;-u%z?BEL+ zyH_Ib8Q`JtX4su*Pd&^3)nnPptnAI$Pr(`}PapgB^(^5u_WhBU=+oB+V!h5Aqe+ z=lO(AlIdiVg$}$H`rZewE^3P(MB3sa`SGhPKUTZz?Q;Qq9KmNM+JV}I+5vat_RyLi z|3Sxj769!L|AZAM)8EYE?Qj$F4g;3L*;spWp9=pYF?pNMc`NR#iSSm0iMKv^ji!~` zMdiX?p~5dhMf>yl8_v8i*fLJrg`UxQeiHSMRnM}C@JV&B*5h&J)0D0{Aphi}D$k{_ zMgF%$co8MhYm^0kroO->+wpexLWvrfb-OG@55Vd(1$(cV==OOsV#HDAUdfn-H zT++|6$|W9?K9cPPXKpF(dqJ}o&^?%5tikA>OkHo5+1(xK8M9i4VB3g=6X^r2a9kzz zNq(*ozY#eW{hsp$c064d;@mj*8!E&9J;uVR`~8p~U?=X#8wTCF&eZ!Q?b}knEJXh# zovHOP;qRRy{3PI8wd^N2!xZTgqF)hyJ-@8)h!DghM4i z<(Z;PycZ_HSJJ=(pAH!h`3zC{T$en~dUXAfK4VYtL)={uiyr~_d6OUXaJptcMW4O0 zBl5p=Bc7G8-Ic=sbA|CAb(=e?pA2$aRx-Dx?b;Ns>c*V;#LMBl!b@R(29wSl&Lq8t zPX<01lW2{c3cF+KRD7o3GZ`PUALB2IQ^}W%^g9mHrqZ1TSktFsjh(9Eqvs=^SUn&4 z^HDz1V|2b14z#_RAF5 zFDJmZJQ2QMli>T6V4SJywa*$+>3)UPAq{-Myn*vU=K-!N2!&$s;Q#dc>;2V@`IO8H-S$Rv z&@oc84T1hSf zPpQX-ArpUY@*vZFtvvYbK{^*t=i`+=IztL z_;}nSH|7R$o`}wVCLu4~$#;hG?nuuKLT@d=oqpX)ax&IUN!hs5&w=&Ma%E;iHRc#R zKhiPhXc)%+JLz^hKTrBiylZ~HG4#Jk7iaNE_ft5-xI;3scSw3)$E)jq!XFz(+*e0w zgiD`W(Y=epPx`CJbl6zwD(bJGK9omaLlLZA=Uvd{ROfQ!DTlu|z261iz5qM%e9Zgd zubrpU`p58K0osD@OTN8>y?<@BQ~^Gr2uB z|Ds69p(ClmpYn&v9o_Gt%R(&K`&8SzR+A(0cL}mhGN>loxQvjTMZ-?drh7be+_Idh zcM3UF(T9}BY<&JtIOII`|6VkJc^dHAaDV=s++xV_dF?z`7@pW|hX&~0SWR zX=iZfX+Q2YmHv|*_lG1M{=nu4KK*yBXZQcYd0FU-blh=0cz0w!3Jjezzr(k^!jatl zIp*|kCH+^vzsDR4dtk}sk#!cehs=9DTpdFP>ActT=;8S`od0;Bc%auV&LLC#So7%N zYr(6-=;i2Pd2Z|b$`@4bJz~E4>|b49UgC0~RG)_X^)Fvv+^-XEw3E7m<@q)i4|Ls$ z-_7_fU`y{n8^)Vk@v$F$BJ-nft{+Une2C`U+T7|h_|wR8KH@3He4+^R3HaGyp2aZE z#hPc)-64HvzqMY)U8HZl)i35)H20qBI5sr3>-O-ye|~dsT65@g%XsSzs&loa&NP2K zWuKi({fy>RwDzFAPX-=jI&h8-ze8A;49)AjLsju#4y^Nz^lJ8JxAu_hf3>y7f7JR9 z@B8LI4|n%{lC|KUJ_%r~>09;NPjq?U>x?_2*BQqx>rQ=6P4Zucy*FBC3?_-SXJD#h zJIVf^+Zw}ID`U+`YvnUqKR5%OFpM>4AkLceKaw1L;p5B~V0ZBSP#fdEh_Z2KFwIq7 z_yWofU>z4Ip*wbQ4-&?@a5LSpi+hl!CXSE}*ZafJa>zdBe#YHI(B(81a-V0A4uoaeJwx^fM&OGV+{OJ=*TI&!7B*woxx+_rPQvzjkW=r z^8`MoaC)w9vu)rB&@@EthPM4ve1!bOmW^2DSJ*bQU2FzxvQ@|?X*S>1#o)^fyR;oL z6Z=f^12~gh2LH=xLy$w9MV{euhkizPl1*b(x?MVe^+x)$tRuZ#fu9zo!#5c|$CPhq zDyy0aS-ymI5Y9E{7TW0!tr^(2oYC(nDJpymwhtX<1U|fUru|8*n=aw*o$yrrM+nBm zA=q4~UMg^0+|BxCH?qE=|E=`VT!+ed9d?2mz|h@ikIWVHVIR8+=X67JcEjfTHz>0h z{v=6ksk+-;n2h?IDRvj0#T^6=?dt3bz%jg%`#No}W4oKXkMK&K`%R?_wP)?nQDW!X}3EOqsa5Ab>mm!H;+8zY3^6 z6!v`*ewFraK3^GW=KydFqpclhSs%48bH2-zIpQWOo;eYqC$#-2vU&CD< znENyQCmjCA1Z6njH=bUk6goDr0V<#3sT|xX6JkrjU-Ld+Nc{)I(>X@81=T0K)7BTB z%|c6YexMp-$1BG$)-a0srcZJK>U~qc-<#NMY;nrqMvmqzw`72_A<+2&{Hf(b{t#hw-51i z>5xC_@6>Nx(+(aIZ8|Hs3;eIfxfGHS7vza##2+p>nf3oZ_9WSEll=aXhK&Dxs6v^) zH_4whLNughP#dKMp9Sn9z@>o(3Rh!ZZ>_^Hc$=M4QsBh?tO{9Li1xh;dWm$>xA0q| zeDlyVcpt>waC9f!v$(HPh0Q4i{f+Xd)AsQ6XR)8#uiXikiM}#yPd42NcM3ij)Q6y- z4BceC6YluM@Y31%Kf?E@f1%Cj{vy5IcEV>Q_=%9YX}o^Zf(+vU)%POg9(})OHrkQ) zO&NSkGVnWSa~Ix^K6C;0D!qMX@b(cl%uKEQda)Nihjj9I_A>G8Ujh3N@KU&XHmd^c zG8br}HgJRg&)`0N+wP|iy>U5wRJU1D9B(U}x1ce*40AEMcla6H?fE+De$h_v(}LBw zCkJDA_UEAaEsPJtu+hH%3x@w@m`$o|&Wm>z~ zFjh3;eJA+85AEY&&R_=m)!WcX3qc>X3$yP#MCs3>eW+c;n4x0KKzqw$24o6t5`WA< zedunIWvEXfug}cjDV+TwUJ$*5(8Ht;hQ~iMYx?AGqwmc~D#CvKGTfa(^&P^PL^eYj zk7++czbBDwhcqtJJ_hY)&^?JXR`-G@0q~^vo=)Kh4*KYST9VLrDiu^(*#JkwDARUqED2C3% z9a9e5fJhVL)w6tjl5q)`S2;hX1z!gbK1ZKM`2&G*Y+3tUj7v(Yp@U$5#GS(FxF3n- z22sBSsNX)+ufg9qvMS>(w4L*e7qa-wqgf*ai~nFcLG6V51y3%2eSWY3;}G$kbiy9! zrD5p7J#*=PBAneqKhMTJLjAaBIuCa;Q9kI9DoUp_Tnz7!flvit_I`tnWMv3Ang{tn zf4cGCnyDvt*>L}mq69bK&Zlb7Lt`=NrmhLox_#qVXb7~swfP0z#d$5h81(<1RMzX4 z!&Sef`K-|%Vo!<68QLx8A@oikeXOK$MJ`((^FkA6kHorXobuCswB*wecf6vp^eX?u zLgN|n?{)A2{x;~t>Dl2V_AvHus>&dTv=>Ejltw;sA)H@g9otR5H@xf)ZG5D0bD?$C? z=ui7Uv@6`-ra|PLus@h^#){%&OOq8)M?ab zcpm&fA5E`ZioNN;JXYAQ-38uN%zCEtJ*mk5B%Tz5vQN1-vweJ+0}OpKZ>= zeiX%teLSL9*Dpor7Zfkwd3^!%68+BKA;1xh`X{`be4(6JbEd#vF#&dqiLhV54{FEc zzALaef_-K-!409E z(AKG6;q2Eb@F}X^ z2{@aFHM%vP!f5Mkz0Oou!b|)c1`S!$_RLBGeii3LJ-{EZcg@Pmm@yk;`rTQNRiEtF zWa7S^)&F&d;^?mc-`s=)|EV|ffxVB;G^u|*sd72=J;4smb7bi{9Zr9IKXnjyDe3Kz z?qv^`p^s46nK;MefM5Sx1xH#jKiJ%fdiiQV8~E@7Y!;EWm}#_y-VV$m+TpgfXorbt zhpEM(dus*%JAvQI{{ZSi{14bzs1SU|T(^H1ZI1u&o>5gYspl!ApTWKTn{jV{2)|2l zw`CvJg8A4Vz90WR@fObR!}lbp;=dkLq=`HDlMbK3e^2z||0dFLZtgkIuk!zza0Cl+ z@94kaKBdg@GmZb65P2_tLUJ(-`RM;z#bJ`ARk&aC1pb3!@0E(~2X;^D`Pn#juF$R? z-T`{=S*RZNLx!p$LoWb7^+nqIJ`LFBu3LjP|IIS8qI5qD@(or0JP z)Bj*t`Bm}N2)`N>!7on&JJ$hTJqlhuDDkSB^NRjcL(JL8jxt*TuQ0cxx%Vu*U!-@e z9cJR4{?}|f=by+={YKUmS?GuPsOztCHGN?xeK9WU^zLYV@%cQPp)Zbq8qO~VA2acx zaoxL)6_cr9!`TjY0odx#8?_PZJ@%c0uezjVY zqyMD+l5L9GR-f0AZA^s4`h?yUHmhdDcoYS33VmlLKsV+kcJD}RM|(xq4F2YHJ3@B9YZp9_7v8|S8DY>TpZ zT*|lhURKt8IR>bd;Y0bb!TZo};||FAMt|IOWuT%C`!b^F+t|(vet-6K_>|^Hvc=Ke z8v;k88}NH2?&EY&ejg&YN}vrr=&rP5$KB3uSuwJqh1Arthiv zo@)BesmXUulHXk)1CKt2yG`%=_M!;dM%{gXxX3tbv}-ko>A&qt@>~B{3Oop_L}y^Q18z}U%vzSd<8uB-h{pzVaw4MFpn2L zz3oAkn>@>be<=d|C~t)ae8AqC-x)rP#slaWm_}IRXZZ2846r}UTO%sGQ{l^`4B#%= zI`H8k@VyIT-{q4nyyAQw=DTR8N_=`v1ns=M4@3{n=acQLZi*QC+IZ9jaD-5AhO0&s@((zcaU>C1-l}WVV&;`QG23G(G4Vw~_M5GebO| zoCw*ORKzwh4LqQ1OBstQIc1)G@S&c``@-5Y=a0o9XW8iIWP17uyF_=XXKVI!!tVfW zB+kuGmxOmU5iqMR+#aKJJcr-hIFr=dixe?&o*!x?GLNwe2l!?JU~b?CVpu zHtF-gmL`p~<&I+=r3}M(-3XKC^j%V3Cc|$^g(EN6fy9|J|HnA5_YQM;cdPOScy2J- zTB==Ez07twfWC%4g!k~LaFDK<$uWR|7kdF8Aw1UDP0JOz6U}%|<7}U6;UALr7y4k& z&|MGU?g!AVXnGc~kmvb+GhHD?R~_mAaYggZak`EI*w2W2qTiFHr!E4#4vi%!>9<5KL z4iT7(febqNGH83w7x`)&<6R={lOw3-U&7{iCuQ z(4PKca^UD`*QHHQp#S{J%)rqnbNM~FsS|j5fn%>+*FCWbXT8^UN#5X0E?uV{*hXI9 zDZt*+JmGC}fwu(+n-AX-@0o)?>cEP7=RP`&JKKLyFAhA9@sxmF>*SB1-i^9NMGx}z zpggeAn#5Ok&wUrX^&lUX&-2yK9TM=>@}BPDEZ3=bX0V;(uE6KTff|g@n^D)xMb^Z# zXvYKSue}&Mt+==DYuDoMP007zzYskhv1Dk{2fVX>(m*F@=Dy#i^UEIGH%}b6e`oNy zV=h+{#_qNEpHS}u;LZKWb20crTlTZy$!V9nX$5SW6|h5jUiUue?yDf*-f^n#pr>m4 zb{$_NFjioGN(S6Rv~fh=r3YTS%J4mOPLI%M!MOyNSDu5!GrHe_&lKg8>m-gLuOlb! zoBO_&vEk>%sdq32Fl-l=n>eI@WCHrEH!Fuk;L-z;apqo=`BANas>e$VCI!|x+#AFs{8eaZM^+dw-ml4XXy z&oaLTcPT>%}A?}ZP|IRF=#T}d5aDUKJSF#_3j)QN}#l8?@G9m3>!v~GI-=oiQ zF9g=N(g!+ca^Qi54cK544wo_T?^7!Ti#2YCGl#?3g4@*e$Fxekc8c6)J4j_F0!D)0u22wucen`O05A zBK$h|U(r5D8~Jc9{*jvH@I|qYmU*Ao;^Q4bOF6m{_y^z(>3;q$enakc}Em&2zF-9;LS_Z;R0erShxs@Uj*{V*cG z9I>$ub{XN%ZMveS3poDX=r^=2_RghO44&VHvHnty=Q+m5{GMUMc;G*%Oh2c=_oE0e ztj_7fxCQO*==p7xJ?~6dGAPFoyRuIGa=jOP$_BqCf^WEca@%C!&Pv{s!TT}jLl{IG z?%s9TU{Ih>M!wXSGH9*1#Wzw&hXb4Dti~c@ANWZbt#MgJhV6 zw;uQ-;kU8%6}^k`;ZER_^KH=czNnrHEl@n7Z{h{e`kLlP_W4aO^Bg>;<5;L4GzM`N zN58vk?l|~-$g4-ds|a{?c7{BsYUN?KXz~cpM9k6OrpAof6UhgbjpxJUJoV7r*}Gt? zy1Xw2XYCny13IM3t?13NOkHD!*ZM%=l9p?!L`=GBlN9H+etS>#xq`kMR7tT-eL+NI}SA!UzuXL#gzP08f%Njg;i z`Sg?T`n^Hwrg_Lu*)yxr##W)Ntwft!0o{cAN_VC1D>dvI5sb%!!JQDLo$^7rc<<7W z45s_|*!FqkqT;K)u-Njz6{N4)}UyTfo?AC2a$v9ppl$-_v!j><3jJtS>Ko zy!rE#uJ}W9otkvTPWXQfT_J5z%soq=I@T_6e9F5`87`uml}(Bxg^Qnk^%BK2+G&ROS1 z`vje7?bEY;j%>GFGiT@t%4nu`I<%5@vQ0a^{@QD=zkV@TxL7`Hr#sMxhhPKj5&~q3 zoX_ar(Z(u9TY=rA$0}LLu?p`Aqup$bS^Ckoz34~eU5eMkc0~Un`$L4y#JQ(iVP7tu zAU3k>Olzbw(wxa!@wCUg;sNTVpQ69vIMx{BoSun0c0v0aS>vS6CZFDbFAn8+h#zk0n;X4nu-nj|;4k@xvTL4WjsRh07M^bg&xgk=o-?iV^J-Z3`Bt9G{$GwGa(hSP zIs5!Bj0?#39a)$ohMwjcQS!d}tB2u0I!)VYcDE4$HG!56g+V`}(r48Jn#l`in$1^jI|yX|HAFmteeF(3Sp>pj5FlSzJJT@k`dAh(8m9)k=T{GvQjPTzo> zN}o#>WmS#EJ*Z1VhRt!bnOKhg36NLt;4FB-vuBA*xMoZ=`|Hke{0m0{UDd34eSs-!>DJL zi|d-ci18C`iR8K_@VXoJQ7P9oWr>R0v95_{K6PVV(=55JNv$94$C@U}#CzB?f^@Qu z=`S(X5uDyoQXcs;o`dBbs7D=~0nhugj^E_6JQ1`xxf|r&Z?|J`IdXq>qj;#6cdI@kl>A;vfU?#ih&p?XX|EAwRHF z=DT3;Qx>R)*q-NM-Pr4>8xazx6mH7p46Kh-`JF*toEIDTa-ioW@MkgCCnIe>)-dnH zSz>PNfiY+@)5H9XHhThcVwP32oQ_r&>s+wc7w9qO{NIEB9lArVrI?91|JyO=e-eIe z@+HreJJ1bVp($If8I2-c0sK@v$AIf4_Vn)g53WaHTj~aF1z3+l8z~oex5Dp-J1BCK zYXG`{qtlJ~f6N1X$L)P|IqEuqx<34C(Sz~JP^1X*;LG}_9>lFgogW4sjD8J)L%*5F`NY9IJb?AM z&`v7RPQXX=Sl*7lUtKzPkmm;3=>_Pgig#gK5I60MF0A>V3Hkgn&Q+qnJNhZ?AsO27 z0M><_s?M7E;$o~@#=ec(e|G2WEpT@}upw*iiv_N^2+tna1-a=5{AS1!&)mtu{CmDz zeRIsQ8S;>y)%igG@X!Avi1R5uz_a{UJ6_(wcmJb@u;$_I`!F6KMBcRV27k5fY1(*% z>vPZCtNesY??>G@=LIzMAU`k0Zk%K3cYF5Ik44?VcT8U8kVmuinIPod5X$+NvhL@g zK4wXOBEx-I>G*@cC*H1ue9JvA=~ z!*GCO`usXk;X@z6{VN3?^hvmDcKQ94k5cy%xBdKwFe~0vB=empCU% zTwaMQ8@NEn5c64%c<6x?ZAd3+1I}!uSpj@wq78W)w3*v3?1X1HHf5U(={}uu(hhz8 zAodrq%^7{Jm+f(qy0f+b@`i8B*WpaTsjAGh`R&@?9q3zVpRw(k`{aD+1mlib58q)M zNxNvOI(t)K4NI3{XBcbheK@}rKEFz|Dbj-TAs@gxrBl}PTFY?v0d?j%tP4%zII8gT zdkgm5p#PsQZ5Rvg$BCPFOc`sSux{Utup}NMJ!#Gj$hnAQ+zFKj^&a~4UNLLd-X+kV zZ!Co`{VMnbCkol8=LSr74Qsk0OJLW#;O}~>Yi?u-#)hW;@io~$R-rDIVGOYpI&KMk zDJfe{wL?*KF~6DWl{i_qPP)~Y6L}qSL_3D}q_eJRH&d2!z^4S{>ghkxzv>AV7M0DGCf1Kl?t?ZAigDYDTfXh+Qfo>H`d z(@T^sSBCi0f1u7xIte@OAm+2W?h_SvXglsC>^Pp8Wb6sb*XJcYe4o3gYdY;Xo~4x1 zlX*?0}sG_5gzqyzlow z1nY*Do5qZ^-zal-`qW&X#+_9k#Qqv%NBcgFJUjT=z#!Z2bI_T~(Z^MH2YPaRxMu`? z8)PZI75f!#&%N&uY2;q$U!k1aFI`d|!8l>}aOKN~vqbzx?)}4f>yCw=KeP$@z=L&+ z4CgqR^H8&}FWJ}!R|h@ai8IG10^j1SxoWL0c+?L)&NHt59X5m+2VvQ_s6GvTD)7g^ z!M>CE-UrzxY!}MX|I6WLw}7vgATEJlj>-AWcqhJn5c@khCdeeml;LwTIMz#_J2h-y zWtVV`Kjuzh`{oPOwYjZZ^pgwviSoeyF_~_R`l(dwCydWAccO6^dH~;#KtF*V=%|bt#&$jYvy;7f8@ErXY}XE z{TaDp$#R+GVK@2)#zTKhRQ6bEeOy4~{a`To zb@U4^^bc4QtJl;}2X983`YY%L@VlY_y5U{Olc5_nN!_sX5YJBVPF_-;4Sjko^u}W7 zjV&0royMNxZx$Uq^g49i*}3#9aQ|{{Zy*>gQ`siJiE#{xr5 z_{(=q#P|?*N5k&i4cop6f3)GE_*;&>8%A6&__`Z^cZT4<#`;@t)~pvjt~nSZcn0Q8 z!5L%V%@O$8``uVGjPt_b6KD!yZ~FV_CrY4ye}J{*&vHGvZ2#~L>A9P_Nf=+sFwAM_ zFq}OxBAthAMau}&V>}Lhk%BSDpT;~|C-}Bf@-TM*c5m%D^ogXg0=9{<=Qo10Be?E( z1OB|O>|WIQ+kN1}N${W-f3%I4;}7eSdV@Od40wQX^)n@(4D`$bA6{_hf)DCG!Pij! zW2oOwv{%r0^bG#Uhj|Ep27Gu2f3JWCU&CLQEHivcy39VTfr`j5=s+FTX_L-ePNq-l zO$}p?=X@ghz;;Htq+WX#d>}7KCwwSHC$w*ob4X^N#9*+p$Jp1%bliVuou~3f0!Q=l zm+kVd2v&*s36vAOTCwMn{bd_2IatQ``Ij6i%f6&rzJF(2f7xP}JI*nV$K{^BcUB*6=Yh5YR zeVE@&@>I{0kU#X{QHQ+8Jast3DDT~F&x(_J{><70+X z()i00E~)3t_&{F{c}RQV+@+TfT6GuejQUHi<=+jv3Vzh%umh7c=&(NQgG=VG!vf}V z>#!pz6W4p~COsGf`pkW|PUE}O#4jDzIYpFq0HzCnfB6S!;YXpe2i8X+K)eS#V)bAj9DsO`fwry;u(&%{mueQ9^whLcNf`Rfyxd({9w!578GT z=k(?%p0ZrD$EBYI^L;1->eAC&fOsEx-UI(bH`?e#^dFh-Ze^S9&UU`L)eRf58$OdW zS=ni4M}*)ju$GDT-+d^PVFzOzU1HQ9X)VAX%Q6ptEH~?%_4FOgYrLP84LyjpM%rJ0 zdS=%^)}Wd%P;ENZXPld`Y>?v{_yCT2@kiZs0{$J37i&wf-x2ySIsdoEvRB3@0_R=$ z6TZ+D+;71=B`)yFi$AIF$vac}WccIg zZ%yGtNIyime@%`*M$*IfYM0)SBQ>tn`*9YHpEP~;6<5zMEfjWb*NZ-ue#ylZSi=Oo z^hI)AtkF-4Bd!DFJL)ZG@oIJdUOw*LgHD#~Op0Nj(e8(DOx^=)zHb$MTrc-xP|va6 z>C3MN4=BU*<$n=!Pd|QSrYP^wdy`W>eD3*6`SCmM6Fm{P(0&PZAA#Y=-vK|qnPx*y zsOOlk(^_!otqMCo;|mr)Bib+4_RfS3QGUiB!^bxte#VtJ_erj0!TQN8i=Xis^s)I4 zen#3H9`HIJeroA+#QyZ(grAYVMZ?cXU!~z^tdnD0wa0I)zD7^dw>Wq2J!!thWsr@f zu;G@#hO5MQ_uJBrGkDE8)c3B%81UBdux%$`9j5C5$83}_j!`&{;QC?K3+AnRhKDhx zhn*2YAM5#um@fCR%@Z5Dz#l`#tZmr^S(^txP2Znlt^?x&;vx>uxPxU~6ONRn#pC>S zBR(Jfx5x8~GS5w(8tAaw^5$Tl750gaDIcuiA)bf9S3CS%ljHfw?CE)~%Qv$9+od^; z{?i=J`@M*>Z`U^$_5V4}p#m?4^RVyL-FZ{wW3C?Zt7n&5cYFeCyNvzy?_G=WT$WmM zY{tjC-H7komV9_O9m9_y9KUjop#Lh^k>DT0lQrH~%_@8}=N z!yYZHQyTh_B@d$>zF-a4d^_k6&b^<>{7v<_&l(PWOx=lR(m zr^UUFd;AEu0cGTG+FxsZB680kb?y_N{>+{&`yX~1f0d)YY0pttv+d@ETs?XBiXKf* z#ctRc##vf-Vr<&)7JK3A{px*?ed_(ZPl~rsLci0$$Ftu(vqbsB(DAaJz#nZr6CIrh z)@BEu-lX-snh&9$Px-Z&Fa3PrMa6E|Ez~!!qkqVQ9X2obp+k1IKVWhUy_DDQ+SmY2%1#`vQ7zYPVhdCyH=G=9ottUr4Mv`$`>J>@Nw^O0$MpEBjUDBl#&bbqBdb;KK3 zB@Q0BMdXL3OkU)ka{aF-lo58d{LP-yB7dh$S&eblBlE=3CY-0U&*eJ6^AroFW$(p2 z-BI`+O3;xW1)T>tcA^X{<(X6lzjrGh!dImB<`e{as$sJV*s=xZt6nZf|BAiz8~46F zT+20zzr>na@|p4>qFZJE&oKhl1;1Uf3u}acdnfdjwH+Jwg-5nq@Dp_4UC!Ha-0fM7 zb3Cv&)#DLI*@iu^XQ2}|(huU)rXjNxoa>|vQhyZZ?vy?<+~*n)jqd{ar2XdW@AC9t^I8NCbP?;+SZ`csZu2cl zUXQ~sVU=NoVb2BiR%H+Lz;t5|LNeV(1q-=b%e`{8d4^P)I_ZxQMH~}BzOia~T#b1x z1nc5VyC_7TPa(Q-w=W59A)`D)rgcd1#Q zp{-%eiFN>3>MAvsPVKL_C|qb$cDO+IkidPa2F+(67v9@M^4p6#U5x#V1yAjs>xI6O z=^(QnoOQr6y8EtC&sAz@3DP2UZj8pWCTcIk|M zi?WiOyU=sk#81D^agZ}Wf_rQOFeR%K}Y_Nm3t!J&fk7z%elrg8eMSC;L;A`l+1>}i;oGUTjt-sQK z7?*B8bU_z*p(CpKi!~0|_aNK&g`{<|Dee*O7wLZuW{J1oqEF~cfu0q^%O2$XHttaD zz1HP!`w7mnX(MLUkevE$a<D)VTzi3weKPHgy}-qO`HSG`@(-3h=$qzw(eNpM6K8&QqAkz{rX7ts zdWi2gg7%@G2cGVPUtr$Px4+Ere(;7qbun%BUg*u*>ZRh8cSiMI>T}p9y+_8MSacfr z0+;Mu^f>bKPQzK0z=O8ly9c}sx@HXY0dC?1ajF?*c*{L$?~^D))3ntuPI67!`xf#& z;yS(PN!TYr*W`iDOAaqWe_xwDZKA}(JXkKzv^m&+u5i7XRo>e?ZPMO-sFQu@JNAK= z>rv*Pffse4hv|-kA3w{Q+zY%1Lcmvm^m{(0)&Mx!5=K96oe!W6p$z4@W;BH)--KMx zPhCOTG0uMJgs$y^?UHkQ0BZ(u_AScY{^`I2o#U6_em~`N^1;U9Inbm@>0UJlX!z&N z>w1#?me%EUx(}HO{wDh%-DU&S^T>O~ZGoO0z<(Tc)*)ZkVIA`1JPG+~=zC*5khQGF zTm{#G5l5G_>oA{Vz3#uD?6&!R zF1^40P4e0{zt8`c@{=+QyB5A$=!Duc!@Jh*7V4~~eAMZM$P??+EKjNWOszAsEvuH} zM5vg+#8+^y25PQDo* zd=#8>ps#9&+trf~{+?v{zyq%HHvE@dgZ4S}FUPP3?Mm1O4k0& z0*>9R<2GX+LXF$FpIG&)!+c)2d_o3H~O!Fmd=izAOYp6muacj&Q|F_tvb!*S{+tci=rHE}!(BDE&& z7{-xZSHfp|rPEka&pT`SM_apwF$?-X(|T;2VMw1IWNFCz$ALkv`C5#%emhXEyexq; zE95-s+jHO-{Jap)wxOKwq0jyi&hujb@IHJvKKQd~PyFycaR7Z(%+N5PL^xcjWvQNQKl}G<9(I`ZHINMY}uL67xr-A1;-{2 zjRwnj{?S*!U!zQX4{>dzX|EOSqa7qT%6=d)lx`7>R}XU|ub z^y~)z*)G^V4np=iaGwC{i1(e?tqa?VG>dT;!j-tcgYs#t3p20RI-=#XALXKavd!di zohM|VAM&8&b5<|?HOzg9TEZ`)4hJV<4+84;9P$Qlpr0=vs6#(H18cx2 z&y*e7e{92Z0QVgH>s`pJ2YE7&Immr_JfOFf1|zlgR!fVTVua8ZxfVVw`t?*vVx;|R`&KkgdDx-HC0ffn}t#+>Z?cUD1mmtj79 zDfAcC`(u67M!2EF`|+L!JFXA9oBfKl|7wSR*n#@5NB!T2 z`tL=#dEXW5A%HTI2O+(#vlDfG1pOHIIi7&t-jOw9;EUjM7wV%Mu&OMxduO98l<+f)57*46`ojx6FHzUV#38 z0b{QhpxfC0b6=g%dy+1u|2L1nIFEO+{lBqR(#Zz+P%n;sFOie4CC8`kyvudvy!hO& zmp$mg`4nFG`U~L0k3t^K!p~3pu>kQw`1|R9G5h+D!uHM|-u^QCVf5wu@h9zb`p$jY zZ%!GYT=h?%z4!g;bN2EcgW2$hP{zKDzBx6&tNa9;>qXBdWjDh=!+tV-JstfX$S21x zoc$)x{J~j6$-Uop?PMnAUCKn~QI2mo_W>UQ*ZiNt8M0>u%E)~gynpi~=sTPJgF|=y z%gjgV$C-=2*{)f8Ho%Um#a&6Sz#e)C?+@X34{WHQYt}#~;Jv^X#Q6ISz_0ZF;LwJi znU4lt*grvA1UOc>JbU*Rv1?|;{H}3Q7=Kg}a>AQh%9cO@ZFJ9f1 zfp2ge>vCQ71+D@5ru(WdxII^15%A5s;tyflp2l50Cx5x)A9q7A9p^82?ikMjqi-zFFO+%mb2{_M{uxuwVreK-! zKe+eh?riaF=YQNQ=ddEEgF4hn1odU;SI*VZze#>C-kLv1+2S2+oFjP?_1J}a%*R+{ zBI*tEa#-h^bCxo`13u3N{I+;sIrQZxa~}187j?jau}boewH?5Vg?2ejsLvL}J+bxL zLGG7-0zR+n5Z<3Psh8h4Z}l0R5zTcH&m1FOl=UmX``u@A9zBM&!^ib{h$n%E-vNBL z0^iR8|NX5kgE*MsnV)4{+WT|h`U{k8Kjzcl#$TR$T2lb!xD+xJL;5FiN9WI@ErU$= z4+tZU@8bIjypxVMe>IHbFmNW;*6VQ|>?EvfnylzUxOwk5>L#V@9PV&S*R4ynZoT(q zuc2E9OuBWlp<9DB*h z(yObYtxeI^^*-TiPlVQoZ}f?5(GY6ACgF>OS{s|gzLt*WM6?Yr;nqZatFJ8v%Euln1#J4#TZuK>5yht7Mg?#PE12|-2u{6}$8cX;Z;<5I2nb22N z<3nz~#&CO6BG%?>i^tYQo5Stm*4E~&zF2G6*VfS<2{y!9fuJ?vt8b1qH2I?KzEE>> zY;(BLL{4i*OFd|dt@A}&H^mx4i70@~)YXR*o5LWmA=c6sZI)|B{;sBho8SlpM0Kqx~k_%FJ?HI(RxhY6Glm2E=! z@QB*2Z9til^BYAC1O;uzx3L3-SQiB!)1p_iH9$CTZ;c|W79X-RAfy26)R19ceHii| zYu(xs>uA4@33XsANNc=N7?@OTfx<*MzAi+G41wSdHZEUdbltje9E}vwY$Xk0AEDb9 zh&6Grxt(lrAQTDO!vs*RCd8^uq!OnU%AB@MA~uyjEoC*SY>Vk8#^xRB*b;4yhS0d$ zGjJ~4!Y1fI?kd$Xb*yUQmYmVPC|A}RxzTr}xY7r?ZtrOK3Fta}W{cI)cF94Lg1gaI z6@n&{>I#i$V@DJ$l8VTbNT8`LZH~4rizH5X2_3ap+v|~+boU_UK&Fhoq>@| zsedJtNE*MsF}yC?ie{iR7Miir{zOwBL-S6Yhv zxoVC<|D$6^!Knfvi0r@f{WlbA1{7!xNL_+dVE^jSmfCozwVi6~X0WF|)X*fGb8|Sf zDcra;g$G%PO7vFY5W0T~xmHn)a)%+nqgXYllQpq+Xth|YFukt{$M1-SH{WuHld>^@bQ?83Q*c0LR$-|KC(UBg zcN(cZJQ16;P-euY#0FwhPzoN1(E)_xsSpQJWh#xz0s$Q4TU#uiSRHC_B1_HR8Bv=P z>m1BMDfrAy!z^PdW6zhAvZTx;KqzD-+4nmb!P1@+x3@O6#x}RY-hfmt5RkNvxU>Ko z!-;T1f;NQ@_8E+HSpK)fd`ZJeDr+fczI+%_TMM9qI$Eh6rB#n^ISlJa_H1FFA>Kx# zS1s*2sg$Jxh(KHTXz)p+EY+Qp;o{E9wYOB?@(G}>TD$hvwfNlx($MFCE`r43i)#PZ zjW_DAa6WCxV8Yj0;Jc>v8ee!z0~8ZXsL&Rr%sbjxo#C6k2XmA5SFV?(6|bS zW@$L&izG=mfeVH%!+W%~F}wx8?coIeug53&!|y~q9BRQ!Y~4B)2jgOWD*{s8jQ&Wb zNOdNNk=iR5N+e)ZNPS@BWQ=Hn(MBXo8{~ih*{=mtHavrL8&I5KSnnuyXY>6gM1aM-biu{l$-@`0MXYO11fv zdXv=m#*T1DcwML^+PpOtxH%SYS`QAjrGnZ!>a8KN z`LJcAQbBY;*``ned2W*CEOUoF2=k!+3@ci`L0se<^>}mwfm8*9F(}zj}WmqGXIpR3Gw}62@N`3>8V>a{MpD@WNkyGgYv? zm2BWgdGg&9oD58bC4(ewQH@Cb;OCgi7jV zgp5|PDv|+-a7!DMSgbzO3^rrDrT+KjQy8SxUm&8b0t!(WwXIq+LK(;oM~Z%RBj2m_ zh)sR1p^K%4BWFb29EVrpW;FtrpL%G|IGIom^aWM1w8j+-EOri^F|ECIO=v4jMVJ|; zkLp%@Mxu$z1ca!*BN4_Yg+2sJmZrYtQzq}wT}o1m3jyCto4^1y+5v7vqU$4VD6Q&v z)X*?(%qdjEjf<%05bGca(Q?sIE~0qr;8$s}=)fNuCAFD|wxH_*qqlHSE~>U*FxeVv zzO|}G1cS-XqGg{f`efBzwW4U5Sh!3q?Whk6|1x}`$4iJMQh|zUI#k5!8d1p>CTh^e zW1EFEpiv#DA^xX{yFq2Ui7HK5_9`JnFu}y-_+fhf;ztJa+lVhM)(PZGeJs{2(37>G zFH*TA;vEgLK+@O~p@s&uapj(=G2&EJ-PRF~Z)MR^`rlw~0-gwQOGnF{P-&l_N^2L% zS1C8iuj*xD6&*3vNnaR3J|X2cEy$XP9U*h5(HgQ{7;k{btISnqWqhR2CF83$O5@5% z@riKyr!u{a*j4GVtCF!&LmOGik5pEQ7#Wz#On#;^Q=jSRQkltEomsL)nwp~yll({q z%daJ&_OOZ-d^IA)vUq4S+Oc73;|1a&>8GKrAeEjp?wNFZAom4 zj8fSt>MWE&jfPP)gCvvsRDpDO@J)I<! zb*oq&ZiYpZDl}vyzEzTTOKc4-qY(j14NJFRZ6(3gtuW*u$iRGab7*~g5~emL$-uY#t&OSt@ST)_w09+72&zQ|$y&pE zvdN7IKWpR)?dc)Av_<#e)xRIfe$(GAqRe^I8fQz$cY7Ceo0YLVPSER4^ui^MbPStFDx!y zSYFXk;KR};OkiPzDCf4y7Zffi^W{epiMI9|Z@2+V35a09`dAE0&)Q=h@rLjM46$y& zDuU*QNGRHRgMzOwDOp$4SRAfj*SN5xeqCwt!p5Sq#`=bkzrMbxsJx=2tgx`W)L&L` zLAaZnH?{Z{HY}`IxGr24DhvA;))%g;4;6TC%MpUT)$%#W|JO|V$kZ>m|76^Q;~(;T zZjy{ISJ9%&A^t8Mzsezgi;lmJ9fk!z)_w|^FMexDV4XSt?1v{kGUedZ&rd&;^XSaS zW+R&P@^Rg>W|b_(#K%+sqFA0{d|j8^%>nJy~Wj&Q^ytuR{#Un=;C2OqTHVwBO8#t4^9RpmqhKr!g7XsI(;oimKg;(3aEv*mG)tc!7wQ$BT$>Cn~?&w6XtI6X+4q-6x|sgl13b=pZ-M4wEXflri| zhcrFU;hm2Uf89C^>+UW30{Q?!qz!B3<-__(=4V42^BB}=SuQ?=pG0}avnm50*jCGR z+Cc&&^_NHL%~~Dz3rigHZPRfEea!c`re&F#r&c*fx~uW`l!k94jkawyNAf;Lr`r#H z8F^)Dt1Q=4$QYkh@;^ftcw`%kXq>FqBu-lzl)O+c*J*qY5nqx|svn^)`MSm_GUCh; zoA8F-7o_tG(Q6`;u!o1$p>5ed6208R0$>oq+J|FNu8#!Y6u(w)1U+4d;41S?} z_+*}s={y&i>vjY#^k+y*S$IjOe+lnN9^1%*5Ak2udEdqIr14g@3G%2Qngr zfsUJmcd=~B)Gt5|$3N%A>LDES8d=f9cRrqA4wBBuG6u;*tgG? z^?gLA?Pgj$9k!i#9QaSzsb2ht2dt0}!>-n08ik~* z+$L<5O<0{xSi&Z(%O>nGo3N*Jm`{->Y5A58Gic67+^afF_L-x!QOfAJY=unPVoqtb ztwnwm>-0VaCiuHthuv+<->H($W*fLp9VYu88yRNZeMzU8MBLW4K>Gy2O!tyb*UbLX zu8u#SBjx8^osRl8z1>WbWyzU{a6Hl;8j+tWOSw)Xd4{w;{H@YqgLofF=TzCg+jN>{ z=50%((w!{NtD4RuX5E-Z&m^V)G|qnJYl~Cq&Np>B;^rfNW#dQRM|#q5Ydagk$pXhIP$nl$5FrYVc26j z%&2evK4l4Gp5M}8tMG2kv(F)pxIWNv=DL}BDUqoBjo+(v81pj1%5|8zZdTcZ)#)&{ z2?I7^2_xPvbC{_uG44w`ZaEPcGLBcq9oKOIyj$abGD_T_InGp1OR59t$={)BCGJ`$CdKx!_#G#7hf9WKM@bLMcOYML!r!>>%J};xHcZP176>NwKsCf zO%OcCG9Afv^1CKc8Vt5JHu;O2u|cvr$^VjCmZa*InqUQf)lQG4DZ4as)87bUL0Z}5icUNtyD&_*)Dw~p&ss;9vz9Km6lUq!x8%VMrvkLJb z_K;&Yd38gTrHBY%P;s!jrqo(klw~ujR+gfAjf$7xCfY-x_Baa->al$Q^4FLubZwG+ zl&};jBvZK7IEtb(L&;L3yatUmRl%x?u<8oWPTel=;gg?sQ(5RE;X>1!hsI z3BeXkPJM;r%ZkkWO}0BjTGL5SwnKk$8z#cAg~+)LrijB`*O{_KQ6F}JD%2X>0wj%j9ddrHexSqNP4 z-`rlcA%!?CQOdaRmxLM{iO`@;X()eT?QO=H5h}!xzcJOO4UsV%X1w*NW8*ohGbK$T?t_F8hDVG+pofQV7nQOLaAvd>S**{yS!9%v%G_F}F zw$C+PNg5Pc<)B;&w2{+Vt_ZA(%3h_swmPQ1<)^8_tod1S7Hb($8!X$aqS4GEj78t}#A&LnH4(H0z@)P`mDJjw{?H>FWM7Qrh=xoafLk{nFKu{Mg5 zkExVn#gwT`#IrigW1U8!$e}JW;V$ZELoXY)5!#xCL0Qy{5?2B8Y~XELt5q>bQEkRi zRwKkcW2VU#tQsBmC53VJPlMExW5HHfyCxpPu8;O`yT1^EqQ9!_$G+y&ex$C9ukT>f zGOMH!W+!XpKRrm|fJbhN=Mf~qcI-F}wuKTAHH6x9YpqEktV~i+R2amWUEB&CKtNY z_p3_Lim{R8d9@m_qx zjhzL-j}wuzXCw(xo_+ zB&DKu3AZg(w^lc%24{sS;W9a)?2`KZn{ZB7LXR0_#zr@(!))>#F&gxjODu-rfbKok zDoasRs0WVeQDefXC|iQofKAD$@zUBmNUGwFL8Oiz6T(7Cnq-O#KwG(feLTD#dcYBFD#cjPR!Cx3#bRwE5E@Pf895eQT4t7D^GZWx z1iEC+sOSqoShG2bJ-Chtb@W&eF0*d{MvWvJ%7sY(|2ul52!2c)7SW8Y$3Ywgful)+ zP2sIU9LXg$&k8x1DDt;O!wuohQQ2AHFbI0?f(dfJB+&uCKsC}yJ%yl^!Ri%IPRaH+PR&8)u+pV=`AN2n_ob?w4gLE_oaXcSRIFRgF zJ4$b);!quuP3Z4}N}I2Qx+f=WWf^1lcxGi@T5CynA+nt8J<4j=DnDkjNjNl}kqIv( zzm(PSJKqTxvwl_0LXv3<%DR)z?UeJI{qZP*o?f@f5vUqEhc}|`(191+KQiRx)&>`grlG~acW?DuilZw(( z*xDepUacQZACntpLC8R*jRGht{sdU5Ou9RG0v0AybUBE!)G+sqIFn82(8|n4{>2tW zo2_La9#oho(HK;v8;y>3Y&2zdjRt|RY|%TUH5!xIY8VvSZR+H8uDZovQF}8z(wzFR z*Jr;mtQVsE3^`FvrD!3J0%}Xx%n8`ICKZUiO4co}FoFX`m8-&R^d}pHPF93ujp5dj z3Dc?b7vZqEo1@|8##^X@Xek&|supR+?4#dy`fx8jr;rJyESXEpL=W zl-k={JKAZL#9UNrV6I8K9>Ll@82Zg$R$Id((N%Mk zUT=q~PMd^ju9>8DVJsX;Efp!OmFOi6($=t!21c&m!eGt3q)D#XkoM|tXi1aP(vcHHV@Yc1M;fK*u`mm7nOHJ3ms$vl zEG-_GWTt8UDKkqPM$T!2VZGcks7K3Oa%oz8=`Rij6>&k>$cZRjsE$MBQoErt0@YBt zs*1B*)g~?S+bFh!SmlyK#Rki zl{1>d{34nJ7Gf&*k#xu!m7emo-;C&*Pr%*wTd&*;EW6WW0SoXOqTW!0_C6XgKZBpo zI{!h3-^Es^gEO#(#icjUp*ktd(0sou46$#((kV(EGG29lsh1ursw=xPwlChIjhXon!|^nT~{T)t}r; zQXOS0;CHoJ&rvR?`htm={x;=`1XZKWwML=KnT8n6bEY!4WUpk*Bgs&y*rRG8OQzY< z{~Y0^@i23&vRi%gpTk@p#QhshE+b!=I z6=1}2hzzMM6V9Wi9ywoZll&s4V{GSmM&XKb4%+0M;@e0c1(GKx43!j_hchE`gFsjg zbWN+J1*_WS!j=V6!Hj(~hPkFM4#$Gx!lHC)FB;Fn-w>YSBx^^KlI)f&Gk#-R)QiHF zC6QwX%fbsTy2B*)==ER_eG&7v67jM-7hpHsf?#m{7TnW{356JDFr$gB!A*sNM+b7v zt5|@$Yr_jZam(%3<4pO6Cb1wK;YDvPVeU%(Pd_~RgWIh2@j^*_f#h5I%eeGU!R_9o z!5_4wx59tI0sd7D*OdXDd)V#ruVWydRq7}Czcv4_A;u2=2@NmzFejl?=l>W%?>WG~ z%Dvlo&$Zr&5z|%#5BClE}8VMS?cvO#yMI##tOgFA^)Fn z12rC=Z)kq3@GFtA9sT2QV>ut5b!dJppQ0Xn^6lVHUa6oKnSt?ch5x(*{J5(WAkRfK zKUVlx9N-_jT0!-hf$?sIpN;@K`nP{n0m`$2OgOCYtq$<=P$0m`vlK^xKji@5e7yql znPB;9&40)NexHVy=P;UZjDUxH*_Hn%@?Zy?=a_;2%b5(Wv@{2z6I z-@jBr@C--uV}*Y~!|Nj&l1U5iQm?*bh`K|5u zrB(%{n_&`#HQj0r4>Ho8ehtqvCC!gD|NRc|YvKxuXG@wNEBq@C@XNL;D0#-D34s+p z7Y9n%)&INqD4@Cw@>A^qU(1dGk39QNy~_Ws`L{a2-+iwF;u)3Z#|nQ!!&~bm@)-p+ z+YF3%OL4?ZoX2KY{!R`5oCV&R{~8T%&A2-m+> z_&;}mANN@Wz%yUWj}`u39N^#8@DQ)G#|nQ53^+UfeW2mx*)%2$R`?nR_`rSzB+nBa z1^#mm@LxKhfOyWR`LX8T=Kx>)IR%x;e&hLbcIEHX@WxrQ1`XEy@6+(s_A~qQ3c}L; z$h-_({QXyl{IApS51A9=-I~7-4b+bQ;~JjlpPC;ld_==r=|BFMg33hy(+>H+qT#Lj z%bNd`DfaZgso^u}-?a|#@BWFR|44@RyVn8!p~DLP12gmRZl(Y49pLvLQGj310H2HV z((LMQ)#D0~=ewF8YyL|e;Jd!4pk6Wq0c*lxg@4-t{)sOspiKI= z0)~)X`HyROG>^2$n*SXR@GoijHEGZz%fHJ3{__8$01Gp~|EUA~Dh;2h{BJtI*J=39 z4E0}$25QH@zCTlh8|T{^#jx`4a}Mxb-3p@I0Mx%$_$C;>cKILI@V*T24?Dp3X?S_I zmI;S7|I-feclRnFYkKSVLX4B`=&#f8nflMqIKW572>-GJeA^h|=R?5k=-)C%_?-^$ zonwUmt^<767~!wTwWojo7~x|M@CP+~Ci#2B0sc7+Z^0bM4_HUsdq(%;!<^FL!`{fZfS>)Wg3sjtIp_fY z*k395O!9MF!&~jYlg}x5nAd5Kg`MK8L;kO5_`x*jk^S$S%k268(oqH2Y{}4C|Mxh+ zm;a4|=NZ@L#|r;N4R0;~tADGY&^@O;7IMT(4*By`>xqbP+e@p>hodJG_ z1N^%hK9l^f`iOo0;)KfBmm&WzI>7rhd?xy5!p}>dTHHipnTD6=>6&P;)?c*){Ql<^ zP$v5;>;V6zF~aY4fPYTITjj?}|1%EoCpG*lrn2+Z3jfhOd;UH4Ed`j#ep&4R|D`d) zZ*qWtVvO*I9pIlCBmCbvz<+&=@NYW6e`}2JxjuXTzog+ajb9c!z`r_1_^1Q?Psa%V zpac9bG<>G^bHV|B+_!~%GQt1c0e-fIzgwY6{y#4Hre3a`XV3qHhR?+R8VC4J4WFs~ z-0J|}HAeV9bAaDJM)-epfIm1!cyXmY|Bj3i{(1-aZVjKX)R(pXZgYUY{O=Utq73lc z9pLZM@aP`X9&7$b9N-fgK9m0bmIM4}#t8rK4)70Y_*H4tkJSHDud=VdzA?go+yVZ& zzgHP&YCo+G@Z}ml6aOA}fM2fRF+50nto8Sb1ALu^&!m3_9pDpVg#YN(_WbYC@cC)f zkF3Aj9N?cCBYcMg{HtSxKjZ)}PAbBeXQ2NZ4)Du0d>{k->kjZ;V}zgZQG5QM93y;@ z1H9)2MR+Fp{R0R1*&5!Hq5O|J!22}(xD4>$c7VTnjQPLg0Ds*W^S}CI_WUm#BmAun z@Wo?<-{t^cK1TQ+2lz!}gzs~J4`}%7GSr{<8hidVj}gAe0sf$d&oq82$+yq{r!OkP zw`ZXLfCGHpOA4?p1N@I2;J>fo_ho>;rof*5yT3cO{5Lzmzcfbp6Ati;zBjh~C(XB~ z{|ODBiT|H;fY1L2mH%fl@b51i;GfX&8T(HM_~ROWO@{nGdaZr=r+!}n7G{92a)1wL zczFkm35Qjm9&&)+e@X#m@<0By1N<-kQNi=h81rMze;X8p3kk-X6XAXEpHx65{!P5z z9)9@`6nrNC<98k4_x(`8|3dvF|F_crl?C?sZ+}&Ryy;GY$`>nq?+y0wk$+Zjnf#X# z2#6j39{S1H^55#WhwnVC=_Yd1W2HY<hnqX zr_GO1oyPC|8s5St@uXX&!1QR^W55}Ky$0! zYKHv(%>jPDcWnG$P@&3i<^NL}ewihIYyY!X!%w%Q8_bZuPpAL9hPUdE+1ZNzBNn_? z{{5>1{Bs)qRSRM(eA$im^}m0L%HNva`u#}_4>Kg~IjG?^8F`$iiO<3!3Gn@^RZiQ1-~3qfzrkNo<}*G1lJfGRqVkdo zzt2}vi2r;=g^czW7M2zl`+TLP6{RY9UG|QuRX4j`DU2@hSJIX<=g0SMlW+xOWI$XY zJ|f<~^BXLin3D@Euc&-lgSG^w@C!TpPOB8iH z;HqFg#2u*@N12ajt4c#U>Ncn_nYRv?I9pVjPPZuScp5ki`pjucRGPZD1C9zEzeya0 z4CK6*l{Y_$N0*b|GeP$R#2^2oz~F0HGkRtIUIi=ZMOxA)`7$mrblUA1IF9W{N&fwM zxOT^l;^;4ihi8?zMClHcc?Zh617+I*+7UMdIm+n=KOzsiD$Z|Pg1V{f=>t9Q-}!v^ z@vPtv-n;Z8gXa1o4Ok!E>-mVHBX5z|*vC8#J{aKvv2mvx;qwDSx$^=&$3R=BOVqvt z+(*VQ86=MxH$%*r=(!{?#Q4hL;o3bP3k=P7i)Z1Y$zfW4_qxQhSK_-XJ8;x{)1(=2 zlN5VaPo1&wUe9GRUWjMsB7Vm8o*Dc;>lV+f1kV1fyxueTJB#v71P<6`In9ubf=k4K zebLBso=S0G&%N1~4d5F2=8{0q6Rt@w?mNHi<;5qi8+Z}CgWk+}6Y%_AiSL?wXI$2o zHDkWPr}ri-9VCx_x&Ci@27|7i_wRIre_4?2aXsg=TvE1YUJX87N1nN)d`E8VJeubc zO&jKj+UNt76_CaGFL*_9bVKLS4Nq5Al({^6vnPwRBf)`wr50z~2?8ZrtlRRj}9V4IJfnwO1Tn z?h->2!OxROQ@tbb;4$}{rfj4OL3Zv$9NR$Q4u4UPu z9WSOGb9S_vKU9?%fBze-`xen{v?#8nBLKh4_dwlS`NEr4Lpf_zvs%{`y}Z2 z3(&#ue*g{N1r060{Um5;0S&#VV~=a%-oq~M0CB7UtuKNum{gJ%CyP%i)XQ;M8oy_v|?7Dj}4|V?2RhITmtp!Hq zPt`B3d)5lq_A6YMP0ABKgw59Ba*UjIKQ!(SN8IK3Tcp!Sb2=@}B)LWRZXLgcM!4-A z(YSjXQKSKFSU$!WjQIJu?pd=+Qa1516@aWsBV5b!o^uA4qj{notH&-M#4wLHbrPTc zm1PGkAD{eRrOVM_1}#jNufvRd7`DhJY>iD=qfMBxcG`?@pG~?WI?PPVGdj#n^GTbq zpV+|uLWddoj^U1OoDImM*pes5`_%l|+Y;dYPFj~Q|FfwN0;f|vG(kr=;L`1KC(Mn9)reMt;f_=67c zIofe3ZI>kU$o%0Gv88{XE|4`p>-P*4-md)nH9Tz_^J9hojE1-RNKe8c#wXJnhld^V z|A~h8Ni3=VtoeV#0sezA!vE9({&H=gSo5=f!v|)|Kc9wA+Bv!iR`_iW@cCne|BeHE z;TYlPLC(N}5%OO?M)(#7_`n$9|JDJ1`556Z1w-xVU!&oz{I-6VIl$Lycwb8Nf z=m4J>BmDn%fTv@Ck2OE*_dh$pAJp*rMi>*$OeG~HMKbBw=a}}t zsz~Ag0r?sbUl4yHmLG)Q`P=T>^1Nc>N$Dp$27kOb@S2`uI=}5ix8bMyAokbrC%WK2 zbHk681%DcR_uDS%Ilt6(VEB3ODZ`Jb=BZr0L+~5+Un_?4=|?}IeDl($Zt{!E`H`rK zJI?tm`2M6%R?i(FtTY+6QKwrgO5e|#(|b~;o!Og)+pp5pVGhGKex8bdAM-Ne*Tc{5 za*LegJk1}fIFAQB$raP_cN^ylmftFB--92r`?J-9-SF+6$;$1`o)#Diy5;Yxkkynd0pp(Yf~ZqTPqC1PxwKV2E*$rTz1SIN;0eJcMd}2<4hz zCqxO;zkk)?PZ9TNx7c`Q*5SE^ulvkmaa7KOv0n6C-yrz``2Gg>fjrmjfqtYP-j&@m zJnZec!zGI0`zZ5d1uC-tJkY~@CxW(lxd#u`yY?LF0}NrA7v}|&^K8Vg>&!Pp)gvac z($c`k+uQfX_ye!QXZr^Jh{rPl{$u!t``>UKIMd)dz0vp%Uk>!J3@l6kHG!ec;PFh9rGGs9>6PNE z?t1wCe_y=)P1NNtufqJ;J$W^trvmdYa&D~uW^v%Mx3)j3cux^4|UiSH)(~I0a^3{}ORv zE@I_*~;hCUWqcV+WG)$@pFiOeQUa6F+!# z8?f&G*WSB(cdJ{Ho%r0G?>qgm(cZPIR#mN9Yt^c?R@JUYKWDbgr5)VgAcC2X3SXuo zg0i2muN(UrD)VEEt7SyHFlpuf0p+fuoDjk2ab#T|VvJ8C{~6GT^aUVoCw#OD=%F8U zOuFzd5?xz0pN^6K2#$D{u{Z5s5AuS~XMt`&2*N-+bpMO+lVK3@llla%m zjwE(8qTMCgq(7wfpxw4)ag4NoW|Uxf-oD^?XV85cXg=Fn;Yy#_ybKgO4ByzlbYG}1rw(LcWf zaS}a!@I8&XUXCfYze5fo-&x^e~L>*qVs}l2q1Mf32Um)zTn)$lF=L~eh$He>>K+jh(r(D7%+ms+)79(1g5pNt% zoFNpP2i__LZ@mV8pnDvYt@jyXTyL1pZ;Dud?l|yYgy(Y+PomxP;(6@;utxiM-v2CHNd|t|ab9h?i3V z$8WJ7v10B!WVZG_i~d{D&RwYYbMzAeIBlNEF7d+Ws_#1kyD$e|#64m75z7Eo3^5+c z5x!?yCDM$zn5E%jHgHj98HkHAl!=84g>8I|W1T)c`bdaPA6ZNXP8AKOz(FKVp)VwX zcVpIfSj8a@vz((GK-|vH%^MGc9%SC1N3~6xmzAZgOI}?m@M~kfkTEb3a%!Fve3s&4 zT6cmd^3MS5GA*VA<7DJ%$@>~?$}!A;eOYX;z})`4ac*x>Wj^wduHfsCK64d^Y8*|d zJo_+2d2duZ_#FIDlh5B}-?i8rP51iUB4<}G=E*at|3gjob3Q!_{#Ip7N-pI~FXT)} z#(+1wF)qE&JrG02j10>d$dHyO8FP6e=np>Q-l?kGIh`%4q0_cs+r9vL?tJLG70`Rj zq5qcot~UIu^r=Vp=?Zw`QIzlRAK~jS5|SS|Z||Pr^!b0Zz_-R^J2BOyoLG2m!ISmZ z%AYJVCHDEyj-Hk3yvjV}#TDcmtF5hfrU-5Uym=<2ufM|7)&GX*>H+v-f2lIhKzn0 zHZZ%lLbL~NU|UR(wQ0GRQMXZtqdpM00diH-5XLSr#O8>={cqw9M9UpRvf3t}5? zSWu$ORo5e(h%pMmhwcG9NFMFMI7(d!^RKQ;a~yl0a|S1E+jh($=Q`?MnCq|xF@f(d zAuqOA*qKl2CCnFt9|`wa^v5{o{|-2bH{TZ!ChAqDleg76f!AOL^%t22y&3ID#dGC{ zTTZ$WAH%hl73G-En1?z~uVvv&ign==)CtaFZSuya+fGXQ`3(BkhwA#{(!V&>*uL$%eXp{s|EM2)O8v&s)&KIZ zul1*qKB(u*zZ!4r<9QSMcRQ}zaN%eaJLuzx1AiIs#e2S=hwGcTSbhTjI&o3I;QY!o z=3{*d^n@y;72{%g&i4xFj`Icc$QYTGB1oKK8u29MuYsmR?bqvKd#Q7=jon{S zwlijya1h7ylvz9t5&Lw)jc;a(w-Y8ko+&y;*n6_XzLCm%S>oWx8?mq%X~*q_kxSpt z5^s(w6{1B^-pLZ3iv8^@;a9TG;@&z7<|3EUzc<$OME;g9ruB;NrB1Y&EywN-Dt=7 zgr_sbE93W?j%SMZ?ekyB6i=rr0Q6#N!l}vPy;S9$$>RC6`Q4e~opk%bO!3|X<-%mq zGhwk1FJv^mhyF~ow`7VpCo0dQg%h0}nc~=_qb5FF??j%-%G;C0(aB0T+A~>s6BSRs z3giPfY2p>!ykeeoFhQI(&)=IMIxUoAeD{P&bO3K12}wtj#S00LK;qO$<$SXEcx2Oy z$s#Z+p(9yb9d#d)l^b737M(T)2`}2_3vt1wbS4XLqJn&T6OnK#QF%UDoK2jB;@%|t z!DMkT$?i=SN0aPG=}vkFbv}LFgYV#eOp<@BI5mb2j`zkAV$WED@sHiBwQH=O}sr~FY>%UD(h*R zct=SJSjGFw1p+`jPFh3&F9T+!C11Q?dB=1-UwB7!n_kHW))EfR5c@`reR>8+ECDI+ zk4o^)0P8O8m?3%;CmLu~9-kq)t@f4~;%S?5HBX$iWd-uYzC`6ho_HZq`8ZF!ljzt7 zFi8pL^ThF_q|Q9CceH{$&yP+xm?yeNCq0c)qgiV2b(4^@`?^Ueb#%=93p2!f$;w_- zm5d=fHm>sVe9%4TRD5-Ycz;qp z>VE!u#gBGRR`#F;lVR}nW+uEjL%fo?G=S_`V7BforF(|>ILrPvP?N2^gDSG^r)CI$ zcIkV#zd`B96Q^!)2yyiW4Wb?1r4rz_{Di#^j7|8%i$x^i~9I5=JDnJ%86uDm~8yf9sPZ@M@-9Rlk3 zbXL?oozUNzPLS_S=V)SFlNk6kNhuXKPLt0+H;Gdi@>8bLQy^KhvS*w)Zc*ODy#*Z% zSQ5^H9}<@C9VY?_=-|;2ia%MrKf>-ECpsk$y*SeTak6-Gr2Rs&lr>-r1!Vi4GJoGV zanNdiADm>h_auuBn}RBi+7k98i}!3v;F+_wM}_D~Oxl|)E+m$MHxG_h9!~}Vp!?mU zAKVAlye{eOvC!X@?y=(FSmn*J;`y=4@v-8CvFPQovCMsZ?0Y0x_HB}Q0knPHMJ~ztGJ^Py2F~oD92cO9bQf{;aTfx zONk55BQ|=WONZc@Tb5aWp~5?kdaiBfJ^;177w&w$6K%FLjrWY%?6;WTy$rqc(!C>) zHWIiPg}7T&DDIZF3EIpV_wLU`oGk3j4(z??#d_x)*1?OCoxx_ToBO1#dH4Q>->MI+ zk+$YkX=_Fws0X-tc`V22 zPpFf)>VG5Q-K!0wu`az1>(eo)Z!GFf291rwo}q;H2NB!tMIAbgT?CDFS~3E$X)I+> z8pD2qzA1A>byF0LG5uNe*$TarG z3^L_7_Ak)x3mg}wWGA$zpEk8CumN}597TS!v!vIC@o!G>^-l$#z~4}k^3;B5r^NVS z9rn{Hv$zgZZTV+_$6kx6y&LxYTcxepR098t^f`3Hp3n8FzD{>*>(ooF2|hpMi|TWj z5VC2z>gN=n1}tgwLS24KSqbZL!>85*y8`J)xq)<@+6VDn-HrV=KHy~yWtnnQ z;(;p2Tw4j&{^*-0`>l)|lP%X;BDz+?UQ8UaZ&%e-yb!R&7xjn~j`jUbd)vjOZ)V zWse_t6!3fW_hVd%`x#hgnc!DS6h+v}1KK%0w-@8xGrnc+qkZs0sPv+?5B4NHH^xb?MmlNZ;wS+bNgK3k*D%t_6`7uL~@RVcX9cwDUtbj`Ve<=CaM(&}ODe$oCb&!iuH`qswxKUJ<(JZb&KC!Z>hSr2q$KN4}~Hpmsywkr3qUkLL#arm&5 z1FAoia_`xsupE$b5ACAdlVjd0BIF*&P?sV47+z{M`?%+a@=YB>)t8qExu^C|?Hh3h zxtB{{w2sRjEv`VB8&3Nj@^B8p-$IE`wC4=)LtENeY3ow`)15!0o!r_d=~Uwbt5tyK zTjut({%h&!)}NQ2Y5hg1&KqLK&QjBk9i`?St)-NaN;YVFB>1HjenR-wp@;+b}>)Z%4CH)vB`DJ4Lw(ZY<8G3k8!^DS?&+8joF}$YulGWC%6l` z!BXf5cS2XV12*g>KIjf1orL`*Y@N14&ssX$L><)uAEZ8au>F3sD1whH(ryEJNLW}h z*vI1)*FDG2=x{@;NQ-If7@*n!5VYR+zDuN3Dzg`D#TA;hdt|7yq~Ap znH{h(UqRd5X`=XB+C1&35bcvBy{fiiFJumV1KV~AA9Nbf;6%_XZON)kYOXI~sNY`B z84urY$=SRtA%}aBYj*A|)#vV-DIz$SFG9zQ8+=C{#tr<{K%N3G`y|cdZ-1-l-RQWT zyP+R;!tcQ{eog;AJx29?vQ40`pv~>8F&$FT-H5==} zn{4Am%Xdpf%j2azzaQ1GE9iV_VJ+!8y^v#q`6S4gg3P^^W0_-3C7C^<1RHs-S&y3o zwppSpF$rx^;Ae)Ml6~#R-eSyyXHW-mLYc_)(~xI9tQYs}Z!dU+{Bauk7V{Z#3p|DR zg5}r_y{wMs&&Es+=xbWO7g@kHeS(-PX}gxX<0S5@b>wEwb$(ildSFS!Iz-rOrXY_Y zpD1>2<9hM4QRM-y7Xz+Wz^f+kEcX3x#~$f7h;ygpKa6Wp6Z9?eQWM5^^ZgY$gtztE z^K*u(pKG94^^ZjTtFgxvxY>(Kn@3VGH>5)DrRV<6k|yVl+Fb10O%MewvM*|0;=8*^1R=PJxoIgcp^=#zrXtj-nA zuJe$cIoNNEv`=*r9+Ro1a)`GPnQ1l62%Bc06$GMabCyZWW*0X&RHe z)HF8tA9hSU_TmWZv24U9%rhnRIU!?5Ltk#2KKelYY0{(o?B*mM4|sV?mdQ14Esp`|KQ$Z3-%tH z1Ei^*sUnCo4ffs-ozmYb+IuHj3n^c0=zH%0(N$Fe{;4&$pZhWN=>IX&*VF1P?P>j+ z(*9O+NiXz=3(qmmEz#%R=`8VNVEyygqP@QvF-g!_?uO2%%NDs_#5zZxr>Vn~!|xcm zc2jkjBB{5Ek}X;+7WMOVIVYq+CLsm^?N%@^5ay*;;X@w*m+w^j1mE|sfgXeYz-}Vt zmcIyc1MBM^_-3G+y=!$ieJPlWaz`K*3G-8x2|7iQDhE5w$YVtu3(Cv(V$I95Exc1y zUfKODdBrv)udFpYyFLQ`r-C+{L7Tqpw=C@uY~YpMIp7tX zAz`4;Pxhb;X>$j7W!I455F9fet8hE81?IG{l&>k1sBN&>zh1W=HmFL}fjJiRBnl^C%vlEal7={Mm~ch+ zN6ukG^vNFTll{oiuh6GivQPGiKBZ`Vdev-4pHha=Csj|3IY&CwxmundG8^N8_9_#! zxtRC=O}odrIE<-4d_CfN84Hg}Xn3w6FZiC*n2ReD~wX&1*AUD?GZ@J04zZv(Prak*zLg_Ox&IbIt2lF=bD2UnR zdy{3)ejnBWuY(?x1jsCl?Su`sgsFfH8m%vbJm*?0XN34^Hr{jIp})5r`bH0IWpaEm z&vxGI^j*gJ5IH90ME`ZW`dV=o2-g-ph-GU!qmIA*J?Nm5i5n3Vpf~r;h?klyt zGj+`HT+DfxbHu=NZB)I`v{=PAX-`S8N?A;LteFG&&>NZVHp3nmpLF^TPbV zc2KstcUJh=R-Gp@g}qPb3-UrU+ISqi5Q}cCsM`%2OAhMhnG7D(O zVx6r7JWBnC_;mkpp`?*4*dpdYm)HVb;y2JGE`U~Wmdue<=oG?aZ`1SQyp{HSQ%vo| zJ?HnF$5Ic_F8U$P!l6#Xd=c<(UOasG$or+?|8U9h;Un*thJW*&!-tQ&UmE@omku93 z@_uRfH!mALeB>Pt{1wZ}y08~%qX&G>v4)(L^pvf|=d8F#eg78dH|G2M@m>)d--z>G zr(x0)&zu4b_?c9?j(-N#|Ngv68N|6Pwk#^AZ3McfC}fOFCFHzZuR%ZMIcZ9lLH?(x z_Z?sKA7xyn^e0hHLDo`#^-9?uK0hrB@-;e*bBa7)47!!{88F^93}bdE|7+@d=;C1* zT3R#=>dpE%>hfuz%q=hJwusr>ufu+2j)rX-bjJGB{-WL5oV0lbZGoz912nQvz;+sH zmzGC=4?C}%KVrXE=UTmO#IfE!eLSN7M$1(NJV5-gjTd2O;oL0e3(P+b;1YHw#NwHy zZI1Y)ep)jM=Xcq7Hq-bcIe(Qt4zX9cu*G!kTI1~Utij(Y&frdS*-v(iJU-VmMFdxv zO+Tp}*)n$*%3z(h+%Y2|HxKKmN}k_`I^O!u_9xkI;>_;x1l)j+{+1}f1LC&-V(>5+4z{9Sq&q!^ zUeRcv7xa_4RFqi9iY`e5@DtPk5Bq?3??~vaqoZ(z`1BvcMod1H@GKLh?}4xr;P~@%DhOcH?ia zMagY0Q|cFjzN$3(ng)FY=gc*pvs_=;XPI2MCV6*;a?>v}a@N_$*+!FB;Gg@eq;W1& z!bZ~LVdPi7l?d8NDkM+P4oljWH0Dw1ly&yNUf7%Y_se>(z1j#mv(f&>{Pg>KMduu4 zn{6DQc@Cm35A->w{|yU#&{o)$ZLlvV!j6*!ypM+M>N@zKEg>H?$L({-fQyh{(w+eR zx6fx=%+SFh7c{#W_r8&@cE4_EZ!=rkbFklK9`?H^rt8OXAKSdqm23Raw|k*SH{Iq8 z-jm$6KNEVi?pHPX&ZK{Jim0Z~hkKJ5BAb`eNy4B`wmn&ANin2i>$`PX&&dZfGyt$M)VT{UI4g7#~gFF!M>j z2<#^Gx3Rq!6Jg8L+DlvWH#C3PGiWbu>9jS|=NHS~97LPBuS8u7M%tX&ZrYvccVNBr zwf3Uztk-_n)b25~{g8P=Uk}=l{*4wHGj64C_y+3%<+N!3A=>ckDNdh07JduX$LOm* z2J9#Of*G)*&_AvBaVP91dLN%gTj;yw-k6K9w{mQZeeFVD87mR5uk0hs(ZvNHQ%?Y4C`a-uM_Fz!ICTv>KeoZI(3HwcueW0xNVx6HNtqf^gW0OW&unuB>IahG~ z<^}Kc-k_ez3SZhX_|Q(mpVpZEm~~ z`%mzNbwgg$7uF5gjacz0UzqC48-Nq$BW=RYLEKV~(PqYb!V_hac~7fhI=4K_;EcbX3U>ki1QC6HZ8}u<@T^1m z44b#y4}dwc2XSFc8_f6BUoq<4-`9(-|9lwxH7c+!=9!O>JB(?dyt-r=k^8wN0deI> zgG`1^8uXy<;ht#4Ud8JfFM~L0=xCt1jkHNPKT;WQ5Wtgr6R$!}lMk*!w^idF zl70Pcps}Y^`OwWh9gyEL?%_$K-`+A8HeCA!jNzej@zWLmfb(zh{t*59lz$Zo?OxFI zY|6iigpz7aUVA~)Y0|&1(yZU?e2MzPh1O)BpY?$@sISwHOWeM?W>#@$tFz>v#yh(L zkhwwdm4CbF>YNB)O*43~f_Tp8tI5LNl{YN!_P$|mzq(R%O+vj6TvxCc(LX~3AAr1Z zqyK7*n!1<4jXhnoXLDay2Xws5e=~1vLEAImGH*N$nQleQj4bnW^cy}v=_3N3IR^4x z+v_#K)Y7%Z6eyB;UyI7SP0b7WlFR<2iqu4Z#r%@q?}Of9bE1qe?m_7R-Vh%V+9NU; zOa=C{oWAWRDbECSPp(r8_Osag!vLS{_y>&Lps)c;%1Y3YPD8c84fX})W}>WvxWxP~ zef*%YUhqo_=m|L2(ybC-Mx*{<*Dn*h1g3qA<7-+-GQ#6@A>QEq?pXkY&(A!Qx- zX>ZTN;N6*gKvg{S{&P+6mqwyvwbLK0n|e229E+q(0`5Z%T8l28|di@ z#{MeCo-*tLWSp1lI*gAVKSCMU1KbTr#~$KZ?W}cUyh#n>CN81=0r@FQvBvovd@u`V zQIH-lKY;a-f$uNt^sVteX?*}MNn3ViE_^`tgP8mJo5$d+1C<7PfZLyq4HR)7V($%i z%6*85(zg=chuCX{9~?Ljg62pk%y$R+&NZ<@zxD{MWufC(qxKK~68nc0_&)v-yrpD2 zOT1=9jZxYd##ImIKO@ihke7Sv$vfOvpAET6-XR~Y8HYXflv&!IdVf85bh(gr6(c@j zQB~`iYp4hF8@6K%kR^VM9c76sUocNVzUXqK`+9ZX*#-8MV=QG5<_hGYObVA%_m%7A zDvQ)|$ANF+Yz1h+fjyg;LxN8N|BNko)slRy|D@=`&Kay>Go_!wjXH#9vnpG2aF2S7 z`!(ae_X7^!nNao&_~<#{P><{IpM)IQ?hL-XQ?xs_6&>qq247h2I(81}@CUSeFxLIH zU44}%C6RErU-L5N4=?t&>HFF+Z*2U?E~@>24O*0YOEC{1ZY4F>KNEcV6nSKRNq;}& zQ9Yg^hq^h3KMDNb4qk?g>M3fOdkgUR8F-ZC)cx>w*x|6(67y3(=5_N1?9)V@fQt~WgXFiAjjPv~E*3mwB4h80UT@Jkp zIds`#hpmaRkg3pZ*q-sZ{)&o{-iCPdWTd?DV(f+Ikzvk(s$A>9n5Z#$;r*-!!1I2L zje>oZ6HTd!UeZ{U9PtA`A(>&IKchayJZ11d`C9MB{@1kJUhEIR7zYT8^&00?oS!b| zRQVq8^!H!KoGSYa9qCMk>JJ4yboEZXGv`Cd)Bk+f*~K|G$0Wv)W*N(L)?&dq5fkMZ z5$6&`S8oN*iLj`9E=iBvZ+U+!=oo$!eZS?@^Vn|*9C{ysUlaWGTkyC)#H%Vl4|mSL zh&kWSz2%VY=O1u(eFph*1Z`Ap9%9@f@If!+U?2M9$J|f}9-t2Uf_YCy3GTU0a^vrL z$Y}pW#M|C3x)MOMo!|MHEfwQ?5a-cQh8yL#)J+Vsn=yxSyx=QP-aM3X2=LV54d^biO1kp7dF5{?sP zD%Yiy?~kC(I!`{k3_5_3C$T=FK0tYFJWD1PFOmoUskH$6q>}?-U0c<~$%n-6#oK{% zwAuT4|7_ykA4liufX>t34Bcg=2XAH;y6023xh2ex&q`Vsc&aTPE4~y#y=hA9GKmV+6kY z0Dg0qidmrJ_FnLx%9o6h!CswPM3DSPew1_44C9;xU1vL|L~lE z*T13Cx_(Z;#akd(U{@pWJc{{;@n7BwHC88j-XX1DZ5`vodJ%e{zOGdD`d8PK77veh z)4mk#?wl>EvE?pw&J)}E8F<(a+BLQ}p00kiHJWzS_BNxvevNjCe|eslMms%!0^REL z`k5tTNIgAt{+4l#fUzgf$aw{8c4ItyvqfzDk7o~L80newi-P$@(lca@y1t8?XN)vW zIm8%=-cbjP zm(8?AH^UCCthBTzK4)&vfDIaUiFVov<^iA2Sg=n(leKcql@pdhXQ1~`2c`^~iTsqa zMjM?vma0vwQ(JR|Wh~cYv_GpdR9mkJ-KULs!o80qbJ7CSmJM4+f`Dt5*H5)vMzISHgJge={ z#WTemJ^yg_3H=fLREc@L5BNL}eCERL$+^85I9dbSCvBilA^s&D-xgy0+vgP`NE`>C zr*aNtpNPK|nOq}Vu)`vPry&oyo}~U- z1O1hKbAJQ!6}DmbH$?EhZ@>chm(v#G!j)`<~z zVDw3+G0L~0XzX%Gwnfqy=}Vs{*ygj?C-FPb5A{1$|Kr@neG=*(lb#Cfx4_(@$n%7( zeLLZU@@cr!_etnDe##;y^teeIZh%nEtru)_XoPM@=T3gW?Li;b^=XLF}l z`xw92fwuRZbapLTAdcl87ShI?bvmK_bcJSXL3zSe0D~~+yf*n*rAg&w1^7@vKiogk z2l)qD?K18oq2GqK$zH(VdX~OK*pUZ46R8LDHfcoHKlJAw&?3`y8<0N7sA;MVQ7@za z)yq79@mPrKTe$ASbuX@aa7kGQ9_vOwbU8;l@q$k7#QP<<7UNoki{-0u*>LguPt+5c zw^Iqzi*A3Phxa<{PQ)VUu=V#WKL^)rT(fZT{2Vx@?FG29YLX;F{AR?G8plVEU8SDRc8Ywb>_5LR$UX}A&*a|@ zZLg31*D2J!KiXgDvt0t;N|bowJ-(?Jy2p1F<^7GIamZHA^#U?@#hS;&#B-qWMFmbD_E4Rum)}~P8v52E_lC@SZL0j%qF$d! zR_hk1hiRd|@axFu;>f>7dQw1pQbu^#hk3uL0bjepyQD{DotkzWd=*OD6-t}Kxs!A! zpoi;wm_qq5{}LYPZ`oz6Cu7!GtJTT58+aj)x^tZ+A~|7s1U&=)y_-bgyt|b8-XGB) zlQb^tuF71k|0S8DCpGH+(U|pUZ9zNd$arII%sB5!`iF0oa!`%O3-8DJO0YElXEZGO zam8IK?eV@B{k7gDO7tAqeC^s6Kz?Iy9Y6TH;x zYFXyEsXK#XKv=9-!eqYL$cHry^LcEs^Xc-7bU^(@j@ek}w#@7diBp~fuEWbLQFV}r zGTHh#TBJkHvNShge0IAV z&BA`^T_dUUj_xBac8x^*4D^FT*n86^=ZeH5$k09GH) zn{@(K4Pdna7T?taRvTbd0M@g>Y30@VPi7@6C-n1#UN@^}v{Sa}u_L^{6?Fyw=zOUK zdO`LdA3ce2+vf*vUNxuoiRARQ8q`-+fqhrwtJ)~5&vA|$`C91*fae^sqx3N9v*Meq zYMaH8-N2>GguOZ_hwsh4yB2-;2;cbp3Hnf-{tf*1O9Qevqt-#at-R_J}Tl`m(lupP0@X2KiMa&3nUD$oEH&q zt=9t^eRNt)RKI&rx3SM1m`ja)R_7g2sK-|7an>>WuK5zaj=smN@9!e#=RYT|W7hY~ z|DyUN4MT5TA~r%!RQL9`F54wK8aa0P%YW`R1jkGa1Y&%D+o9=yjQNr=`eE9h!`RSW8qKHB76JPS^#kbia{dm{zOFZ5 ze$(T?dNDt8jSBuLyc>V1?>q&b^yfNZzfk%pJFurJm$3#it{L+!&kAPRw-E1cMLbd} zVv$r?t?K*TXbaXGIFA?m@N}IH>vX2ev?ZD@f_89T&4qqv8!2X;1Kg>Qhn<)cl7L_A zHNpY?<8qj5#XwPOCE!b?Q1k zWcQ!tTk3Z|mNLDMGi_Jj4VNjq?9ja<<#}+_f&g`rSnD|I_z&YO zu7ARJo-yVnIh}}+#~h^F;WLu52FGd|MI6^MN_N@Abl` z_n!d{&t<6l7&(VJQ@nCL2tJt2JpNnY*Rf#U%szBK>=_&VKRT4L@1>{qU%uZRD7x1F zGI^y1x`7{S_vm^aMm_zQbI%n1Kz{3Fw^k3=a%EaQkbSdS;9DncePB-OE0=UM9&2oS z#5!GH2M!h+N!k81a6&nM40x#oUaEi>7-QOXylj(r*}0#z5`aE(1-|S@$CMYlM}ar` z%T6A$Af6lhJzbUwefP|KWuO*Z$|AUsV2WS+UnFX2T{KOagBmf{xdLdXv!Zzs0+M!?=t_ zUF5H6z$Mc@8iDh+aLznq_fG?Ni%i%9QY%W@@V5-#V<)Xn1*~S1sV^HekqaKmHHqLF z&{&mK(Eb^8DC*xn?0c{wFLldvmbU#SPi`P50q03EAKI8(!~L_Ou!?n{4LA$31pFVg zL9bp&T@d+ffOj5na<%(KvTmiX4}OR$&(r{HXF=MjjqP%>U4X~DQvs_Uusp02un3cX z2{Tc`vPxJsz(PBMtfvz17uFiuhJ3PZfC(GG@Y{yE^|nRtwX$Y8eekdR3VxMOf4%YG zulSvZUt-T{$}fH@&ug+_&+6t$zxXuuG24M(Z|wQB8+JO?o|Dq2!1rEnqwZ!p!gwKd z53B9KFN?qTtKALxaZS(CR-omXLSzjbJYD)p!*|s|7hoRDQ)7D$E42e z1)LU~XU2U3zcgD95I@+nIJafz8>KsTzFxX>=WC^hz7Ws{q3`2tq;i~%BLCp%34PwAn@N_~fRObqPF zHo>--)K|9an?G@y4wWv%b1nAWHep`^`IYAh(w4X;Px!DWCYS{s^fRP+zV|?}2lK7~ zeDWk^k{`0L3_9T{jIYWk;r*4!Ghn|ZbjKraf>${|5k|aqm;#w%w3~XNFQh`Qz6F~m zWtiuFrw=%N0_%!*b4{sO`o2t4uhB1milX#q<`P|g` zJIfMT2jt#MZqS0mlF|0af68+=N{G+sdF}JnKbJNL9oNzHpVGm(jOWS<*riiW%u{yt z<)EKypcnYewiC1Q%>^I&GWFVbPA6kUCsl&hh-_h zutum}lq}w@$GE;QPQ1J1-(1JYUw`}a%wvZ^gT0oiM{+KH=ZTli*0#-4gl~&nyM^hI z@=3>qQMYsmbqz*cj&mAg#H2l^6m}r^d=nhbM-GFBqt`v~W6HRGx74Fx_sdqxnQ%T0 z?QrA=u93(Gp*$Wn&vBeh7fLHo)A)?J6?z(A>1{|r8wy~@f_~??iuE$qm^miV{>v-< zW2buD#S5*8ZBA3>Z@NA0%hns~Sr>+hwdNeclYOTingn=^w^zhQ0bc^+O0seGL8v{m z)v}pmk#8*CBfl7@=HG$&EtIcB%?G=N$PUP>->X z@Y9*`&RG7xpnRw^%;~5f;HSNo6`0G7}eM|hiW9Kr;o=*Iw{OZJe%38+* zPb_OOD~ULtINaB$`pOZ{XT*zZki2K`tp#J=>Ou1E?2XJ@HAvnm{>Z%F93=1S{~4Kg z<{)`j{4O%D19@-$YcE(v?B4Uey-)1JjboA+C+)e}pi|4!Mctr9y^p(vh~NW9sj^(= zO@aLuW2)!FWE0BQQ{TRfJTp&>Z7jRVThxhXE5<1+*(+_6-DAS#27?bNhK_7cD=d`npi5`#SX>n^9#^H(HqVAF> zmU)n-w=o(H+Y$?ovos8+6ZckJ@!Ap(Mom{3U){LR!S!WfWF;Eff%{(I#Rx+IPV{l> zj)T{le>SuO_c^%Y!RUlch&A>tN#S-Vqn}t-g=ZZGWi00i(#4Lkdy6X3&tCRbqYI{Y zn=qb+{&(P>Wdz!ym(3otw@5)B-@;`q><)X&Nm!anCX>+F!yyJR0=^RxkTzsMpVW z4gKxV>J$GGuD2{{Z;>1Q$w9x2Wh?RgmZ6^=xM#gR+TYW*y+y41^k{F9A9S|MKxa&^ zwRwviNb^Ock7;y&1NdW_)}Q0J58=SNx5xondyDjD><6BA8ECKu_bemk>SY0UZTm7Y zLgkkp@DAUbMyYKqvw|1EuQ>*OWgB;l@)jv5w+ndE>vJNH-k!rF_7-&lmWOm_Xpa}q zRs$_&;htq2=-Vz_dR|91o^k2V3UH^lu@dP%!#g+dt-oX2{J@L;+zpuey#syL@0rgH z7*@j3@Y#vB=_9>>qOsoKmA=mJo8}34}UCfEpaZmUCc=RA6_pLT9u>XY@cvrp|Z?dQ}eIyR5s^xCiKt)V1jgc?Plhj{fhQ z?1b(MalaRrjC~10Pt3Zk>WK7@cjGLxfGxf4l5IlUt0S?${dRHe$5JojIdJrEtG?@p zSE#xl0yMNW$v}G#>cHA$U^>U1=Ue>_^N_A9_FG0_zkVwAxTayRYdZG4PQc#R4D8pR zh_fa~hW6`UkUk<)E^)#0y(_Wbs=ps+Na?-KA=IZNKcx}Xy4ZYTG1Js^TTQ(NZp zJlK1%hW`NjJ*Iq9RNssDAL#oyTg`?ue$Aot@!rCoj}p1xOhMn(*fxiDR`Vr%ht`ie z)fhC!?y2htp7ZO4j;ZQ`>Yg3iBoQwg>;WDJyu;qCGQ<(e^o`Wx)G{^W5YuQexAWY! za~4ZGzlrrA_Sh+i%`C!oA1;3)_NSv?zd`J%EI&6~p86)^_&-2ADbI56alww$T8_Ok ziVxqx4EEfq#U($0GE;%4MM%3r-R~N_S3Os@9OXX8d;MJ5D~VXcF)rC+F4?BV@;DIN z$bJ6$UP7;Su51wBwDqGNwmH_>vie?p(8xaYVK2`rkK8|)ntQbs`vekACCnrDn~xVV zE{HLVJ(-d5^v~vn_wK(AJhPpj!>)z>d=YI`_nPy(1nhMMTsPWFctP#lW_ABy_#9jp z&LiO2zvq5b?t{HZ#w4FMYu}!=m?RG=pe4C?@EgG4L~ZZjJorqFdj}EIX^f>0m8nOW z7~iY)TNp#XI8>)ekAntHu-)o+)goh&51X;41@Auuz36EcuL^eJwi{^Y zG`E8<_L3JtUyKWVX}d+V2cHwZ;nK?#&|d)bl39U$RDgLE^pdH6?+)~$X!HU*pZpf5 z0(uE@&1Ol#nH%G=7L5Gf9mj)b7k>shb5ZV>ns6itdnU&ypwX0iCcq@{oVupxSr>jw zc?n|zjr)x|d_7o`#Y1-xK73Sv+8-yEx3W6gCOc=FPhGRVHgb01(m1iuE(BWcGvH}1a0{^lgP-;H$8i@eeM7JC{X z3oVwCh2zDsp4RZUfC-!a4C-t)Tz%Mk!*%XLTw7Aw_Ln8^+W!{fpZc2>UoUvvitk1! z_|C!XWG`&*=Jqtu2kpI-b^6{G%9LJ=`8m|Xn5TP@hkSAgJVL(*+X(!_zH7$$PwF$< zA$IUQC>6hawjMUM&x1X-1-z>iw{%^>_}2kv{JRC;WIYC%YAn-jPCvo(DtJ}}XufF@SLrrG*>X<6%QrRA-W zam(N4f zB|s+{;k#C0YQG=nWmIBc9M362d=KPYnv4nXk5Xaryw}g5A2JS7KTC#f&P*}~n!mtz z3TQ_qj--wCxcoMT5bD|Tmqx0((oV$G@EaJ^l{l}GPqzLw_6F=6`dbKFcA9-W=Q0+b z_(2amPrms(h-ZZj@gHGp^-^yFKD?0IUOXShvl)0}OhyaZL%h(Ak2P$&7iHM@Ud#=o zr)?HJ}O32`r~z?sj9`9F~b~+aqk|1O0keM%@z3Ue)+7P%NKrD&*ck0tLO6Z*>NN2@J9G; zT7HgCpo2E?y#PJ-hOtFhlXbasLDM*ADdw4cHzOTuGU9ExXVN{5GK^JL#v@*u=hZDo zpK*4b0v_muzeU2*VxPH|GsZsmAny6!;TvFHx!(%oX0keAKUc?&?R4O5;bFH2=SDq^ zGI84j-|LrY58|RC+Cw|;2WYRv-3O#dx>sPOye6d1ozmoD{;T)fA3`}%gmK4@&Kj0e98pN~-G=yBj~3&s-k9qdHE zc42(Grl{XL@LOz0Y=A@Feik^jL4F}X@MsXeJSzZM*SJJNoL20P87y z4~X{cAll03G(1BuvpYcJl6LZ(!S3gNqtw`a(i_(r>57nh zt&~U2KKRJdR?w&>Ptk7qeIr$#rXfa9m8YHX5mBCYqK}tSfp5UF<}eNhKJ<`{))~AX z-_KwS%p`ns;|jjHk%8}MlwjT>{8V{9PimWWG+^#HUfMezGJjOdT!~ZdyB${WW1<85 ziSSL1^Y|u*xMhgWuyw#P>MJueKz$Z?s>KH`s2IXN&Z)Zb6^*Gs8%S zX(kcu#Xh5+QIHvbaJA3*(sAH^2XIF`CE6#pJ&by}zlrsF zP?sBZ*P!lS&T;w_`=qv4L1V|!z87|gclV&4J^1!>J?=Rs9V7aG!dT6k5wE^LKixUY zv?FUQwzfpOO~!2M<8}h^mfe^;InIdPN#L7>k$N_KM^X;q47k^U3qN#+0M-BszDt9?O4{eS8mf-X z?nGwwXdEByD|8zuF>@w@t};Di1F^eo1OQ3q=VO<4OMJz0fu=|xQSyku|R z8}yqXo;uT%-q%V$4`Qz=hY;HWo1Yq6;3i)H_C(av1;2ZyWn$m0t^4-hYe|tYIBd7- zyVurVc)tsMcUgG0K75KOpEc^WQm$cm&vPBAk5E5h%tI<@&;P~zC%eZf(znf+fB@p5 z>Dx|4JhZ;1R77eUV^?d;sy-=D2jifr&#G_{=L@(s8eHSIbpoz(;J(bK>m)|MwFz^H z9&1|*p4auoO=#;-}oKQGVrON zy4C2i;zY!TRUt;m1-r^rQ`>&V^&iIjACF`Fn`o>-EaYzNw_FYxLA|0EF+yxVV$ez! za!tx_$~+Ej$nLiw#MfZfNSceoHwo3f8XyooOXcc9)e%08S{cUe>b1Yz}qi_ z7gL}Yf==z9VSH8JgesG=`uk_IUp(K6@-o^7p~vhDwdT;jGsJa^sWHdx0>lDCHOp}1uiG8pkAigL4NG`^CD#p1|8|Oqh&Z%;*bt3c=b)0wY-whj5D%P*P zz_ZO_ZCkj&S<<)0Q>=d<1moK-*X9`CJk;|uw9EKS#4MZ_ln#CN7~(={MEagH(G zq=8=Wb5?rRWY}YmSVhj?%l06aN}s=o%Sx01U7h2cLEM}1m-r`bv0bOpzg*l;G}%Gg zu;XfD62d#$1br!ZE)l#z-4TDS_?wQrjNP-2E(=7z^I*&z+rAO-%e;sM10Cc5=L^vm z7us?heL+9^*r#0UZ}(UImki0P&@XqdLD|Y}IRWA(fbtl(LgL2_{mVg{h^AwZPpCT$ zrDsr%k-mEXi{F)UqCZU2aTL!dnTq|WJy?VA3|4hbu73BW=6>iC<)TE|ozOvS0^uq4+7Ie#A8)T=9$%KxL`5*ecUAH@#p>IUnosQjxbqe6#1099(pj*=& zqxHt0?KJs1q0hv!J8{fN6CS|Hyi35o5Zgbgf5S$#6{Q?$#=NcKMBUdNJzqK!#3#gI zEyfG`1PaNo#7U;fbgl(y`W!)cn?ZBjchoD>ReCq>u|YldXF=DmUMD``_+xDk`b;^; z_-E2IbhccN#uwS(3DUO!Z9DM22*g!=V!^m83F2KP`S@@B7G;s-f$VM>C(b?~#U{O?&3G%uQr&W8(E;ACO}V({8l{s`x@jP`{}s)*vZbZ;^mf4 z)p%Rt8M;`|4O-H1NnMls-bwrOwmAZ%*+XVU?sp=eq=QeM#(Ddbz;n-_&v_QRDi5J6 zu0)@9C7#+}`icF30vyx;2FJvy(P}f`{uR;>S|;o!e8;xZKpJFAS|aqflfw50i@-Ob zoxwctSu^3G-)_L0_>uiUvt?4>Yj_U87P1g9wgU#!S|GRB4=ZGA4(3un?k^z^=g5!C zan?J=;1kd!{fxFRaLz4!EBrRw8GI}0%owbvc_twAW$=H*o`p5oOYo}M)`#yVRiDGW zxd<|qWwXq?_s_!|T8laKMaWk8T#ocwl8^iybb?&Wol~JRP`1`${-kUL{vy7;bT|6O z_3Z`ASj<<+Qa||wc>Nf%><@P$4mGjN*MhwemB0(zreOZ;MxQ*NJ$6z7e%M!qXY4|j zb#v^rXRe27?@oujB98biXX5s$i`0L^-;@uy=7Ux$u!bpz4L|g4`B1FEO`C4bYIx|O zO?6FKH?5kM)wFFxUDi!or)6#OJc1jfc-F6~+bZu?;MTK#wY=ZdRJ*!v6K=({td$L$ z*EiKQst@ZouUk^LZbeyfM*-KtGl>uR@p)@@#wwQ2K)4GoP=b*p530*&*m z&k_xro3g~+>pc%OG_K2Ptb1rJYVb6yzcrM$0#(&VyeZ%O&_n3{mfA*7?TWQ^vEB_V zwA8bqZmnm19q_vWRT^swy+T`}-$7LTulX%+Dkxanuo|eYYitCHmp7FVfg6a7FVh0R zDO_8(esz;u1N3DI|DU}72Lpd$7`VSph&o&k;aZLB0bFie9$ag1J&5bJ?+a0dYay;h zxNgU_7}pY9ci^hT^>cViyK%jR>zBCx71s$|Z{zwmT))6I(k_GzR{;5=e+ft*f$KV4 zV{qMrdjI1IL$0#*s~Q_TtFj!k3k&n}XBB2aa6;BKtj}tkIcv_$;*ym)Su5ApLY{Ad zum)FW73byW6=gZxO-&m%-8y4NtqLG-bwk7IwRM{sHaD)U%Ujv7Zbnl>!`hYZTF?3! zYWWqjXFpW9YF6EfhgQv;z2c!cvu3U;ELyck~&MBU`s;GAMih_cbs{lIGy~T^~ zS)%r3)0Xu)I!3VHMgB~WEEA?jCz~cFWeThXs^Z$i;Rban{{FxqE zx>%M-gr!*hO=8(uxW7?LI1b>7b}wo)7*CGer~IAm2T4y|_w?9j#_hKsNIl5<2zQU3 z*MytJhWvPR;CfVh{~#305L~@&A-H2@8#=YT0b~s29ik0vdyiIb650?d_n@IIG1~4x znRK=pzs1IK)luc}o_%f7@;)dF=y?>0H-7YvKZSpz%M)iv=5u><){H&6zQi}d$$z#p?afuoV>AD%a@P) zunbUSe_k-c$7}ZSc#O1DS{mQ;cOx#pmUfB>ap;%%$6_q_)7!|j8)Kvu$4FZoBdsPz zT2qWPZ;Z5qS{nI+Kepw?7-?_DNPAC9Gt$WU7-<5|YyPAx!e7>5*V2sjIqD1x675qTjLnjoLdSK8m$89X|gq*3t-%Kc>}aX~uDA($X9smE`DU&5egof!@Qb+-k1W4Od%uV8W6W1C3{n2=A>N-K;(d~h z6>EA{jP^~_-apPvQST{Z7i;g&bB>6KN4u28O8|+fAZPD_jV=OgNhLADpSp#+Je1JTrm2;zyp>pwXiu}aO zBu(J85HIoa9!QsKgi0-MKIO|0?IG-~TK)%zfK7ZpujMVqeKbD#{!Q)uD|{a@CaRuy zc98cRj|3R#`7_F_bS+KC74uEg(z2KtKc+cjq|pJ$pRp|BV zp!WVCaWn{B&cbWhqUFy4n$znYY8Uk zYVYMbUb5qi|L3{xzoTgN+D%-C7v@(l3)vg18*8~NuWKwQ z*y7pbX)5=uuWj76;Ev_4Io0P#XVSX#d)};Z~!yefhR^D;m~D!q(D;4JjWD)*HEOk+JJv7E%!)(ZX7F z=RKOic0n9~jSZ`6n`-k`ZfYu+Gq9lrMb&q%SOe>Dc+e^eC8(x3F4y{1^#uimMq72& z$~%@9xL~Ys*EYJE8f!gGo2phWz=#&ON<#K)rYum~GrPJPw)h1e{KAzl(uqZVJA38Y zhV^v|w#3K~qj?4StLsQeG~y4p%&b+L*KIIn)*DbzV4&8*St~Ys)~+gRf>nOS=BBzZ zN){9pELiSd4D#L#he0Hw>sEPco9Y&X8y^#PL5YN2p*k6=(E62io1%tnc#sMUBqWWD zmeYf=q;^yNSAtaxDv}VsS_fxUFZOJy3p07)hRvJYw{2c8eGRffUy_Ji1+zB5Ea!@% zq=C4NEoJ5x4mrkgDIpHT{Fo5uXaXzT^LWn1K{fjuf1 z2s2;8ygR1IEY!fNZ)1Rq9-CPb*z!8f6Er{u>(z&I3>#?K>eY>PtH}h>f?Wq1&JhEs zo+*UP64}(n4GkLx04&hDEnf}?mOk+`)~;Xa9sn*h@u;uA1i>!9k0ESj1?umi#(g87u3ipQCW&To8Ua% zyt2udN0*baIS*oPZNtNNZzzK>*-{rKAY*%ZA78@EiZxBekuVz6#hy(~Rk2hO&Tz9_ zg#|9xT4ZspB%ixH&{^oNty+GYYw4B+a+2emUR1ptsgTQeZLVGGdB{`OxWF*ZgS0qC zgLNdu6pV9fH*NB)hM-xra$R`n7KLhHdySJf+P!XF!}_YlD+(4YD9m@cn%s>I54((x zP2&KC;l$30YQwcgdq_dz5%2YmsH8SOrd(Cu7390&W>?+s#^yxPR6!xKt*To;Fk@s@ z1%-$TxXn|ycGaJmbHaU(Zdm~|6skS4!dPmJ*3m-b3%6{DjOC0Nkjm5`8L1mBuU)rc zEojb=Eea#U%f;4(DcArly1T>9I1>=>k+BZT5z}C7U^GbPTv7`?Y->fs+D*gDxvb&g zL30)X=ABUM8r7JMAzBcb`;LZHgSEGiD5%)HZu8n&DXnBs$lw(eauBL8Ql6EbreU>+ zI0T`9!^+yVwGkv6 zm8W2qp6Sj;kWj%OEd@B0$Og}&lGh-43JOsr265F;vm4uX_j-ou44JhMFeNx`)wT^Q zfx4}AtBlQv9L>U+5MN)m$mR`L^VJQcuJ~)Pf;pZ|x2IRL55{cI zCTg{->l%m5i_y4qL+!@RgRxJEXHz*=UQJblRSGquY8@ukLD~g4%QvssfLU?yOx3Vl zY;GJ3k~*ZDH_=WoloSUtLOekl7^LokB4`dxK<=inG^fUpUmbpqKdsEv3lB+(B!nM$R1#>xYC~I7f%Pd_&zz4-~COK)em>qh}VK zo2Zqo!@5#sB{>O2YPEx9jL=p>YSA1uZm%k2`@%R%@UjikP7=MGU0&#dWn>Nrpsum0 zibD?-?cv7S4N{q`TB^S1I;Es;J&Didd8q2X+S*Nx)a5*zTnOlUxVCXsSof?3z}Z`B z*KV%c)JP^)byMov9u%(vK-Mx_*Hv|!&GK^Bf|8Ks3~f?jELdLRS}?1LCYw8!7rCmI zE|M)mZu~P)W(Wt=B2_d{)2#cF8fKJSDb|Oy>i#-BaJ`7^y=+wet&sw>bSSEYi@l0tzd94zAjVpbEP*fj&rG3l?mtc41V)LNtua z0rSW}qr99F!la?j6Py!haz&3;*1I;rUgFwN+vKLuM|F3`9Jqnz{1{}Yb4MJj!-fsO zRg~3XKyN(ZX)$^h1Whj}cDZU*I0n;&UT8z` z4y|EW;)(%5TVsbB1I{Y0))(GiqBX;SrMD^uf+M5_ks6O6mMy~DNP-vw)kUiHt?JH@ z3|z2caC2Ksuh8J;HaU(l7-A+c{HKV_utb~#Mxf=6&}MC@^)yy3T0X}`RKZ-gb-}Xb zWw97?SUeJed^)`5X!IOujnnb0X(6lX>NZp~Y}f|*0;Odcn^nC8y`|(Rs#e#nY;3Xg zn=Ni2V952bozo!d7sQ-{1_+bkDy6D1QPV-ugs)ozg{B!x1KpzOpU_0{F9vnQpJkVZ zM2-QKg^{>aDI(s4I>#lEtxu@TtWT(g18G@KxC@F_)xjm+uuXLhM^2+favBYHLZ^m; zDECa9rATzHh;>K^)&K{}SMgZK@IU=&KKp?H<8*RB^J5!_2f{1(v-q?IRIh;z3qJ5d zM7V-pBAg>Uz+ow^>4Hla!N;t+0BJ-7ERBO_O3`H0_m(qhP;#0XMNXmGsQI{Sp$W*y zhGEOj5D7)k(9(g=wi0Mac`TNCm8+>Clw#0URc08dZOUfp%TLw00v?g6sCM{Qe-8NTk<7%mTFN8#=0!~d$ooaAHb$i$dSfS!z{)RiN z^J59VzZ^_p0I^hu)PtEp)u|<&NDM4gQBaVt;b=osqol`JgANQ8>Xb`ja7j@Lpm3_) zvAhCHn8m~>e(Rvk{^cWPPGcPrvB03x{^hYKH1BXTHN6=_S&&yC@?@w`W8GTl)6j&g z?+Hz)u{CliAR)!OdU^C_%gA?zjhE5YR7GsdjPW*d6K5pcsEwJiN=I(pjLs46WN2j{ z7Y#A2h`>So>`@c=pn3IaB@_n{#%|u?O)}mfPm1?ptWkzuDgF6C=FKb&k-?u6>ddbN z>a4E?>g=xt>YT3yYSGsMwfJj+TJm*3ot3Y#?EHK4U;@u`xmIu8>e>L0X2W{;5t_ES zwjc*%CEykndFvaR>hf;CDQ?OItc^6K2Khv)*8@vwj5e+=_xxUja>B?QeGx{JKg zW1jWYWZVo^o-xD5Uv&A0@G@5UwOXO$44O9lqRama-m$#4H7}HN8XJb+RxM^;eG12H z>(Bp&n^^TfkHgvIk1q|s==yPfMC|f7e3n1%JvIKK%h$#!FL018f8391{6&|4Nh^=D z<05}IsE<+TlQHOgqo*H_Q~y}4JomL4f6?{NMgN#3ntrC;sFqqhMEP&WDZlk5wfuv| z%5fiE{}XY_pVG?9eX#}@(dA!_Q~v#%)k0b~LJ*?MPelBDtp1Bz)FRROqo3>Iluyvg z>-%u^21J+tX`J#-ZV14Sdv=Y#s7G-%PWgbwxN?t+0YG&5hmjDg|Eu!ULZ=L6c^h5+ zxj5yEXQ&0`zFz~3=<;vHDL=MQEi_d97vq#atCf$gFZ#I(@+DUP{aX1b_8rjwr{k3W zSS#;0^qsfS_2XNwG3$SCrdqH={S*2>x_mhpH&*+%a+3&tL$&{Vamu$0vpmi{j#DC|3LTYUSmAYPBo!|LFcNi&Oq_xp@ftQ-ELNFS>kBobso5LNI=I^-t*k=<-+N zl=o}pbvdmAh%S#av10Z=FwFWZ;*?MNrds1tZele2qU*mE`^sYB|G|6ILeu!t@QW^g zAWnJjy=tMM@OL&&`GZ>drG~nB8(n`g_WQ+Z|9P!^{t)F0;*_6spIUIJ_AiN3K7W|y zH^nJGUn@Tp{cz7@to~PP+b3;$fEmn>gj2 z!z}+_MD~D+RU&kqbOe^mkqWq8Jln)HE{5x^V7vsQH{+#mv@PE;EWD`Ho?h zPahW>f6ouI{QNlOJBL}mF;4jxhFRVhr~Hdr`Dqco3;+2m)%u6R|C%`EU(m`wJ_P=b z$0?t`N-cPvjWhhB$3H18cKatiq!vmVqWtAJ+yZlv;T0)*fq!<4G*n9W*sLM0&|NhPd_)ZeeIT5ItfQKY#70My8x|x7l4z^nr zTifj}2?skN2y*a1Q3+uC1O~fAX=}k>3EF3yNp)8(Sn_Ol0qyQD7Te0wZtbqm8qn@D zAzEb>NEDpk`|~{{lOaK9-Tgg(EU#CX?|kPzT=#Wd_jO;V`@Z>1umAJ_^|#i!m6m?Q z_(v8F(En1m{zu{O3j@@*m$~(wGmYFw=l^v0ANA_vhVS$5`zze9mj3o^#oS8Hc~9r4zmnSl1Y$b=_j`i7Jf*H4)BB&!MR@(y@AB&ZY zsQMcRsDI}--TLY9rhk8NfcmSw`X8k~7KZyD|9xJ4e(v)xz5f{$=nsF7ooD?e1JwV? zdBT5Sfcif@&-w+${lou~S3hF<{!1VKHwLJm{g-Y%=Pa(2CerKIjPJky=B;ieozIo} zFTH-OTBU8vOoO|MNAkej1ug+jrgi-ZI?Ndis1Ad8rG3y8ORtyIW;MPfhp1 z@7I5Q#Q^mqUj2_+zi#mAr^EmG0s2pef6)N-tG)UKKA_%bdi}2t0RO#Seay2y|I)|* z_yGNHJy@ll=RR4)#q7%*#PyIo@f1^4p9Hz^Q>Q3 z+CTgco@f0#2dKaGJnR4C0QDa`&-&xa`iH;yJnOFQ(#~o_v*l znRL}v)22)bhs!5TpE}toTAjJ>`WtTuSiLP;=EsgMmD-=4ZyVWLCgS`UF?%U{dinq2 zP9lr@s{-6#738kY4DS3I6hAZ5YD{jNaOle~fBM(DN8Z01wK-VWm0TByC&zmCeI*te>#yv{hL92UD zjaB*2+U`7XI*D0RKdO2eeW|~AguBhnR_LVT-nY&$rg0&E5Ax^3k(j`}akQPd%)MvW zdFD<-jXxgza+mJLTR%&8m5nO{H;w(>k$QUhKQ`-bu${5Mieg}B);;G|*L1=01` z50iLn_uK29T^l?%&$V;M*v=oA73+bmW5SHMXk4GmJJD~Hdq1G=WE76Yr=r7s(1Ekl z)94^6Y_=VvjV$h=?%-at2zRpS?#H?_Gak8dP3_*D*0{QQ?orm=WR+G{=R)pJ>)?L$ zV`Ft^q}_=SnK$lwvo`_H&4m|yy6hjCLc>3RE>>4^-k;On94mD2&w!o9UYVNo^JGRB2KbnJ>kU8C_ zBG0xLMY@YmJ#bjK5I(c)v9ULUSuL6Nn3!<;7~^XPFQU)Tk>=1c{(L$O|M~pAn!CUJ zhoZf@qq`Y+6Ty-e`@{ne*I9OqzH?IP+WDzK{1|e`$5R;jaV}op#W?-4`=NVJ**^fM zk}tSTbHqDFJoF>8qAI2Rnl~?8{CisCWELf1rF7e7=m` z1rA6Nbmsab@AFFGggM_1pX*M?BgjhKxhH<`;jI4%IM?&LU-si#2ORmr{g1kzU2yp@ zA%`7!E%wT`J6z{5m#0U6Fe85K${F#?E&E`dm3eR{^ICTzIQh zA61cD80b!Zkw55_{82`0a>D3}eli&_fo_9OXv@?q}F4HTM;BN3C-g5)bT4&UkqyP2lf_t1XvNr28nY5m<3?*h| zBy!DtS8d5NPg)V~d$F3VS98sy!K;3nYu*W7^+oD zlEL%dA*+pf(jNClj(Nq-cqPZY8oFw4uGx}VOZrr$>dKq>Ir7@8p=raz^mx$sAlaKh3dU$}unHyy+MK zz&!#;>C?)7&*DliVCG$|**zG|cd(7_@zUUoH}cKPgMSJhwq<3!l5ZZ(dWjluWM6eU z-)tMo(qVQFw_nOP-yf0va=vLFk@Ks3^WKOC%A6jl=dGhK<@S%#?Ij4M|~-pqZPwZJ4FyUCh4FXPRCb*J4BwC)|z6|kPR zvbO}SpIG7d0#=um!*g>WBN4Ek4Acve!Hm5@^K=mD_mf~oThQ9CM}Fw}=e0?_)pm2x zx^KjzL2I{_{Uk-L@V21!SYQOtZGj9re939^rC`P@LG!X2dNr7l2wLrDwVAZ0>f)dq zN4ya^9t*zFUpxGawxcmMxKopqczCXx38MwT8ka;Cg&F+%mb-ZZKC~q2M+B1Mb@ZD*a zayQCVkA}=+)>q&Y>+?^COk3bKW1525-w&DkjEpTI^V1BQ=a(|T!=r<)`UxclMF4ql zHot8fOjBKh3+hAg*Xs9d(`4HT+ceuYSM)q>+b`Q@uWkR-Hv8=@fJL9f-08e!kh#&l z&5L&jFDiq*iRa$9$Pf)B5^%5TefDPT2N*>41_ZC3bK z0qa$31kVkDjJANaB|tY11~V{e8${S`!HlM$^=KNSIAf@%@%ljaqd~JJ(Cm%ju}@ed zzEZN)vK~Yrm~B?ZV^)eAf&Qmjm)@4~iUo&U+-@;+$WR~1*b*=g2Iy^TAmcHh(qk&v z8uz6zA(Fs?*C{&%3J0=z{Aqv|nu2=U94yf&)9(lmg>Q-L{_l6WFI#J0HEXAI^dsES zY!%i_cFD!Z*yS9fiuZ@YU?g+d9|VXvimg_ zNB2Yzs^>Sy_W=Go&>zaU-#e2vDiI8|%q^CFX6ic8IqhdQZ=ds}x~?VYoYLXi(G^4d z&Ry7bTl9ROs-o1oXmaR)RpI00T)2}?;+Ok4a3{QJ+&y?>+|QsJ2p>fyW<}G<m~4D3x+h(FvFzVu(!`V85e}Qk|IyMuT7C^z z$0~}LXO2RD+HWcPiaCB19CS=Djm=*xx@DRbc{VY@RNTe-j@vG$d4_4sf9t-7+k<)N zPp%!G2t=M$oA|Wii6LrNzxCP#uPvEceuVbgp_TfNAn?ppkygRj!JlYQj9zwT?G23M zdd71d{1F$ zG3|9=%Y`g+UUE;imru)&L+%9`llcC1CB&o+}4g zD_XF>nMWh>0ghx&jnp_ar$YRdQOAexT=IMU$1J}!4x4dk-bxPi(5O8*?=#-`s?x?M zUf3kMArmSagB1;BR_m+(mYk|F^KL~a@=@a=cAb;TCmHaH)grcCcleNg&j(*eQs(f-MfVAe%byS8-3EM17c$NsJRu`DX>f91rNib<$!y1sQH7%W?dT&{*c_m#PFxda*DuSZ2=%nB;b3qi9| z%QQ~-ZM2KIo}>A$Ij-@Bs`0-=Px%|X7)y@r`R+w)(K%Ib(tMF#uy3%L)WjODeycrQ zPI|;gtp~*^>p?a1`Hz){>Qn21KL3@^{`9(J&^mM?%XGi@rvY@9VEoJrrtwyEmgYR^ zEUvyPJwj{wN3GuD>0+)N6>U_m#Gp%B_?6K+q+{U^a&(YNK0A14&_VP* zOgZm!j`!)jFEUnLJGzQnm*<{#c>Ybw`yZz~{~+c0|8<{D_<+-fDRDpPFH3D=2F-Q) zyU&c(CpP-SWJV+cj13h#Q`siTjH3VL@<7a|_#-qbcs~^Wb861qRIS4&F!_l+b>`3>1v;W#I zWP$YQ$|mqCU3*CVweJT__kPx^Zt11fffZVlDv66(=mr0Ro(NsG@`nvm=;+D&v&@u& zpcz%=&^Q+w7QhdqTi$@4zeCTU?6#xBBdy|9`A}cy_c!?ccl`eE{Qiq%@;maU&Ip*C zw(-PG1Ew|Z*?84g__ko)S+?MT%gsE$T$tx{nb16dEvWah1>@L)%_+9v=h0dH_IlUh zv-{P$;+N}hUAfSHHJ7!n!0=m71@Q4t)_fjQC*J8EVkRplm;f)%JLYwFuxRoPyb}zL zT{t{t?8UC`6&Y@(HKoYu_|P6X?a1b(YIBs^<`LF^@IP5TThS;8Ek&oJ@NFuc7D18@GJBDIt0$y5t zx}1xClEr?xkBff3EEevL4!H&U7PlJlC7RlbbsfFAO*v=H0-C_hU* z^Db2E`dRL{gt!fD_K`{8bD(jp|4+d6j|Z74HvAzRpJJYBd|_g{^nb0HyZ4HcRDz3GH&ji=)1kL^7L?5Rz_b>d6(tN%IM+VcRwMP zTBW)#^u9aIoV`Zxe$@N!KFUqkyC-_zDGp1%aZc2U^#$otf+u!&O=TeA8!aYaNFVQl0AHSc3eR+(J$BE8krbCm(+V3 zU9tmRGLfQ7N~d#p;bd|O0Z-RXgEva}F5Z={+@Iavj?V4p5}u28$&I59{Ta4s6uz{&_q6Krdtmvh{iW|Wp&r^ziNxXvRsPH=po4$s4g3VfE zS&ef>baw-=b6KTDU-%@jBPWI%=6gasu|NLxkuFPuzH&;e_eUVjA zcLloYchF7ShkQcYHntUoO~q*2kUN5Z$YL&$n_*XJzL@UlU%C2iHFAk)6FHs^t{bD^ z89C(Us9oj4UCSDoDY$7vYrN)L>RhwOxN}!LDxbgjqR+Us#!_FhJ#=lPH8T`x%|ZuI zy^dgM*=#G6Mebf*=`*py();6?$AG`2xMfFhs3VIUovpZDHf~ z`~o|0@}JOtChcd@em3n7rTt^Uva%&sX4ZTwyKc@iTMFmg-;&u$`*WuLaECLV?&O|V zSnDqYF7j+;Z!sTpT22saX#l1KpMoo~5jpW`@I*WWUfha(y>h0tX}ji)KL)>CqI<}+ zcFOAeOTbY5d`9CDubp;slpMKsiL1kNp4nvadfW5lEE#)x!WuE{H>@SHf5oSME^YB= z%slw_oO!gf%!p~Hem`Wo8Crj{`cCH)a(P;?Q(Jsq**QGWRdhNKZ}(zH-Pop;!!x?V z8;iOsi7Ba#$d#sh{tISJ139zx~qwBAA;0E4%j%GBz4J+TIxqbq2A2-ly!GE3bHi@dE=BI%v0YYHe_-@rS@;gmUrGX1AYP-5E697C6~SPC4s=lfNAq z%_ljy#rUfpR(t$b!*3nrR?8$qn_>K@Qz)V&NU&#}1jPqLoi48#>wWdnGxs3(0*}+^8of(d&P|)Hg88g= zYrB$rUf|uaeEb0;&2jmhqx8uOb!^+t0c%zTl}weys z&yf?zUk9GIEgzndg6#nD^dfQtgukUc2PiN8srC4=6n-cprx^Wg`o+*ZJB8+yb@u3p zR`;LB2eYqkt#L2r4#Y*_1D8vnM_|B*Av{DI0#K0E7zFLU>k zv%;L71?|VYd;j4l0`i59Zn0|Dbouja7V;PxG@9CqF2AnkK~Yvi=S*b&ar%>N_w!?g zH;pxmzfAt#Wj)c_EV*y_-+{xaLtpw--m1z)9U0@k6C9FJ`u)`Kaa||BXkicb#-=Vb zr{n zuAxbe=*F4KlO$7KBR;zyolh`{4*%8hS@o$Hpg!f-6>Q2Os=@DhinS;)zSq}LWaZZF zC$EGtB5%lJ;CqDcempUie`FJhhnPdS8G8Sr&pZDnc%SFAy=P_}`UP5A)a;9sfu zI&JxN%`oNDoue*&9#NhE^`x)$X&?PpaMyY=M0rC4twmZB{c_d#j(T7$b=z>-J9JGnmo&Rfg~!*E`@jti9DIWp7v3x)ywro!-C@cdzrd{X{`U>3aR zp63B)ExnC8PJZTtffdTJ`xdhD1LlPMsL3RDY^8D57v)+$|0iZ1^R747@(HW4jajOAzO{?W$=HwMtRBv0OBT_f*1XTiU* zmND+yf8rBee*(X2PAIPh+iG_MzRCvbhR#$Sev$n)@K(;I!IbA&eWlZ@KRE94;Mf(| zw0(059E`Vb|JXFC{kIpm{oB|E_Wjl^eD3-7KUc+*>&C{Dubb|DGt4vN%aBQbVU9mv zh^>e0RSvMjmoE&iAgHwGRr+WE-dP_ecQ*`UAClS}MeaABnlBFghg><(jvZw)e`H&A z(Uy6^YP5p)Kbu#BE{ad^#<@{1PwsNx7}%dMLUojy&S>fl$u zms@2Tr&G7-qJqzvnWpjBj{>cys2~1J{k6W2%CFbOT5<9g+I_<;&!e7A|HOt{qyu&k z=Zb9Hcui#E2L9GxBe+h!X1XIAzs~muuX&%}JH`fD6EXR)4EDSWpI|7UUmKVNgZ7Ol zf5|wWuv$;4?8N$OH4gO|ru{JOhiU)h7fpAVw!>;W%W6eG-C7LKw}Y3X#Hv*11hx>m z7UBmVr}w-3s{MU$fR8r+mHZiIWfr_toV#uN0&Da3zGdBZ8~&;)j()s#jwQT@V)pU* zsgnOJb&Q8$h0$$tQSLxx~z> zieo>xKK?`ep@K6TI5l@R0B3t}tfP;ok5hG`n)jcAhlIys*H@%I+OgBskKVUq<0oEc zZt;vv!}m;H4!^y@JGK2f>&ovuo&SSB?e#elPnkE?>g)4X9*92&+J}sD@GTxP*8Xc< zUZTy{;SJ6KFoPmbHD}k~3|-JqidyUjQ&IBsZ{BQ2%o>wno+4knVjS)DHWTx#BFzv?k$rRJZ0 z`=5c$+xv}+fhWnM{@_c{&#Vx*r!V1EJ_pCIxiHXpf_2%!`=5Gq{1TmE!8_VYyv`W} zqS<9`J<;&HgH2;99TgMU1kai=j?ZJ-ckvZ(_-0j{7^A}nJuw6P>zVlPvnYoxaufa` zVgs8C6&EPIqHIT|!^e^CTaX9ykOThrqMMBT2(5`HW>(zFTz~hAneq3Sj}8p$T)13X zM!<1Fi{ydkq%$Vufj$$jf2QKyFOH4BhdgoW4XJW}$A*+_aLTd{>GM{66_U;N!6DPX z0TcyFZ>DLlIMz_=u8G1I?Mr=iHVtU;l31_bese4iYp|1ynA_W=WdsI0bQJS)99jl zg2nMosNFOgX$-T7vnY0=wGmn4;8*V(x`@Acx`jXX{%n8yV$T-9zl49hLNeXQ$e#!GNWF2*t9kaE@<_j<9||) zL%yp&Qy%?nkNS?2Ct}mT;I+e%R@S{T_17MBVHZvmtMKH^z2m= z9sWybJu|@Gzq50bwf8Sm{7JsUyU6F3jpMp3=IeT5Zyf&E=U5?2+9_LN zA{A|{FTUT#Z%b?5lni20*cuzKL8sE!PV9}N_!o4hRfE6haHFZ1=h?vx=uFykn7-fe zy^XRR=nr||o}uHy|Jsr%<%x}v3fYUtXp^!8MPid>`aU`B8J{+m`;(S3pVEa*W_y0ahjBo~hbCSU^mv4Q5aHndYny?i$%Er+ zbp81=f#Xs$uY%v_&&MVOj#+C3N3H|MmpwRU&FmkJuWbm%qlG>kV}QfWt6x`lbvZiv z*2jW6Zv@{z`4#WO|C?y1bhzDB`hq!Bl4V*;7Merl%%92$=$84WyAr-GonXbU{t>!9 zGDkG3{<1eOMwr&3(^ec`YHMNGwAOA$HiC=Fq3+(TW7rCv z<*d-$P=(6Zw?@BAtQ>#A9CWI6@XZfd>z6!U-|FP76ld+|1je~TO)F~%wj68X1KII) z|72S0er8&wgJtPm*|7MM1(Aw%&j%~&7MSjP{(X3S3AB!(j|ZS{9c$^*OX;V~bk{u} zsd$LB@QzQK?t_$hiZXXhHr+o%mtTTSFMsMCvB6&Y` z{I-NKED7<)Z|i{D*ZWKFzkEkgZD|*CuDcoCB1D|)Mf%MLPl6A#@23L3W%r*~{Deb?N7oHNN#pq#lc{wjgL-p4+e1)r~hzqIGM1il#S@OdHp z?AonScwOy{*=XW+P;Kfr=@PCzGrz8)JPHrgG9KdMHz5b=>}NI=&LYS2UdAU{7g(nI zKWkj$@eBV~j;n}0idEpRXKX{y9$TJAvpi__&mPV4(r70CW-84zhIU7mxH_L`wt+Z` zLtEsvXl6sRZg5`$&F=MRW<#?=hi1y9bm#pnXr}hMklhJnx0`1vTif-oR@RmGOEc}^ z)!6Rw=$1dmboZBI=;s&8z7&7;e!BbQd)Hf69?A#Y5a66X)@AZcSeo6v`OUm5!Dp^q zSCy%TR~i^kbOtaJx76=8v0l}k#iy?itG<4lh22)oyw!J=vGtvKukU_Y)}KQku)Ytp z$H~uubo6rP9DyMIjsWY6b=G+T4o&c@_%wO$=%~h{;HzT-{w8Qs!TOt+U@C6&AExztOSBOB3CXwQc~-{4aOH($hWYBF6}+`e)DHHja{pJ~O}Cx^b05f?9^ zt6Xc}7mSBkD-CnC4Ot>Svyqn#$dopC!D20t98v80O2(%or^!M_sWw=U+iBIr|ys$PTVdT3>@l)C%WcmkPAJC7&zxitYzQZ3s$3VKS;-r-K%){`RvcE8u9VQ zU!(Yqs>v}_UY@_Nj&*kO8=qp|Bzq^_*kloVBiwzH;sbQj3fZm=GqNf)?wx$%1Fm3h zmD%j^kRMCs6`M|=laP0!v){@}$X%CxeWWPT`bJiy6+NcRhVOm{kJ!Hhx7ds|Df_rz z_s$M=>_d+iia9&;%-YX@%NxMy_1I?D#k<7^_~8_9KfxY>*N8jRFkhO9tzl=ks!#P} zA9DL3=cTn8dTJfn(@_YLNc zzfYEY>@w}C^J(tPDd;Hr&N`l)+Ccjq&`&rMjg^y~nkO8ZjZWg>Z7F!$GPP{SCUlVy zc*UmdMi;A#vUc0|m+jbBThdj=c%*BnUB@P&J@vWCi`VY=VsFZscj%}!4xBpqsr=@b ztH+j*pWuWG$B-nA|8cv*QD>o~J1%Y|L~isG9-Z#X&^`}u&c z$98GMMn4rC%Npk7TsXE%8*9FsL(qHPrS0btV7pM(;TzX~(VItb@`>x>+GDan{D@BS z8a|WP0-W!JT%Co^nZPD*$7XNCX5Wv^J{9=cW25+=qt{H~`zdVrr2IVO5_jpW1I3lW za{@Tq@UPs%nUsooDA%lsymRG9)sq{oH7mmBb2AIe_uW!h-X9*CR#}I{H^Rg7=omg8 zj4LmD9Boz;WqrX^_ z)?8n|?z`@utw&hk&(|aRlSk*HNBH`K)+Ob_G>pH#0@$YtUhKXyeMhEGZMgLM3qFqr z98ccIJZ`vjP(=j3+P5IEq8?dtA-dk($VQ)b)$FsAj(awt%a`^~kn#8hH(nq< z)PHY3-rj$&ADZskVh~vAjil#yNNaY zylj|z;A@o?ANl(NU-#A>AFgxJkzA>d75)O|{)Ny{_U-JTtJ@W`#|S?c_jiowKNoMv z4PCNxbv~Z(6lR?lt=Dr#pWmm?FXA8JL^i4TMsi;^lz8Vh=Fw4jLpEqpg8J-(I3HY9 zrOJUn(B4XwlY&|J60ANA_jqvWw<6thL5{J0N2fw2e8#L`Sa~RdkZr6vz)(%&g}Zn zOyg!_Mog@Ymd^=g#UfS_@=0+#H-@M-@y|Pb7Arclc7Y zf1MoR(Ji#=)hU8!dSN)l`zYtxMT!6GoX8GxQ!fM-zpmXFY*a2r$TAhtqnr_jALl~a z@#)tqm-?Y|elMN-ldBg>XPu+?eU1MQfVX$t?pcC=&{*M>fp~gX>R5SB*Do$~tj*py zn}?Vwwa{C>z9ruIh4VSTu$J@RqDM_@q=!#>d1P5X?`qTDNe@|+_D(!LpLeOak^I%% zlnmBfcmscm~rS!(|o%rVtH zdmV7+*7@+^`V@Kdaq*!IocPncb4h#89`N5+Iey^Y_rk4yb8*#oP9sMgnWbF#CUi3C z$<=&nY?5h?e#ROy5br4mtOpPMtN|Cwd+PI}&TN#gOtQQlKeEbG)1-49dhAes(|Ui2KNtL*q@psx5ck%|2(erIoTCP!e>*f!aBd+! zA!q-0y>n)a(^k*g;rxcqWx-eS8EG!NK63YdGutL6O+tnX`DxRkD4VPBM6<@UOARh+5liJaqwFq;o;Tu&Ik}2fsOu=6@ zdFMB*iiQnNuKbiluwZh-^PImi4ElKWfPb27@P-Xmh2+f_I7bMcnC$GoAy(_0sn4hC z$j%m1L0vd0^+>IDY4nHPIfwv+?}S20c&b;RsgX zXbFEvyoK1awdUR~Wc%?1`wDDpdS;ZI4eb-r`whVD`!ToC$0m>Odv%MmZPzOJ$1m5P zOm7%~H}#(Rc-H*{l6lJQ&^|ZeF>xX}^=Win?K=~WtW)3|+=PlbyJyWsqe8_l9<>I# zc5GkTcMrMVv2#Qtoy||)sC*~5LF-4!{zAl@m|UW2_6&U9tOHSppYoTuULgVcI32YJK$?g+f6eFtXE>aJ=(*Y?sG@onVplv(z{ox?Ue zXIDfoz0Ns1cRhTpJ-X<7d$Jkt*>$fwtL`k?jb2KQ3iNWG^OWyU1+PEv+{O5RBdmf? z^Gz_qi%wifc-5b&ud2|e&euAE{0Nb&*!iyYY~8Kj`j3**8S&C$<+Ixd=bX9jkvaEg z?I8E4Q)g=(gJxyLnLFl;j8v4NFY9~h{h2%L+S!}1hr^2$zu%_6^NZmJIGZ-* zZitVFGt591^!V2qFMQm)U-4szHM~cDoz_TnMf`oP%st6x+c#%+Z6kkoGrX;}`$hJh zl|rY|Gcz9%jgCU2%@4CLZ-d2sYnh$o$8{eCzAA9;w&lvDHu62R7NZl-3k}VT)s8pa z@fn;evt~+{d>MY;hJ1PHajMi^6C$jX$+(vRnHp?B4}>{BFWG|eUl8QHZNyJpVy zk&4bGwdI`6QYXBVFX)^hDBsC+`uXR;o@&}XlI5Or*3A0R zL_UbtPkRKqTt@x1&B$##2VHD@q*ZyQ?6K}HT11}SRi-sc9#r+@$lqaKHCon$@9jm_ z1%ea47qG`)6bTn!^bgX9hMVK|2kQ<$Asm3~N~_?Q&L`12Dj6Ow2wy~gNK43+eou3` zcv1s-#V+3p-{eFb0*A-isW1A7Cq*OCyhu*q07ufmzhBvriwEV-Me?weLp1`=D74_<*cxtOxC#M2jXsqWA(iA z^&QdVF7UB4klWeeymxIs|4ew@^JA#{I5^)o%p4co!McG{QDC0y%VDdBe~ zF;vZ8(Qznr{CT$7{Ws98JeYF~dtqME%5mmeN9b4Eul&259gw-C*3+XeO^{ee;-^$ssE;zjN0N>w2hRmV=T*m$_ZG)zKVT;%+6x;^`9{(=d$NTb?bwhx9j(s+=lI3>NlM|zAfyx zZTS{^5X!7b#YAMI=6ww^Lh~LxJwqGLU76a`Mt=Ej<&3`@9Ex5%+|ezMex@q^HhlUP zczpMkNW7l7)GU0^g3acPq6A~AHD&aHc z1~S`jIRf70NELvvbwd4b&o(s}7|EG@5SpSR2XMcF|frqnc zCp0uG))L4%xCNc|E$%X|UtjsuQ=9>{1=~fitg~`EE$lFzPvXnfGi&!@%RB4uR>teB z!>M|xWDV!hIeT|CSA9P&IVD?>1?;t!Pf0louAFwuyU)J7O3k%Y8^WtCT^t^fy&r{_ zq-QE$QZnO%bHu4^JJOv;f3uBsumT#3KSEaCL7!hLvo>|khEKkYyhq0M>`5t2K5%$8 ze9*yN+m)e)&LDP=&0W%3pI?BUA?}&(hKA5~w?7t#KWMv2~x%5u)opPhacV*Zd9oQbV*d1TEKeQv$%J*!X&<^pV&x@}i!#O~2-gnY?vEyCy zY`mrYKVA!jI?<=*$&Rr-JI2P2(f2aio^xyae-xpAH$VfMbNslwx${NjnfRh)P$;SF+{9NR)VoYtfSvPtrTy1-z*p^* zD}WAr>8EI>d1e7;?zFNF6|q<7alu0Fd4fEn+n7(1srF2FPeAH^0OeJ^vcZbCsXbs+ zevqGco?OCy0OrJ==e3UKcIF*0jdw$vUHGM6`z$Q-1)vt*XG*C zSv0~=1@P|-jOi={cVF{x7ogvJ2H-x=`L7xymOJ<9wL+BiBoNZsk znkT!cG-#$nx5g>t{fracv^ICIdl=wAXLjUi9b4FW#M`pV72=H+tc2=1;Gzb$y)Li%5UYnJ*3Clr^Mc z6y;Yle&v*${9x^~vIDffXpf=hj4wxBnVrL)3wJGQ)4s!hbN3x4X;(N&U2FX_+X9F=u#Ap5CQZUT|_Gb1GsvbVgPT3|U`0&E$Q`(bPYU`}& zP|K``s>&MzW@-sCDx3ay!Z%IeB^!J`#BV>xA1HifqeEYg?yYxk4Kh=UxFcNmJ|1Ds znoE2(RAVY)d{!~%rDsf}t#y{wSq#6GWkkBm&{~im* zwp+DjU8NbOyIAFbv8&KzXA=g=N!e{^#`clVpLQ|3L-b^5mP zt!&voyLMt%34Mq7Efuba;G#X1ok&~k3*23+K50vB>QilIIc)XEBcZ--Xr^mM$5@H=Ce7>uICTIoS>WlyJV6zH5EC2e?aE#}ce#vI%Y4DM3e@&$+_( zr0vc+wgJBAqHi1~IbEzrTAx&}J&+gk*C5HhTJX>Y3<%)qp*2Of)UuW((0TGHFP&A- zYD2hI&bhmmxqJAu@6yGuzqilT6T-p1eMql}BC|_^g|V;wJAM^pmAlUM&r3e82jZ!m zaKy<|%C&M1?)`A)BlzYTLuc+k92#u))H23n*y7p`U&`>+1 zB}r^|cmo{t*q+_k-(k=8*81GWyyzNM5IZ?+OpN%^ar=Lmt{=jSu1?u|7czTD<9D-O z;fI6Ql{ zK$kBdC;cG;G{E0FQ_Wu+QqNS2 zmfaSw`>QVzlOq=QyRRKaeja)gKUbNRg})@z@w-(Y9pv~WmQW77VM~W%bI;sxxbC<2 zKWx|5bkV2Al5$d*Y-Eg^KIBo1>oGS@!GW6UfeGkKE8m_gm;SzsF8qzUGdu z*R0{r8u1ik*vFWE4=>I|cUBqsfQPe=zeTyHYL}Jon`&0*{eJMejCVV&VVy59AN;y+ zdUa<}kG*)^b(E>AU0S}5^XO`jX?4uaZ0=2|1|Lh&n=JOY!s|KN-0`7YqBnz=m(8)V zv(RcZU=g@7aND?OsrGeTDsV#!1dnJ+dlFTQ={S(X}L#G=7a4U9(KM*7u#$ z$Ug=?<+jxD>6a6p46)#%Del>@dT)p8TSJ_GB3*b1? zadDIh?99{2_9BZT(D8RbZ^hH$i*n}-KKc|K5%RRO21ri}Ew(D^vvi-$41Dudarw(N zpD72sy8lAJk_jxL+cEkb3M^T`qL}a7_)nM8M-rHx=z%G-^KB0%o7lAO%2S&@Y^m>t z0b@42)kK|TD4a&zs-H6zqCy2@XtqD^*sFZrd2w^+myX>((oPc zaEHqX_O!mk{?p+%dSy0Y*`wrd}}@j7exmAp$bj^XJ2bNK$2)926~ zzhI9mYuQ#4h@2@32Y>z6q@g=rroX4zquF%8oW5ht@~)qAmL)JWzC)ciCyk(v8Cf@U zcx=lg-dRIqMff=80Ncyf(5$ToiuTrj-8y}zc$GRMlF8kryk~BXlr82wQ$GY8MZoCe zC{?DU&Lx*8BJhN3AEDC{7crB4zOe6)JW|S^&mWox>HP60={&*wsYkyPo^>xK)ZTVJ zyeI!}dfPT_=fHQ;5Bl&OeN=mV=kxnneE@?$j&s2;8@Nx~D=g;@q+Ymt@iUkC4 zxi16L-%&TmUc?!0%zyD{2;QzG29qiI7k17VIi#~uLeNNjky$!%$6R=m*y&B!QLS0< zrJl3kOKg+YA7*q-3$dPOiLar@(ltxFI+-UAF$ed7=Lln^{PFe3H0do!9-&0F!xo5-X)fUVLR>c|rAvS{3iyjAQ}^7ijo|9xBuFPV&I z4&`Up)|OW?j$P!|hrp5cJKL9J?g%jtf#s$U^U!7=Z-V^*17pUN0?)iLO*_*CFyzn*l{3-Os0Q(iuk zBClSLPAffD@DQ(+FUR-IJPvJ60k3d=D#gd5bEJIVlCRs!4iKMK{u!}6>iK()67shk zb^R?xb-uslY<*35^z~4kt1-}-8eiaSuC_ckr$>9N?Ge!1vX4Ij->o?siAP5n)}%2l z-}y$QOY4&}UdFe6jG1>A_}zpL@ne!lzmX+i()_7L&wCT;AF|;k$4?#*3wU=m3eR;ZKBIK`9m9k2ib8Nm;6B>z6X1}nV4BazS-0CA8w3mBxU=9rGfXU{orSG`f1MX?dM9$ zD7I#2=MWDg9(NgcT5*<>#;G>tchcF0?f8g~OmO2%tI->TGsSTC!x!7en?ug;=Yt>fG;QiNDU@MHDh`fHDHhFUxI%ZQuJvh0J2U`dO8 z{Qif@A&BW51e4{SnfL`@l)b+fJAz#A_~$&B=OkwwRtzGPof)&U3uDU7%${iuWlb=L zwlKHquwAyCnR%FdkPbftU+g26hKy=lK%Z|S-^S9;Cx>Upeu1uE$y$4q_cvPEvFvQ( zC&lv5W_PNb;w69m)&mcZpr1p>?>~IyLeqG;H8Qp>FfulR7{~G8u$Fe>8gH*RjgyEs znr~D-HDZGs*U%c?M7s~cyYfvxZJWb5s^BK>0_)>6AqMa^2 zt1mV2d&gVxZ#j0myYK&AXqF$u2PmD7u|+dE?}a(%??pcXKlgVwi+?W5e+8bZS^v`U z^c=h-p5m{^#*~iX$0nthpz}HBmvYuGb}{FmgYWh%Y#1kQ?D}9b;W6c$akpMeDLkfF zm2=hx<=Q#3TYdO*xWAZoewg?s{mKuMgzt;lD|h!7BJp@2&xu#|Cwq<}mn3_hL-u?T z*%OA3d_QR@gd2C0_HlgncX%rp@i7D@nnMZlmz~=-wex-Me%o+^WBMy zGY=F;31tsu9u&kF_q=1wNyRKb2k-yT8Wwv=YbE@@gioyjTHodKmp?kp=U)#S79%F- z%!B9oJu5paR>${!fh=@&cMg1$IWUwyUS4qgr|H(NtvF=)6BTF&-pc?_NqEj#!O^O=oIll*!O`6XIrg5x=ScjLc# zUi{aki2bpH zdvXqH$T!$POhs^|+T`cTHIdHzDDhtHU)d|28=G-9InOy^&Y+|3BKlrKo44j}aPl$H z1zJ8}J-ToBjPfXZX*MOR4(|+_l~-F0+vf+zbbjGe-`#$<^a0NO(RURTesBQyeNswQB zFKe;Zt<`)=@6vbu?)vKo&XY~$8_^MbZ`C>CrTFDJFgaFML%xS|R$mS|(5&~vhIFY+ z!+7?Xc)ojb_nf;2>OblFDQ&gEZ}sRQb`|F%^Se(Y>2W>#9l$y7`}p1+AC>$5EZ?x; z6Ku*kGOU^Db^YH*^LzDp*B(muz4zzm*LXCRKlW@wolBTHPT${uE*uM1AII;3njz8*rL|^yz$L-@fb=(e(jY~h_yA&Gn&Y@v-Szj88e$j6j&U1A4s`z92 zL)#Pm)u#QRapXyQyYfru&%PX9#2+M^VFA1@-*D)1atJa$vC^PJ&)5Dxeb(S>HDr zBy-Q`Yyfv}k6*q&eT}glk6~Z>xpj(3Ywuv!S~K~;<5lrWH?&OWZY0@HWwo6LW%pY8jX6i+BCJ+R)|j4g89a6WA@z`pNYA&TPrN z!gObqR>jxxF2K0`@n@~Cs+enqr_bfS-*r~FPB`)55$zPO%lw~KTyXl&5n{{w-d|3X zPs?}V1KCrerScl~kDtkX)pqB2hmPi8Z6Md7<8L?AcT zR>&P&fzh3v+3;o~! zPzm0v!AU`QW<2jJvhl4lt>3Z{)!+N*9&`Tk`mQhG`omDtWd_}$nejxC4a(C{K0`5dYM|c)@0yk0OWpwI99G21 z9Z+t`rn2jLavfCmMfQrj>%QBbVqp!)QO*D_-*hQ^dT2j0IPPFAe+|U;eh7~6JscLV zH~jT=@u+3T?nOUaVufOljt|CTd7M}NN#+i5fAP^V#@B(LZ_cMSZ=b_DH797gCk7)G zbymT&HyPJM$hOWv-oZO)TYh)7yM_LdL$NKNwBnob(F$kvjH#NtUN%9~(Ln?M-as7V zdiDrhN8Zs)=rDu*1K8RxxO;*dn71{QcXfyx;sNMAQ27Y*M!0nU>PK~;)7YLKkRtE< zto8oy&Rjdknvg0VQ=k30lKwfMpTUU_IA<^EoZM-fZg+E5rZUee$$i!QgYMJ5lNss0 z0vzH~IQ(lTevsQ)MGRx#4d$5$@c{!nMh)NeUCERVy(%3+b-rW_WnN5WO={fWw})V>nsYY4adzTDT}ZiP)>%gCk&MDBbsp6=k6%Ht9yeaPnzK`<^22$Fe6jT z{JftsVkln*hjW5%-jDL&UnJ+|7-O1f6%tD+B$krZIg>M>qO_qrAMvRCNIssN+#c{W ziS0VM+4>Q%#d)^uHXGL{~eij+TD+(_o8(@Ym8)yzB}hdvPL`k zV&3`j?s<_pEy@+gcKFD1GrzsT#Kj}&c7^WW#5dMjJ3i971lhlOJnJN}Hu%&z`@ci+ zxcf_Y%;OB<{?=okkARcdW7__4)^$<&7waD$cJIad7x---YrAqg6Zki!OQ@d3dQoi96?v!cHqZ7aq}QH( zH`XBT#`*{D#vw^Tff8cTbnbsK2AEm6Er5_UWT%?eF}6SldARJN^3(RF^Z>ySXQFcSAPuQTEY% ziNCJkpfda~o$m!R&;^6&f`OL&13R}@4l&2Gm@k4w{ptP>oi8r`O_3SXS*&w>$p@T^ z9M}1`{#mw1S+6=6&(*pcfqd0&Xa9z&kY6K#t?%Al(R)9F%8Iv7d1v;jo_l{q0dm&c z*Ht%NdkwhzDN=Eac#q(4{6FNWxv)_VxDx!Xn0Hj?HB(ObkuUxL)&$#kBYk+?za#ggEjSE2cKHUP{)}E-dR+#9W0GA zrJSK{WG{EV87D5BYL^IJ{e9rY>U7@F33w{?tf5s{H&feaCx1(AEI>b18?t%Yn3Fk9?uZ-vZy-11ZuEdCYlg`Nd;vAFiXFW6(Ux-4)1~?c{;;oJ~C+9q|MutPgwEi@ChkrT5HS6&d9TRhrglwz_GQ59Ui5x_wov3 ziM+hnd*pDOVt;)TewUr>E7}>b;?2@s(RrHbvxz;54d}e}F#^R4+^skm+i*Iz&{kv~E6 zR5qWFYw2~`PjdIhKZ!?!7j?P5ir#ZYv`?`Cn4CS+;4;BFyaT&L`_I=PQ?6G&Cw2}`Xn%9;^;?3kJX`aasGMAi_Z2YrzR_I`C=-i)m2C`x= z5zGH9X9UP@c*r{=;JIO0G4>S3Wj79NOS|^o9e1r-9bT|FeEagHOPAlXcu{!4n(!Sp z3s)`=FRQs@v6--F@$I$C78|pmW>L6it^v;@<6kfe} zrMaVa)vDTMUk&qyg3-mRYFG8VTXkp6!o}g5+bNgY#b=$~RxWmXTJ-7g?RPC(xVm=v zvMZL>)-4X-y?EuSyH5X_8w?gowK|@ zCTFg*32p!9ouMXb@bhXO{ zDm8H1rgquFSe3Li`}Y=QwQNt7Q8I-_>__Kwi4F(YP{K^Usf^9<+s-^1+NbA^x+Wi zT*PpT_6{<9MeitUV32zpy7V_YYr@gRHH+YJcY=bjrFSh_+&gZsuE#VfWv@1utfJWJ zl{Mjo%a^UzY;hT@PZ@_H!X|9SoAH?@)686c*V0AKm_2$!SEt8b*o_z>wUIC#xuCD< zBUqR!wRHT|l{HJlOKXt>HA{^Ur;%K-pk@^aclmL`;*~3xuQWX@5O!LFYs2@{GGlrX zG~v#bHDA4>#!Qfy5c!>g%NH)ZYi0QM+Lg#QD6}dne0dP{6?I-UPi#2+;t|t9@24F` zUcBmZFt&2>y zn|m|ENB7r#w-++^-gD0XInQ~{bDneV`Q-V<>mR1nLP)rm%S#PK<$^L*@z&bpo3+;O zhM708QpCN|_W;!djRfJ<26wIY)@%qlE77fkg@MXJ3j-CN#-;{XOh%;~)m&}EEv2{K ze6x7-B{v2h^m$O#q&RP=xdAdJ^W6xB6yx5wwvKElNecPe{2nK}6Bg_TYhZwqOA{^T2 zp^G}LwC`9S!{m@JV~^?HZ_&L!u6zG3-fj3(ukYYN`#u}*v8pHT7_$g_PsKa>WnU#~7 z=c-6?R#bV>s#n_-d2`d|<~o!8O-*%;H{Wy<+R;Q{?yA~ad=@m;u5GCB%|&bCCRCAC z6@G7^<|YMSo}IliqcY1^zOphiyL@F%R%T^JZe@9eH@&<(BO}k1otu`Hmy@2Ga!ItS zs@7FIGb=J(nJay{-dtaLW_jAma&MNmA~)NcmhScD@LI+VQP;(PCK z^0YLrt4UFF1@puCB|TVDyp&0srpN6Gc}iF?rhz!C&TdXQ6QWsY!5)}$BX5&TlyL==uDXwjvmhyLUtZkvRgDnHT_ z+SHJ)S=4BWpt}_Qs0jZGr8R7<7Py6U57Rf&^8{Z0o)cmA zTq5l)0(YJ`GoVfBR2!YIBb_0>4by99X$YPsGUQCe@UR64PjOTVOs^JWQl?3kJ4N{A zDAU99G-z*#x7P)(LmQ82UMF%})FCicz_Vhtyvy9?{X+Qtj^t<}6H4Dg(NO;dbSA{F zN&1M-CJ~8%oIRpO$xK#;%RhHz|BHTn4 z^0?8D%P(!X4&mlkym+`*gd628T}1B<1MG*wO&dqhz%5>Um}$c~4cxMXo0h*t2H{p1 zgsU@f+hXAMl+KOH=zifAPl;W4O~TV)l+r#;FjA#0Ps5ah^MXz<*-pc7gXNX-b(Wz2 zA)bwNaG~&b5pbS3&Vz0+Eh-ETQ0)SF-&6uPv0gHMxQ?7 z?X2)~YxC5gZXj9xLWCuIN*CeZ6K;FR&9Iy+cAsP!BRU9r@oXH{&S}mO;YiPn!wu40 zF2V+fp-H^sj30gxA9PWk?G$cx05veMaYqPJf7b6Mh@Fx!P&6JbL126@;o z{L9E67s>3XaO3Sx!+ciS18#0KU_)Xw<;AS*3)<91qKmh!hUlJBPKk$wBHSCMdSU0h zRz*o~XB6~EUayF7@domm1OML%e_jU7(kko{(Tm4mB3+y4$3Xsbgukj^qysq5n_pDs z1~D?%y%oZbmv4Ae_&VX1rVCGg+l60~&X0KO5Pn<2{1n|FY`5?)3G-LV%!k5nxz3OD zkYU0;T~G^tk(=GXEm^pw3EiV`w+J^iedJam+*BEnTcys8bY{J9`vsndws{rZA}sd# zFWg%ZUyD3VYoqi zo=gnjIzvAuwt#|^h;UkcsuXTc!s4RW^}#sa+A~ zuY6Y$j~7H3vag}|hDjI6?LC3H1(@OFM!d$1!w;@$6xL7=pxtvD{TQXeP&J#|gyAgZ zcdqBYJ9Af6HBvuZdRl2o-2xiuT;JqcP*S3daTk`{xy+LXpHdngFJyC9RiG!FcYu5N zxcBgc@<51>4iBM2(NOeDLh)ynF5|;U1x>ZpcX;b^SNWRgv9M%G#qg2jA`%+kFAV6J zRU-+-p-E$UHXqgF>003TRjkp&1H;FfjaUOKP16;MGQ)Fw@m=!^iank?J?VM1bsmf+ z)HW0bjL3(Dbtz%d4;n?_Yy^&qY7PRfk2+-Zk^AbS6zkbsjqP@ zOxd!9o|0v09)pa^EG`pqY8CdhNpTEI4EY;#Y$8b4? zbnCcYm|nPUkfxC!siLO296D_o9z=@Hhu$v*Hl?R?T}KH)8Pz32Q!tHkH$AYVmjuaOTXX54^z=HP zZ%v7p&wah5=rYm>Np1N+&01fjNZ(+PDqs3(^xP`tdOstL;6@{W`v@!}k(S(jtO*DvT zwL}%wrRayiT%Klxz?Y*FDz_%u;Ng=vJQb(`Jyd4}YLM#&mO}S+n4W=3jXn==3#>jQD(X<7$*RK?6pyaX4ipxG zeg$M0(>T9)To=JFs!7BNJxg@wiC>1gs0DqWBA)vxtd4TAFc zyQir(9GK%N0#VS&$o6=AXcMEXBKkl*lD5XT!9z1S39*>st@8#r8(@^jTI}H|2a=13 z&o9Q@%_3?6r-LExT2ou;qc}>|5vaTn?VD21!n(UkwGEH|e)7&~z_j5;f1zO`>c5N9 z<#{~Ah#^OrAzW0#o5)vQzNnonv>g$9>*`>P3aghcfpQL-izOjd%t-Ti6b?KzHOqsU zW7V}aMZCz7Uz5L~_5qJ}s;9Q52_s_=G^|fbKW7x*1v-E638ac7Fxcs)Hzia!bG%p^ zvZ|)2L@_BY%=gEKhbOSIXt~$h*g(c2(CEQ@^#{BSm7Y+!ErlV-=4P$2Aw35nuxbG< z__e4>>ANLB#X4IJt$uTn9db4J_-ddEA0k&M6s{}GBHLIb%!i@FUZVX(H-C|_8P@uu3c4b|nfRmc*Oo6Ey1Fa^ukaWp`UPz>Rj zg(;bhMNm++4$Cme-0VnIQ(!UwfX+y-3-~I04+MBQ6-w)AA||q%uy)Q@gm6?c?p(IW zQ?wWl{8?0KJd2g&4i*M*sn%m82ai&Z!4dTs(if>B%Rn=M%k`iVDKLufY7}>+o(eDSp#-T$ zv}7;^nldR`&cwf_t3@%HB-FaKXxWx~E7o`#u@=>XWmf(oB!x`sy1TRj3^iP-V+bGT z%V^c1uOaf+k6F*x6(A#iYn#P+={*W&l%o4GGebxFm1c&&M}f{@Y6Fy z=P1{cK|u|6Dd!EAOB1!qL|2ElEfor;QSI<}h81ae60&(uik5t+Fhx~b!-^7F2jdDk zL^Qh+UtT^~d^HsjyJdBymDhn(mEwCKv+mT_Gz`c-OKVLo0W+qfAfZabgK{P1BzxQuI`YS;YU0gc`;fmQt8rt$bC5(T=O5 zOAmur0WsjB=`9cGn|ZqpX}&xSFGLMDOoI--XyJpp(xl^o)kYnCaZyJ_AvIm7Qul~{ z38J`^SK!9YAjJ<|3%n79FE!BsTTD1@?ex%~$<-T!7^E51*i-lb#-)O_ zw$&h2m(Iau6VY;VwdAU$X~5VO<(ZbYhTm-McMz(#;B zAC`iv(O>%jEqA{%GCAuT(F&@$+PUPSxl|1+(b~VFL}sszhQy^QkgJZqL{@qOVe>LB zUA@;g;sXVOTXJ>vJFga_x;)i};{;J^M`Y77ta619AYHO-uB?m>%NZyAXDO0bNoB8+ zdPPu!@LmGL87f0fr>2E%IPc}Mh~}sr+!~Uh7G?M+5%R8yrlW*+I)?&>e|6pAZCHb^ z3hD(2*T%@H$n>Vpr)h{Q#ogGi(EzaG+*08bz9+M3)vVYZ~4+d}A8}xNa+) z!I%fX(u&hv24gqTio~pIb69+M?PnA;R0Pwn6W zY9hT{gBdN=VcUpCL_!ACw3VSl%`I-kmUI>VxqR`6ws41)uPD}LaNDu)>vJ)9J=fz| zwSK*)4tv_w)?mlArVXBTX^b|D;oEP{#ndq0+}rQG=SF;FR;*!jeSXhM+JTd=nz^zc zTE0okZp3o*5HWY?Df~fQSEahrGN0k_v=@x_(&HBiJS{)cUh4W(bpMwJ#=;Hg& zD3APCkIx3!2w#cKsp;bT(yY?Qo8S|p#M8PrkQk!>&M5J>n&6WKUR`G?*dN0GDieHGlz7^&#)yA+ zl=#CY_~Iz>Cr$9nqr}Hy4-zB(E2G3`nc(XLK9c_2Z-QSRCBD@J-x4LB4pcHqe`}O@ z+H=MTzavWgNEApT{8IuyOI2Kx@<;pp7~x+Lcv=gpz4Yb(J`?omkInHT?Xjm z&p^Y+2!EkaiT`|vBjrJluQS1)y-f-KIuX}gdi)C}_*WJwpfeHhr%mu3ixoWWrKP>} z@jI{=k5T$}6e}p&TT6TC@&9gu?_H{()IDKT8hX4P2HG(GQUy_^0>xdA_nY7^2t41D zOG87C|9cbsd&?CN?bW5d^!T?-@O%D7L8*Ilkk0I zl>TmkhkAxxdVHw~{tbcGhu6PvHNn3fW&A%k!T(O+{bAe>mH$ZCccb(#Y*K)8BH)Wm z@O1(oNq$>Q@Ytb(UwV1z-)RpaBmOr7TPs0r5TlhQXJjA!mfQZ%{xVYOwUEkN+F!fHJ}d1)lE-sG*_9m!aWl zgiqv~a52_Go|;RK|Gf$RsfQGhU4x}ZJ^uRf#_{hL_>u_tWhVFw0w1aVYBa&m5gY0A zy$Llu==sk_0*&PNT#EwY`xOp@&zfM2-}i_DniE0(Pnh6e-=g3n$^Z8z_#T0GM~MI0 zNyhv;zoWz-sr_4Tg75yWg5MJ%{(nFRo00r0w<`Ev3?0| z`Tmz08hZV?Rp4R9!>*1U%Bw#A)OYp1#3cR~1wK;wX)wW0drXO+@5QO%OwWIZ34X`p z3aE^Pqq+3>H%;(ocPgNg2>9#K&t)Wk_mc{q`q#9V?v*`hfjK2rPvhcW*#&no!%2>d^3f=~E?f{#>x?r<8% zf6H?Uev@(w{p#g+#sq&z;MH=X642vQl8oa&D)7lFP~7$Sl_vOJfsa)GKW~D+An<7s z;y-JGpYuZn*c1W3aE5XE_X+%#2>5*__*p+vfF%*|XHD=;0x!D3LR9qfch5BD|8;@a zhu6RVtqJ~(DDm%@;NKSbG%3V7f6&KYFw2<#m<|OONq_d6;1dNtlK%hE1n-OzpM9M% z|H%UXi}2(R`Tp2wfNdFuZw`MF~Oe~_(9hD_zr=Olz-bz@GnNm|EnhW0|MU?LH?6w8>c_(WhLRXm$UZL z%d^D<|K2|+DB9Oqd+G5POz_(eDyV&0FrM{z_Z(yX=iq>Lx||W>-)w>}{+WX3`$8*^ z{8u0U+a~z3!wM);``3G;G5=}*q~LFfz`s1#7+>{@f}a)vUoG$%O7PHc>pv@x`$mPF z_=8GLy>AkDYj`l0{4a`wUjF*>@Pr9|(Z4Eqw~nqJ|AGm=Rp9mE_3wW)!S9F?pL~-d ze|`F&5_o?E{=aF0Xa7q9M#8rXyhRs}U*KteqV`hrO?CUR34VjXC#V6%U622z34W`< zkB)%EG*2;_ngoNcsPw z34T$xB6z1x{`&O)y9wSe@FfxO+3CjeKNKat%LFgKrbOHlA$|tKMKaZwzt$-6g(i6U zmrBI`2=Q+;!Pg0VUIhG`Cio74*XNi1{S$#lHilg<3cO9HaO$gizaa2oV7weYu6I%1 zRh;S@pQ*@Sum48{zGa*mQn~B-Cwlt4qmb_3E8!=CzV_0`Us6Y#NY2Gs({pQYayp&q z*?D<5G&I|l?sR6S;m4Vgh975oT3Sw4meZM+n}%Py%3_-fi*K_?gA^t9Gpz2;*cUe0xZj9-?XqDRUdE;yEbWC*je_~}_y`xya zV-xEHY-icGB!2(QI=-uSsx9OF?^%OKzq+-v`(ekS_rFrYoQL1uYeoiJERNt_;Z}Al z>)-n=*10#9^@H0TNsP6ZOD#)#toAOVi*KwQy^|anJ1wkzU=nlnj%O~*wQSsp@vOZE z^e9a0M0ehzfq`rcx9m7?b##4>uqQ0;{*w=T4yj>q?pyobE_Uwo`K*2Bz(8s5#FnN0 z``BSh%c)WBeurf1JAqR&E^b_i^e*W9?CbM8KaX?wLk{gnt)6!&o^H^TE$mlsZUB$yM!tpZx8LXee`|&JG?*86^frBb$V2?|h zJtyX`4ATDgF%$>y~6pTY5vHwk!UJu7Lq*EIS03LsA09 zWxII*_`*G&4uF~_-@<00JvU&ryxBjM^#?sMNaF~kbtLk3ROiK?OYPr4-X>3S_n)^~ zQa`myT|AE`vHpQ();R!O0J)u?Bj0<*u>KzF1TK4ro4qt&W~HCO-LZn5I|&({va z2OZ0DCHKp{R_0m&A=V!9RCqVNg{?z;=J?sA7g5b_?xgXz#y!{k3UK{D|Pm$!~DHj(!o-f7ros?MV zw#TIQH4jVe^xg;h#9x7AJFd`D;-I{wJPN?iHafN~fIR91ueJ?YL6XNQ{E>bXfZoN8 zw?k&PL3V|mLC?a@{;ALrtA*=G5BMV)sefOMaRk-p3$_2)`Nb*;7z?mg&_H?GIHL0+ z^edUUT`3*z&QGltF7vpH1#dYd*04_6y6fu`Ht(8fWd}MBJ-*bR(Xw>w%oiJE=e~y1 zkW(LIR6N0*w`K%8mmdJ5AQQTLzbp)qj%&Tbi&@1I=Ucl_6T?X zBBalQ^uO7)wep3=aJ&p zP#&a=VC|G2Nl0rh;(2!@J8%N>P<6&Vl4b1#?+3mZI9LX{C*rO}O~7_`#Jc=gb{*ZoB9#OuWK>BClK1G_m4fTj!%`-J$TEUME`LY!}W2oES zi!xz*v>-_Dc8T=|AcN!$HwRmB??zt9kiE*|QN%-e$N3g{M?A}tZ5zjpmfMI1$pHD6 zK{D`9r1EL+y120r`nwQ%ya4(`i&>(f`wHm6!1R zN$TE3=?3kcdo8R_O53?BpH1j17d-R~3{2AUKxrf!dZE^WbX$@Bp>~wgTYxfK27RNn zCY^ogEu#PZk?dUAQr3xKo&FxshrP=nS?6y^4w8KLTI4<|zm$)ok&nNMX9s?QJj=7% zPs7-k4oG%h)=t^p-gVPI+jo=AYDV3;0{1^bN0j`&Dfm<9#AmVWz$eRC=f6XySZ8#g z*=p~rK%D-#w|7nb$iBPTI;QU!-amp3Sq%I}ly`D#LHwj&whbGDDJX;8c>Ww={3v5@ z&Ud?BLwWh#ZLIwZxTSto@K(NsHQWO`b#mnj?t5VaPg$pRJz-%7QYE)*Hf$r6 zdoOGRm3zqPCD3T6vL6S&??Kv5qQ3aVI=bt;bqudFPTpS7`6uYkN08$u%iNtUjAbvf zQaYw|$zKi}>_wUapFH$d2kAGS_EQrI^q0X{}W{bXW_nPiM>Gg8154?U3s6>(mWvw;IzJgTKS(+o^t^)d zDxoZ)Ty8{r?&px@b5!Rj^*rkQu2j^W`SIKOQXuQqBo`_6_(asDzp+ec>-`Gyvay57 za68r4{Br*2*1iv@JYAgsxI>!M7tCng^%Uy)9@s2u6Kw_lAoLw=^nO3txg_v3lJyrL z-;&`U{KWlo8FWcPJ`nFm#=(xpPi&(yx)t?#z9jbrpewH-Zd<&qEg!m%@``#y?mCV9 zZUg7dI||oaRGb1t{OY;C8L$-`saR|Jk=5 ziw7Os=(x5nOWg78kn=~@xUQDX`7gXMmYv(anY9xy&C-NE>C1uAe~0Z*^Uz2qJ|8nJ zsLvA{^qum8@|5xh^2_bEv@CTX{ZwzKSXu5m$S2Fn4x(9S=la{<{20mwY@xl+g7{M{ zEst%r$j28WKRu`?KNvx{md8#F{OMz=gSwHwa(^@081_DS^Uht4Z?bdcaQh7Lj0eqi zuv-UExAZ{omA06opYN~E%0qmvR>pE$(Y}L@x$p^OZ$iFOoA|RYH`0+Zik zH96(R+4DBdnS0BvH|2lr=D+#o#)oFEVA^fDn6kw-n>~-+IFF^yV>iuX*Ue+M-pX#d zg>r0me%cX!u?5mfM#so7<$xE)Plo{~4UK`?8dg!;;KNTfwnGh+2WT-c^EI;2 z(Jaj4DK5IR(Br|wZAHb(!@Y$|mlfT0Cmh9=01zKzoB8kH&%=X{{OJ+h`xf2%w{`E| z(Y=3H_x`Bv{d>Ciztz1%N5ZbHVQ-9W)4jLp-nZ-C$&hLq*Mf)P`dM@mZu^;N*J9Y0Jx_44~?e!z=3!eXn?)`b)`+nW~3%d6o>)wB& zdw)^){*vzfW!?Kf=-y!u!Y(m{5pokl5~24Y+eW}4Y^#W{4Io0WD}N}cscfhXR63Kh zGcwZBvND{s!+xc+w#M0znU#~7=c-6?@?$-mqEI^X=BCZfbte0pn(7*FzUe0Hc|!!| zuBxqFg^k4d;as#_|E4A!tbv_(0yQ@&`10)Rl^K;;zVelonc3wlbFwlkGjc1-E4=CD z<>;nyW#^`)<>jR3rd$&3s;YI>&diETSLRAzt~b|*-FwnjmV2|j6}j2ov~;gGCoi)y z*PC6A^T{efI+VQP;(PB<($cuDCPft_>Ii;G50(@!WzweUaeG2uQ{x@{?Cn{?r3noX zS@j)qR%Ze~tGq<`S82lBltuL1zJs+@yP z=_(W9Kcu_v9Bg!TuoiO1#pj7fI6IzrQp*VOs6P{a5zO9M~u5Jl4Up>Cs;2m!1zN!Gs?lyBzQL zticv`+6}$Jw`+=c3eA7*gL$ref4A_R-^F%ZVOy4k_R_i&`(JBLan9i%NsZXr=)d45 zUVj<;CQ;>!z9n?I4c$A&4L74JM&~#d@5AA#t);#6c=T&?JT-;1*8zd6)H>o>k1v9o zQT&O5AhqALmmdEu6Z{r@;M2w1ZptJ7)#G==)hPZQ0?*rc!{Fnq!N3(M{f#F0=LDX&UlmgPS0De|0#BW!+UpIWc=0;^ z)mQb7J};hsLft|ndeAvZ7e-aXu27p^xW+=yh?XuGYe5s6E-K&JOO01`yTJtCF7V=} z2Ip~wUhuHM1pkZxie!W!`uJA}ygvOen#8Y9|AQv@qXMsf!>J7D@w-j%??s9KXA}Hc zf!D{Ue}7-#(^Lkd%yZ)JD4vPe z&wj%?wS4x1PYOqTP6nU(3&7_!tTYjP=6e)AlQ%k+eF51l0-xUyd?sVeX)5P)D(BM= zKED8;8!S^h{qGW=Q^02;#?L2nf6p3M9`uoqB@v(NPs;7y`J>uxlGHAHF`jj;d}m;~ z)L+)nGOtI><7h6I`X>Sti@$eiY=*|6Sj)Hv%SW~Qe`z_~UC!EHvqN^Yn~tHYEG37 zJ7{d_B*y41@(X2_Q7=s0d_UI{zhzWA<-=5IYFqCk6rYmrUW|Fs^9hm89=wwdZN&VJ zFENe?x%A66H{>D0NcrzJ&IINMm`{Z92?|T&5g|O>x!WVko%H#XLzyd*gt3~78;hX# zi=h9vqa56Z@=%Cz!iAkEAE7x#>O2}%pNa1o$X~kOAnvfW{5@UVdqjM&E!;gYf02vi zOET?-jQxePf7lKj8Mp4&BI=d?f5DD?@=x&trguBiC^ zqvGa&HKv^*kIOJlRQ9xzhyD!A?ZCS~2l+C?9X7|QcMQpe^>2oZ%Vr3`_3`9}#3S<;!X~{2c(~38&(tA>?&Qm{EN;}4?%FgC4aM9RY zEXsk5@&JAB$J8q5`rz2BEJL?Rj*th*PxUK99&x$HD)OT7*|L*TJB`sI9Jb4HyCA<@ zKHp5{Si62ch5c=JC&k}kvG=(#9=Zl&>8GHRt1sU6*5cnj^w>5_Y+Et%<;F+n2Vaol z+I|f8e}nt?R@VgAB)K2kjmFrb2L^P z#29AaS@4Z{74rBHGG!EHOlzw7R_0|S1J^Ds7cj>ZFJU>z8r-3Qz0fZH>; z_gW`qP@KKi#0>v9*mcbHI7+m>y$O6E9Kln z7|XS_`60hD#1GmBv~x2UXlvg|j=hi-V~U=#5nS$ea+jwmx+*)tYkat_()nS3-D;F|D(9-7TAq!{dl_u7>QDTY!JgCI|LkpH z<-H7b6L){OFs!V%K-Oj8HJWnXJdyQ#F@8*CT$>l5Yo|GSu+uz_GO7bPFG`$csF&$o zo!?Lfo#XzXqqr;c4YhOXwB?iM2k=y;$VRJWYQQSJsUKs%7wwO3*lNPS)@P{m9cex* z#pQ4^mnzrsr4s0|eoVj|M>2$azyC+exPBgmexlqUuaLJW1C(d@jF3B-f8{QT*z>(_^5c9s35)q545PZ-nUB$j+diqjr;>$!)1#)}9PI^a;C1^ zBOTznzJ+nStfx!1k=xKY(8oljy;IKZyRFMMhxMcgGpr^F_^`^o>| zfq^WK%<6kUo8qE4W=e^~LA#LZ{Fc*sE1<{(Amhs1_-bj9_br;R=ob=LDyRh63b9rb^wern$4D)i5kLI== zv`lL2zJ`Be*}GxmX}*tIM>%3xI_2TMi7XFub}~M(jBjg3{oHn8pp@!xil6jEYq!+7 zQnHC&*jfr)0hWla&6aVLW?KTjTfi&n4$bSLIk{99Q{7K)XkWT0oEl!M&tyxeT&Q-H z_}vE#&8@dVe*#Ds;YoMZIdC@c6$^c(HbIY7N~JmBO5Cwsu{W~*xRipj@@u@z$CC2$Sn%|}7<{}>{|7eb&ntw;9P@OWVZ71^YQ_PR+p2GT%SjPADT^uOA z26;nyxfyMFo}bxDy+i4tazg7MFfXs2!mkl|N%50@X!BB?e>L!P3E%P(zFjQ%hOy#X zCI;U$n76(W>joadyn4_rgG>^g3pyvRfUF@`ny=`v%Dnyd1^8b4w}ruP%w+A^;EiOq z1owWpCy%);&(EA(A8vyih5Z|ZU19xZ@SY0xCh>$h(5YnWI_TR3wjmbtNngV}wIt+I zE8^{iTLQ(6*N~b%?CkdtIHa)G@rQp$-yZhSZ;0`>1_Z%ZmQqKW1t$ z=#h}F@byI~*O>oE_DxDnmRQc#m2RGo*~rIy>x4ckf5`Woze5}IM#yk7^5`At1NqVS z%8}dHOYV_m3t8@y$U}6K*{M%Nwz09T+?Lt9lHm3v@X44H*^4=mM=U`kPLlk#rILKWpdki*a^~E?V6*Yr=YWcRAEr56O?(EMsr8C?GcNt8dz>j2W-jWnRmkZXfY z0>(u=`;q4ZtCPh%*TFSrl;2;h`WHUOnCeraq0QT4Xpf*QKxb(!fiid2i}}=Q8`6Kh z=yOR$+YsLri;x~aYzNhQ)UG5wGAnC#r_z@&L9!n|^womLW$32u;zMuQMzVte$oMqo zc~f6(3j95zw<`0GG2ffyJQ;HSehfR1Jb-!Oh!cG8z#ng0_hW9iQ_Sn8GSLki6}%>~ z?Xznpw;jQpaQV9|_&hHkwAPF2HRapxfpXTl4su3g4eb@OXW??9a)CJPM(&i(&ry&4 zA;O$%;3Hn^BZg1{v<@hjdN+ezZF*+${C9EJ&RSvKDmu5gskY&k(pzu7S-km@8v_sG z#9n7jit~n=8=SuN6+T~OqqEw(K2W{3+S$0auCBJB3G+fJoH|kbuX9%aYs^{Af}+n7 z%1&pL$g1K;nBysi{+MzZ4z!O-{iJKxT*Y;-v!~e9kf+<{oGdK<#iD*p6+4}Ev4f_;m+gHq{T_@#4oO+ z^rN3U3MWe2ED?tD8^SB|TZ!j|!e8Z$;#@A=lJTsUUz6}t;Uc#=sI=+Qy19j0nxIAD z=wp~JHGSmf7jCMI$ZeC(jq-;Ud(rg^`qAfym=8=?tOe&6=N(U!*4Krbn|w5KqVT=K zua5k1Iq|3N)odJB0?R^}^h_0T$R^i8W7v9A49s{=* zg`3I?h5Lnp+j}}UlIccRfM{7Uew@-Uc| zLA_fp!lfbHpuf!L);9^i6{ItUe2m*gaZ}mbr-^TnjuOu-_#YMiK|CANQqt5b!s*k* z<~I5%#hU)U#DvCJ^>u4H_0;C7&o^<_r#uT8=8)zt65`dZ*BsIjD z<{(ckR}q#Q7{b%EN?;Ts4=0x^qEpV$F6A%FD!er{P*YKYa7Jk9x-?G>4(8UBh(CvR zit|`W<4twF&`h&OwYO%&m66F=-?+-xRCBd+$we!u8&+1;K5#{e%w8J}iAz%;S6w*{U|#7B zR22q>SC(OO5Q3{)OM+W+b@e;17VA}cs;`8*$fjl3#4WrsOLAppbXd+f=|4-6yhab%&VYMcqArqV9 z!6%E)SA+@#YpOi!yj5#q&^OfiqH5<->(-O*@_5iN7FfR1Lj&MSn?BSGE-p`p*za7H zF|;wPH1=~VeQ4;_ZYV4vnpmhue0geWEBWU^$+|+L3i$Fr1ZXK>NC!NPu+ARrP~k6H zx?~xBD6G4y)H7%iHF}W-A^9rM_eu*1eNiqTp}^15g7K`!f6WAsaaDeW`Va*jJ^m*q_ymEcF#+wR$G>TU-y=fO@G#os+qfkcx3w*_7d zU5Dc75qM|FMS0Nc^9v?;Hc1JuPrn{N3U-S4*T-KHC4Q3$exJa%C~Sm&_3{7O1n*2# zAd&Es5)}S3LNO>0`vhKJe^6TKQt#IbJet8_S5V-E84dZVIMrc+3EnnY2?6i0OON-M z;3o^bs76CH^!W7xug||^llb-Wf6@e>C-6cHq4@RqpPArGqQw8!1n(DkeSG@&F9kj= z#G&#~C-63%z|>du9)k>4pS2`5;2dY8OCQ!Q@Ou4e5%}e3pK32X|3pupcNG3TEJ&qm zx=sQ0@t4$z;pr&%e8|YkOXCNKT*7%F`<5xZ(65_6x>+`64-G7^zS*0}E?%e|h55`f z=7!raw?7thkmImcBp&-=Tic7V?sDq{>`jij{hwH^SocEn!!bV?XE;>?1?o3A9?!P<6-rP*< z5B`zWpR!IpUJ%Dh-?t>x_gg2Xp2FD~`@zR=N3yYg@cP<_mZi35n5&i60jq0+M=R@e zutql3ag^2fk79=HGD{ot*OTI)@JwPi}1G^GRFGu<3*6~V#s$k)^9Z*R_5aO&5hmt0A!55sB@$P zNsu*~3-$}hf7nI)DeO^zeMB-SeP{+_Es^`M>V{%xr}#RhDN88K7uNXH4$IUG#}iV0 z64F5OQ1i%0CVE+LIUHd1Wsu>KAG7)b<%qdgN@=Z@$n_n}LUr$gY>kyM^Z*2z}e?5X#(-Z%Ln z$FgP*(tv!w*DA+iFP{2d>#C={C{J=i&GhC`tR8)ZrEEv#bjemWz1hkdHa1JkEc(_v~@Jw-&{HNoY&Ih?% zogjHtL1)Qcl8qp`WHTu)vY%L^%+t6HHUZ6W5w9aPTAd48CuR_B2WY;_SeBerHoeDE z@$@s0*=g*Za){D3o*n)aW%S537HrF5?fe<`Mi{t(^^>fEs7HHd(_TKxnk71yX-4AU zxlB}_(7M(yK49(Nz!u`YHAaLeq(#&or6u6Om#{Fq~H-BpcqKekJw+qR$ck;Pqy4d5X7yBs~?M3zZBbH8_nFhU}HEy)W zlcFCj^GCJkugT3j0eYlAy^kpS`}E*ED|%PYexT=Wtl#QnElY`iIzL0+>~>*|LTO^ov}oD{ONf2Vbnu* zhB}~Z9J{y}ZNt8s-2Hp4tiF3Z+DP`6rO9JkryzX&DZD%JOzQy)5bwo}#b{eDK^t>1 z+L}dZb1uTV*xNgMGu;=_77gv6(F5J(=@IE9{i3weI>m16)i9V|W$higtLyLv2Bb{3 zADu7z$I0CjSnGJXV*=YTJ{dFe$IJUCus6oX!})jPY20bw1oG^dFb9zVm%#SJalaIQ zUc!lNZi92!_RN#gk`sC*sYL!zl9uP4m82J?m>x+wAg!RfIcATA?X;kYv(JKa;H2m1 z5hT?Mag1dxaA=VdF#mmr^gGmqxCZuQOV=-tc~6pBq*ezAW0flfeeMRCb_SV+YP*OZ^hIllB-0j=DC(WySh*3u}KDf1Va){|KxLbhSbU zX-%L?gK*?e?Rn2E>;Zu`&LZqBC0FAw9eV(HX|Dm;QS6O^ZZ*4Yp8IgD&3!m733cye z+A}F76>a&re4H(m@>1KBl!rQFlamhZw%MpIJ37zv3ah96Jj$@&S`yl*`uH6k;0$sSVZHnb@Jegp=~==v`YY^!* z@85%RN_8IbK7R9Pt0+i)wfW41@haB zJH>Gd>9Bc64Dx~WQ2T?o%acXBd?aKG-N0TC8Gh&w;T*txi1ndQB(y9&iMu`>pW?gh zcW@`YM3>bLs@q8q={(6JU#arXZtKK%9Oc2MsP|E%bn>4F`NPI?`A;&GzgCZ_oz7(s zIe!2-FFFK0IK}E0A+40oWSmcy!diZ9dvV{#wikQo{GQWg&@VU7?+K|NK%QpugE_D- zqIN6lEVcwP{FPMSL-%*2`e%yq&4M%qA^+{rt3&i{`f7Gax59W7G?Gezg&tCPYO5qd z|EPUSWp}RyZ9-icrM%mm#YzuC-rv#6TjZDHDOT^!2Tg=4!2O=FElW2Uh1<{SnFuH0 zo(*~pM&a;HcJx+--Z9+oK{&rrIMOK!cNYBNZp3#1n#QiYthj4e{{!`pH;C=vi^!M=ZZ^UJvJa%&2=OfwOYWhNHL-{2e zX@#wkW2Czs6Ii{U((pTW_a~qsZ_&7|kna8?+(I-&ntmqix88PA+En{Vwv*dXVarJ$ z$S!RIz5GV#if%#u+%cuOG%yP0}ub=&D zU{dq5%+)*t-xR3ZpT>KLFSUG9xts#MMLBxXz@NfTK>E3@5NSDbJ<>l}u}`nUo>E)) zH^BCy56h4E^l{L4HTJ+sb)3Mr{Ulbp?nee;5C`cOmos!Ic@$*&1md}O&_+V;ANSnD zO38Lp*$5(DGvD zhJB~#n~P{u7&Whnz8Y4IhcMVPG1Z3t&0EG!L)v7dZ9?i0S!(1|5yUxrLQWmfN3|{? zIc@$Ne%SYp>V=*Z*fG=#M^kY}y^u5)=S-5ExQ)+kgU*lD+KrIjt98PHq2bj&k4Z*# zLND4)=+k)zwhnC{L!CPT+cN?F{TGe>_hD~doUB{_4DNavP+gKV9eCK?GKf;|7Aeu9+Zt^ zaDNB)Be-`rC^izU`cl=_qyMdo+J0o)sjQQor#d?x`bBj$_Hi0J5xPrzaLCxJjQTt< zM4)SrOhS7E-;?0;L)^7GMS4isML6@f8-2wx^lS3y$z6JxlKtjo6gHfpjZ%&{LScj) z?-|vy^ihL!9)$aM;eHVL@ofYDcOd6x@<)C@WZ=IR@_7L6Pr!ezf&W4H*TQ`*{HqQ8 zKOHkYV-?&#Mf^Sk|94O~df@&J{J&}7|LOSY8DEF{J)nP&p}!;JF1S;^Y=_=bzED3d z&bm#dHWjrKseN<+GNUlBQ~#g{L-mUq=6M5|5*-Rdw5Xl-1B4-cAiW@+=(eCw?hj}? zpbuNs8Lgh|=Vf?MPvU_O|5g}YH$r(lT4`TXTb1hp)pyuyjM~;H3%pG8n}~u zhVV(Y2{w)QbE3Ukg+3Iuy$b#_$UfZ#zDcf>H&nkXa%QND9I2E)^qsQ=?jhQO55f=) zH~ft3q@U^(VDCYH#V5mrc>?|vj_kkfg!`}!{h?GwQD^MfiL!nY{hMS*K0rGO?f9J( zPTTj%%kwBE!Z=d@uLy_wZwSxC(*zM;>p&TudwXEFXmgMqBYQ^nOSNSbFCPccd^>JJ zJK+h)pVE$RdEQrvy?p8^4RNSDPyL7Va%$$|OVP(lb#GTn<_90AX8xezd5rBS8Q*h4&|D_mnNEpBw=oy*kxfP?OP@jfsa<6L-_(U0grA5mid=-to5R*`-ZKVKig zvQ$|Yp-#UVvR;qAt@qJ4wFt7EFrszJ9gq*{2gOM;qWGefZz9?QlfE34TWTH3C()q% zQFTJA512B@`_Cyo|0=?KsL=}wyB>K*e6|Wc@jX9Db(4kLbShhr`=#*QO=D=(hCn|E zZ$rSgQ5#}2>>#&?I{OnUOR7B)Z3wFG_2H?E1|h?0$TEZzWstthLvC7HDD&vELRrsk zqp}$feIh!JAL3gb{ms`I&{E6mr|6f=hAgOjB>%_2LHbT3-JXE_SPS>7tvj2bJIB66 zy$9L@Xa`-2+^KyFdzJCGqTY$ew;0(h#fCXj)ph~NFAHfV*;YXoY8Yx8t6^pv$b{%n z7}8~G1FLk2o>RP&|1<+Exeu2�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 Lit^2uwf_GBj5r?+ literal 0 HcmV?d00001 diff --git a/android/arm64-v8a/include/glslang/SPIRV/GLSL.ext.AMD.h b/android/arm64-v8a/include/glslang/SPIRV/GLSL.ext.AMD.h new file mode 100644 index 00000000..009d2f1c --- /dev/null +++ b/android/arm64-v8a/include/glslang/SPIRV/GLSL.ext.AMD.h @@ -0,0 +1,108 @@ +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextAMD_H +#define GLSLextAMD_H + +static const int GLSLextAMDVersion = 100; +static const int GLSLextAMDRevision = 7; + +// SPV_AMD_shader_ballot +static const char* const E_SPV_AMD_shader_ballot = "SPV_AMD_shader_ballot"; + +enum ShaderBallotAMD { + ShaderBallotBadAMD = 0, // Don't use + + SwizzleInvocationsAMD = 1, + SwizzleInvocationsMaskedAMD = 2, + WriteInvocationAMD = 3, + MbcntAMD = 4, + + ShaderBallotCountAMD +}; + +// SPV_AMD_shader_trinary_minmax +static const char* const E_SPV_AMD_shader_trinary_minmax = "SPV_AMD_shader_trinary_minmax"; + +enum ShaderTrinaryMinMaxAMD { + ShaderTrinaryMinMaxBadAMD = 0, // Don't use + + FMin3AMD = 1, + UMin3AMD = 2, + SMin3AMD = 3, + FMax3AMD = 4, + UMax3AMD = 5, + SMax3AMD = 6, + FMid3AMD = 7, + UMid3AMD = 8, + SMid3AMD = 9, + + ShaderTrinaryMinMaxCountAMD +}; + +// SPV_AMD_shader_explicit_vertex_parameter +static const char* const E_SPV_AMD_shader_explicit_vertex_parameter = "SPV_AMD_shader_explicit_vertex_parameter"; + +enum ShaderExplicitVertexParameterAMD { + ShaderExplicitVertexParameterBadAMD = 0, // Don't use + + InterpolateAtVertexAMD = 1, + + ShaderExplicitVertexParameterCountAMD +}; + +// SPV_AMD_gcn_shader +static const char* const E_SPV_AMD_gcn_shader = "SPV_AMD_gcn_shader"; + +enum GcnShaderAMD { + GcnShaderBadAMD = 0, // Don't use + + CubeFaceIndexAMD = 1, + CubeFaceCoordAMD = 2, + TimeAMD = 3, + + GcnShaderCountAMD +}; + +// SPV_AMD_gpu_shader_half_float +static const char* const E_SPV_AMD_gpu_shader_half_float = "SPV_AMD_gpu_shader_half_float"; + +// SPV_AMD_texture_gather_bias_lod +static const char* const E_SPV_AMD_texture_gather_bias_lod = "SPV_AMD_texture_gather_bias_lod"; + +// SPV_AMD_gpu_shader_int16 +static const char* const E_SPV_AMD_gpu_shader_int16 = "SPV_AMD_gpu_shader_int16"; + +// SPV_AMD_shader_image_load_store_lod +static const char* const E_SPV_AMD_shader_image_load_store_lod = "SPV_AMD_shader_image_load_store_lod"; + +// SPV_AMD_shader_fragment_mask +static const char* const E_SPV_AMD_shader_fragment_mask = "SPV_AMD_shader_fragment_mask"; + +// SPV_AMD_gpu_shader_half_float_fetch +static const char* const E_SPV_AMD_gpu_shader_half_float_fetch = "SPV_AMD_gpu_shader_half_float_fetch"; + +#endif // #ifndef GLSLextAMD_H diff --git a/android/arm64-v8a/include/glslang/SPIRV/GLSL.ext.EXT.h b/android/arm64-v8a/include/glslang/SPIRV/GLSL.ext.EXT.h new file mode 100644 index 00000000..40164b61 --- /dev/null +++ b/android/arm64-v8a/include/glslang/SPIRV/GLSL.ext.EXT.h @@ -0,0 +1,39 @@ +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextEXT_H +#define GLSLextEXT_H + +static const int GLSLextEXTVersion = 100; +static const int GLSLextEXTRevision = 2; + +static const char* const E_SPV_EXT_shader_stencil_export = "SPV_EXT_shader_stencil_export"; +static const char* const E_SPV_EXT_shader_viewport_index_layer = "SPV_EXT_shader_viewport_index_layer"; +static const char* const E_SPV_EXT_fragment_fully_covered = "SPV_EXT_fragment_fully_covered"; +static const char* const E_SPV_EXT_fragment_invocation_density = "SPV_EXT_fragment_invocation_density"; +static const char* const E_SPV_EXT_demote_to_helper_invocation = "SPV_EXT_demote_to_helper_invocation"; + +#endif // #ifndef GLSLextEXT_H diff --git a/android/arm64-v8a/include/glslang/SPIRV/GLSL.ext.KHR.h b/android/arm64-v8a/include/glslang/SPIRV/GLSL.ext.KHR.h new file mode 100644 index 00000000..d783a8f2 --- /dev/null +++ b/android/arm64-v8a/include/glslang/SPIRV/GLSL.ext.KHR.h @@ -0,0 +1,51 @@ +/* +** Copyright (c) 2014-2020 The Khronos Group Inc. +** Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextKHR_H +#define GLSLextKHR_H + +static const int GLSLextKHRVersion = 100; +static const int GLSLextKHRRevision = 2; + +static const char* const E_SPV_KHR_shader_ballot = "SPV_KHR_shader_ballot"; +static const char* const E_SPV_KHR_subgroup_vote = "SPV_KHR_subgroup_vote"; +static const char* const E_SPV_KHR_device_group = "SPV_KHR_device_group"; +static const char* const E_SPV_KHR_multiview = "SPV_KHR_multiview"; +static const char* const E_SPV_KHR_shader_draw_parameters = "SPV_KHR_shader_draw_parameters"; +static const char* const E_SPV_KHR_16bit_storage = "SPV_KHR_16bit_storage"; +static const char* const E_SPV_KHR_8bit_storage = "SPV_KHR_8bit_storage"; +static const char* const E_SPV_KHR_storage_buffer_storage_class = "SPV_KHR_storage_buffer_storage_class"; +static const char* const E_SPV_KHR_post_depth_coverage = "SPV_KHR_post_depth_coverage"; +static const char* const E_SPV_KHR_vulkan_memory_model = "SPV_KHR_vulkan_memory_model"; +static const char* const E_SPV_EXT_physical_storage_buffer = "SPV_EXT_physical_storage_buffer"; +static const char* const E_SPV_KHR_physical_storage_buffer = "SPV_KHR_physical_storage_buffer"; +static const char* const E_SPV_EXT_fragment_shader_interlock = "SPV_EXT_fragment_shader_interlock"; +static const char* const E_SPV_KHR_shader_clock = "SPV_KHR_shader_clock"; +static const char* const E_SPV_KHR_non_semantic_info = "SPV_KHR_non_semantic_info"; +static const char* const E_SPV_KHR_ray_tracing = "SPV_KHR_ray_tracing"; +static const char* const E_SPV_KHR_ray_query = "SPV_KHR_ray_query"; +#endif // #ifndef GLSLextKHR_H diff --git a/android/arm64-v8a/include/glslang/SPIRV/GLSL.ext.NV.h b/android/arm64-v8a/include/glslang/SPIRV/GLSL.ext.NV.h new file mode 100644 index 00000000..50146da1 --- /dev/null +++ b/android/arm64-v8a/include/glslang/SPIRV/GLSL.ext.NV.h @@ -0,0 +1,81 @@ +/* +** Copyright (c) 2014-2017 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextNV_H +#define GLSLextNV_H + +enum BuiltIn; +enum Decoration; +enum Op; +enum Capability; + +static const int GLSLextNVVersion = 100; +static const int GLSLextNVRevision = 11; + +//SPV_NV_sample_mask_override_coverage +const char* const E_SPV_NV_sample_mask_override_coverage = "SPV_NV_sample_mask_override_coverage"; + +//SPV_NV_geometry_shader_passthrough +const char* const E_SPV_NV_geometry_shader_passthrough = "SPV_NV_geometry_shader_passthrough"; + +//SPV_NV_viewport_array2 +const char* const E_SPV_NV_viewport_array2 = "SPV_NV_viewport_array2"; +const char* const E_ARB_shader_viewport_layer_array = "SPV_ARB_shader_viewport_layer_array"; + +//SPV_NV_stereo_view_rendering +const char* const E_SPV_NV_stereo_view_rendering = "SPV_NV_stereo_view_rendering"; + +//SPV_NVX_multiview_per_view_attributes +const char* const E_SPV_NVX_multiview_per_view_attributes = "SPV_NVX_multiview_per_view_attributes"; + +//SPV_NV_shader_subgroup_partitioned +const char* const E_SPV_NV_shader_subgroup_partitioned = "SPV_NV_shader_subgroup_partitioned"; + +//SPV_NV_fragment_shader_barycentric +const char* const E_SPV_NV_fragment_shader_barycentric = "SPV_NV_fragment_shader_barycentric"; + +//SPV_NV_compute_shader_derivatives +const char* const E_SPV_NV_compute_shader_derivatives = "SPV_NV_compute_shader_derivatives"; + +//SPV_NV_shader_image_footprint +const char* const E_SPV_NV_shader_image_footprint = "SPV_NV_shader_image_footprint"; + +//SPV_NV_mesh_shader +const char* const E_SPV_NV_mesh_shader = "SPV_NV_mesh_shader"; + +//SPV_NV_raytracing +const char* const E_SPV_NV_ray_tracing = "SPV_NV_ray_tracing"; + +//SPV_NV_shading_rate +const char* const E_SPV_NV_shading_rate = "SPV_NV_shading_rate"; + +//SPV_NV_cooperative_matrix +const char* const E_SPV_NV_cooperative_matrix = "SPV_NV_cooperative_matrix"; + +//SPV_NV_shader_sm_builtins +const char* const E_SPV_NV_shader_sm_builtins = "SPV_NV_shader_sm_builtins"; + +#endif // #ifndef GLSLextNV_H diff --git a/android/arm64-v8a/include/glslang/SPIRV/GLSL.std.450.h b/android/arm64-v8a/include/glslang/SPIRV/GLSL.std.450.h new file mode 100644 index 00000000..df31092b --- /dev/null +++ b/android/arm64-v8a/include/glslang/SPIRV/GLSL.std.450.h @@ -0,0 +1,131 @@ +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLstd450_H +#define GLSLstd450_H + +static const int GLSLstd450Version = 100; +static const int GLSLstd450Revision = 1; + +enum GLSLstd450 { + GLSLstd450Bad = 0, // Don't use + + GLSLstd450Round = 1, + GLSLstd450RoundEven = 2, + GLSLstd450Trunc = 3, + GLSLstd450FAbs = 4, + GLSLstd450SAbs = 5, + GLSLstd450FSign = 6, + GLSLstd450SSign = 7, + GLSLstd450Floor = 8, + GLSLstd450Ceil = 9, + GLSLstd450Fract = 10, + + GLSLstd450Radians = 11, + GLSLstd450Degrees = 12, + GLSLstd450Sin = 13, + GLSLstd450Cos = 14, + GLSLstd450Tan = 15, + GLSLstd450Asin = 16, + GLSLstd450Acos = 17, + GLSLstd450Atan = 18, + GLSLstd450Sinh = 19, + GLSLstd450Cosh = 20, + GLSLstd450Tanh = 21, + GLSLstd450Asinh = 22, + GLSLstd450Acosh = 23, + GLSLstd450Atanh = 24, + GLSLstd450Atan2 = 25, + + GLSLstd450Pow = 26, + GLSLstd450Exp = 27, + GLSLstd450Log = 28, + GLSLstd450Exp2 = 29, + GLSLstd450Log2 = 30, + GLSLstd450Sqrt = 31, + GLSLstd450InverseSqrt = 32, + + GLSLstd450Determinant = 33, + GLSLstd450MatrixInverse = 34, + + GLSLstd450Modf = 35, // second operand needs an OpVariable to write to + GLSLstd450ModfStruct = 36, // no OpVariable operand + GLSLstd450FMin = 37, + GLSLstd450UMin = 38, + GLSLstd450SMin = 39, + GLSLstd450FMax = 40, + GLSLstd450UMax = 41, + GLSLstd450SMax = 42, + GLSLstd450FClamp = 43, + GLSLstd450UClamp = 44, + GLSLstd450SClamp = 45, + GLSLstd450FMix = 46, + GLSLstd450IMix = 47, // Reserved + GLSLstd450Step = 48, + GLSLstd450SmoothStep = 49, + + GLSLstd450Fma = 50, + GLSLstd450Frexp = 51, // second operand needs an OpVariable to write to + GLSLstd450FrexpStruct = 52, // no OpVariable operand + GLSLstd450Ldexp = 53, + + GLSLstd450PackSnorm4x8 = 54, + GLSLstd450PackUnorm4x8 = 55, + GLSLstd450PackSnorm2x16 = 56, + GLSLstd450PackUnorm2x16 = 57, + GLSLstd450PackHalf2x16 = 58, + GLSLstd450PackDouble2x32 = 59, + GLSLstd450UnpackSnorm2x16 = 60, + GLSLstd450UnpackUnorm2x16 = 61, + GLSLstd450UnpackHalf2x16 = 62, + GLSLstd450UnpackSnorm4x8 = 63, + GLSLstd450UnpackUnorm4x8 = 64, + GLSLstd450UnpackDouble2x32 = 65, + + GLSLstd450Length = 66, + GLSLstd450Distance = 67, + GLSLstd450Cross = 68, + GLSLstd450Normalize = 69, + GLSLstd450FaceForward = 70, + GLSLstd450Reflect = 71, + GLSLstd450Refract = 72, + + GLSLstd450FindILsb = 73, + GLSLstd450FindSMsb = 74, + GLSLstd450FindUMsb = 75, + + GLSLstd450InterpolateAtCentroid = 76, + GLSLstd450InterpolateAtSample = 77, + GLSLstd450InterpolateAtOffset = 78, + + GLSLstd450NMin = 79, + GLSLstd450NMax = 80, + GLSLstd450NClamp = 81, + + GLSLstd450Count +}; + +#endif // #ifndef GLSLstd450_H diff --git a/android/arm64-v8a/include/glslang/SPIRV/GlslangToSpv.h b/android/arm64-v8a/include/glslang/SPIRV/GlslangToSpv.h new file mode 100644 index 00000000..3907be43 --- /dev/null +++ b/android/arm64-v8a/include/glslang/SPIRV/GlslangToSpv.h @@ -0,0 +1,61 @@ +// +// Copyright (C) 2014 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#pragma once + +#if defined(_MSC_VER) && _MSC_VER >= 1900 + #pragma warning(disable : 4464) // relative include path contains '..' +#endif + +#include "SpvTools.h" +#include "glslang/Include/intermediate.h" + +#include +#include + +#include "Logger.h" + +namespace glslang { + +void GetSpirvVersion(std::string&); +int GetSpirvGeneratorVersion(); +void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, + SpvOptions* options = nullptr); +void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger* logger, SpvOptions* options = nullptr); +void OutputSpvBin(const std::vector& spirv, const char* baseName); +void OutputSpvHex(const std::vector& spirv, const char* baseName, const char* varName); + +} diff --git a/android/arm64-v8a/include/glslang/SPIRV/Logger.h b/android/arm64-v8a/include/glslang/SPIRV/Logger.h new file mode 100644 index 00000000..411367c0 --- /dev/null +++ b/android/arm64-v8a/include/glslang/SPIRV/Logger.h @@ -0,0 +1,83 @@ +// +// Copyright (C) 2016 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef GLSLANG_SPIRV_LOGGER_H +#define GLSLANG_SPIRV_LOGGER_H + +#include +#include + +namespace spv { + +// A class for holding all SPIR-V build status messages, including +// missing/TBD functionalities, warnings, and errors. +class SpvBuildLogger { +public: + SpvBuildLogger() {} + +#ifdef GLSLANG_WEB + void tbdFunctionality(const std::string& f) { } + void missingFunctionality(const std::string& f) { } + void warning(const std::string& w) { } + void error(const std::string& e) { errors.push_back(e); } + std::string getAllMessages() { return ""; } +#else + + // Registers a TBD functionality. + void tbdFunctionality(const std::string& f); + // Registers a missing functionality. + void missingFunctionality(const std::string& f); + + // Logs a warning. + void warning(const std::string& w) { warnings.push_back(w); } + // Logs an error. + void error(const std::string& e) { errors.push_back(e); } + + // Returns all messages accumulated in the order of: + // TBD functionalities, missing functionalities, warnings, errors. + std::string getAllMessages() const; +#endif + +private: + SpvBuildLogger(const SpvBuildLogger&); + + std::vector tbdFeatures; + std::vector missingFeatures; + std::vector warnings; + std::vector errors; +}; + +} // end spv namespace + +#endif // GLSLANG_SPIRV_LOGGER_H diff --git a/android/arm64-v8a/include/glslang/SPIRV/NonSemanticDebugPrintf.h b/android/arm64-v8a/include/glslang/SPIRV/NonSemanticDebugPrintf.h new file mode 100644 index 00000000..83796d75 --- /dev/null +++ b/android/arm64-v8a/include/glslang/SPIRV/NonSemanticDebugPrintf.h @@ -0,0 +1,50 @@ +// Copyright (c) 2020 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and/or associated documentation files (the +// "Materials"), to deal in the Materials without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Materials, and to +// permit persons to whom the Materials are furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS +// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS +// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT +// https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +// + +#ifndef SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ +#define SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + NonSemanticDebugPrintfRevision = 1, + NonSemanticDebugPrintfRevision_BitWidthPadding = 0x7fffffff +}; + +enum NonSemanticDebugPrintfInstructions { + NonSemanticDebugPrintfDebugPrintf = 1, + NonSemanticDebugPrintfInstructionsMax = 0x7fffffff +}; + + +#ifdef __cplusplus +} +#endif + +#endif // SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ diff --git a/android/arm64-v8a/include/glslang/SPIRV/SPVRemapper.h b/android/arm64-v8a/include/glslang/SPIRV/SPVRemapper.h new file mode 100644 index 00000000..d6b9c346 --- /dev/null +++ b/android/arm64-v8a/include/glslang/SPIRV/SPVRemapper.h @@ -0,0 +1,304 @@ +// +// Copyright (C) 2015 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef SPIRVREMAPPER_H +#define SPIRVREMAPPER_H + +#include +#include +#include +#include + +namespace spv { + +// MSVC defines __cplusplus as an older value, even when it supports almost all of 11. +// We handle that here by making our own symbol. +#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1700) +# define use_cpp11 1 +#endif + +class spirvbin_base_t +{ +public: + enum Options { + NONE = 0, + STRIP = (1<<0), + MAP_TYPES = (1<<1), + MAP_NAMES = (1<<2), + MAP_FUNCS = (1<<3), + DCE_FUNCS = (1<<4), + DCE_VARS = (1<<5), + DCE_TYPES = (1<<6), + OPT_LOADSTORE = (1<<7), + OPT_FWD_LS = (1<<8), // EXPERIMENTAL: PRODUCES INVALID SCHEMA-0 SPIRV + MAP_ALL = (MAP_TYPES | MAP_NAMES | MAP_FUNCS), + DCE_ALL = (DCE_FUNCS | DCE_VARS | DCE_TYPES), + OPT_ALL = (OPT_LOADSTORE), + + ALL_BUT_STRIP = (MAP_ALL | DCE_ALL | OPT_ALL), + DO_EVERYTHING = (STRIP | ALL_BUT_STRIP) + }; +}; + +} // namespace SPV + +#if !defined (use_cpp11) +#include +#include + +namespace spv { +class spirvbin_t : public spirvbin_base_t +{ +public: + spirvbin_t(int /*verbose = 0*/) { } + + void remap(std::vector& /*spv*/, unsigned int /*opts = 0*/) + { + printf("Tool not compiled for C++11, which is required for SPIR-V remapping.\n"); + exit(5); + } +}; + +} // namespace SPV + +#else // defined (use_cpp11) + +#include +#include +#include +#include +#include +#include +#include + +#include "spirv.hpp" +#include "spvIR.h" + +namespace spv { + +// class to hold SPIR-V binary data for remapping, DCE, and debug stripping +class spirvbin_t : public spirvbin_base_t +{ +public: + spirvbin_t(int verbose = 0) : entryPoint(spv::NoResult), largestNewId(0), verbose(verbose), errorLatch(false) + { } + + virtual ~spirvbin_t() { } + + // remap on an existing binary in memory + void remap(std::vector& spv, std::uint32_t opts = DO_EVERYTHING); + + // Type for error/log handler functions + typedef std::function errorfn_t; + typedef std::function logfn_t; + + // Register error/log handling functions (can be lambda fn / functor / etc) + static void registerErrorHandler(errorfn_t handler) { errorHandler = handler; } + static void registerLogHandler(logfn_t handler) { logHandler = handler; } + +protected: + // This can be overridden to provide other message behavior if needed + virtual void msg(int minVerbosity, int indent, const std::string& txt) const; + +private: + // Local to global, or global to local ID map + typedef std::unordered_map idmap_t; + typedef std::unordered_set idset_t; + typedef std::unordered_map blockmap_t; + + void remap(std::uint32_t opts = DO_EVERYTHING); + + // Map of names to IDs + typedef std::unordered_map namemap_t; + + typedef std::uint32_t spirword_t; + + typedef std::pair range_t; + typedef std::function idfn_t; + typedef std::function instfn_t; + + // Special Values for ID map: + static const spv::Id unmapped; // unchanged from default value + static const spv::Id unused; // unused ID + static const int header_size; // SPIR header = 5 words + + class id_iterator_t; + + // For mapping type entries between different shaders + typedef std::vector typeentry_t; + typedef std::map globaltypes_t; + + // A set that preserves position order, and a reverse map + typedef std::set posmap_t; + typedef std::unordered_map posmap_rev_t; + + // Maps and ID to the size of its base type, if known. + typedef std::unordered_map typesize_map_t; + + // handle error + void error(const std::string& txt) const { errorLatch = true; errorHandler(txt); } + + bool isConstOp(spv::Op opCode) const; + bool isTypeOp(spv::Op opCode) const; + bool isStripOp(spv::Op opCode) const; + bool isFlowCtrl(spv::Op opCode) const; + range_t literalRange(spv::Op opCode) const; + range_t typeRange(spv::Op opCode) const; + range_t constRange(spv::Op opCode) const; + unsigned typeSizeInWords(spv::Id id) const; + unsigned idTypeSizeInWords(spv::Id id) const; + + spv::Id& asId(unsigned word) { return spv[word]; } + const spv::Id& asId(unsigned word) const { return spv[word]; } + spv::Op asOpCode(unsigned word) const { return opOpCode(spv[word]); } + std::uint32_t asOpCodeHash(unsigned word); + spv::Decoration asDecoration(unsigned word) const { return spv::Decoration(spv[word]); } + unsigned asWordCount(unsigned word) const { return opWordCount(spv[word]); } + spv::Id asTypeConstId(unsigned word) const { return asId(word + (isTypeOp(asOpCode(word)) ? 1 : 2)); } + unsigned idPos(spv::Id id) const; + + static unsigned opWordCount(spirword_t data) { return data >> spv::WordCountShift; } + static spv::Op opOpCode(spirword_t data) { return spv::Op(data & spv::OpCodeMask); } + + // Header access & set methods + spirword_t magic() const { return spv[0]; } // return magic number + spirword_t bound() const { return spv[3]; } // return Id bound from header + spirword_t bound(spirword_t b) { return spv[3] = b; } + spirword_t genmagic() const { return spv[2]; } // generator magic + spirword_t genmagic(spirword_t m) { return spv[2] = m; } + spirword_t schemaNum() const { return spv[4]; } // schema number from header + + // Mapping fns: get + spv::Id localId(spv::Id id) const { return idMapL[id]; } + + // Mapping fns: set + inline spv::Id localId(spv::Id id, spv::Id newId); + void countIds(spv::Id id); + + // Return next unused new local ID. + // NOTE: boost::dynamic_bitset would be more efficient due to find_next(), + // which std::vector doens't have. + inline spv::Id nextUnusedId(spv::Id id); + + void buildLocalMaps(); + std::string literalString(unsigned word) const; // Return literal as a std::string + int literalStringWords(const std::string& str) const { return (int(str.size())+4)/4; } + + bool isNewIdMapped(spv::Id newId) const { return isMapped(newId); } + bool isOldIdUnmapped(spv::Id oldId) const { return localId(oldId) == unmapped; } + bool isOldIdUnused(spv::Id oldId) const { return localId(oldId) == unused; } + bool isOldIdMapped(spv::Id oldId) const { return !isOldIdUnused(oldId) && !isOldIdUnmapped(oldId); } + bool isFunction(spv::Id oldId) const { return fnPos.find(oldId) != fnPos.end(); } + + // bool matchType(const globaltypes_t& globalTypes, spv::Id lt, spv::Id gt) const; + // spv::Id findType(const globaltypes_t& globalTypes, spv::Id lt) const; + std::uint32_t hashType(unsigned typeStart) const; + + spirvbin_t& process(instfn_t, idfn_t, unsigned begin = 0, unsigned end = 0); + int processInstruction(unsigned word, instfn_t, idfn_t); + + void validate() const; + void mapTypeConst(); + void mapFnBodies(); + void optLoadStore(); + void dceFuncs(); + void dceVars(); + void dceTypes(); + void mapNames(); + void foldIds(); // fold IDs to smallest space + void forwardLoadStores(); // load store forwarding (EXPERIMENTAL) + void offsetIds(); // create relative offset IDs + + void applyMap(); // remap per local name map + void mapRemainder(); // map any IDs we haven't touched yet + void stripDebug(); // strip all debug info + void stripDeadRefs(); // strips debug info for now-dead references after DCE + void strip(); // remove debug symbols + + std::vector spv; // SPIR words + + namemap_t nameMap; // ID names from OpName + + // Since we want to also do binary ops, we can't use std::vector. we could use + // boost::dynamic_bitset, but we're trying to avoid a boost dependency. + typedef std::uint64_t bits_t; + std::vector mapped; // which new IDs have been mapped + static const int mBits = sizeof(bits_t) * 4; + + bool isMapped(spv::Id id) const { return id < maxMappedId() && ((mapped[id/mBits] & (1LL<<(id%mBits))) != 0); } + void setMapped(spv::Id id) { resizeMapped(id); mapped[id/mBits] |= (1LL<<(id%mBits)); } + void resizeMapped(spv::Id id) { if (id >= maxMappedId()) mapped.resize(id/mBits+1, 0); } + size_t maxMappedId() const { return mapped.size() * mBits; } + + // Add a strip range for a given instruction starting at 'start' + // Note: avoiding brace initializers to please older versions os MSVC. + void stripInst(unsigned start) { stripRange.push_back(range_t(start, start + asWordCount(start))); } + + // Function start and end. use unordered_map because we'll have + // many fewer functions than IDs. + std::unordered_map fnPos; + + // Which functions are called, anywhere in the module, with a call count + std::unordered_map fnCalls; + + posmap_t typeConstPos; // word positions that define types & consts (ordered) + posmap_rev_t idPosR; // reverse map from IDs to positions + typesize_map_t idTypeSizeMap; // maps each ID to its type size, if known. + + std::vector idMapL; // ID {M}ap from {L}ocal to {G}lobal IDs + + spv::Id entryPoint; // module entry point + spv::Id largestNewId; // biggest new ID we have mapped anything to + + // Sections of the binary to strip, given as [begin,end) + std::vector stripRange; + + // processing options: + std::uint32_t options; + int verbose; // verbosity level + + // Error latch: this is set if the error handler is ever executed. It would be better to + // use a try/catch block and throw, but that's not desired for certain environments, so + // this is the alternative. + mutable bool errorLatch; + + static errorfn_t errorHandler; + static logfn_t logHandler; +}; + +} // namespace SPV + +#endif // defined (use_cpp11) +#endif // SPIRVREMAPPER_H diff --git a/android/arm64-v8a/include/glslang/SPIRV/SpvBuilder.h b/android/arm64-v8a/include/glslang/SPIRV/SpvBuilder.h new file mode 100644 index 00000000..71b90d60 --- /dev/null +++ b/android/arm64-v8a/include/glslang/SPIRV/SpvBuilder.h @@ -0,0 +1,838 @@ +// +// Copyright (C) 2014-2015 LunarG, Inc. +// Copyright (C) 2015-2020 Google, Inc. +// Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// "Builder" is an interface to fully build SPIR-V IR. Allocate one of +// these to build (a thread safe) internal SPIR-V representation (IR), +// and then dump it as a binary stream according to the SPIR-V specification. +// +// A Builder has a 1:1 relationship with a SPIR-V module. +// + +#pragma once +#ifndef SpvBuilder_H +#define SpvBuilder_H + +#include "Logger.h" +#include "spirv.hpp" +#include "spvIR.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace spv { + +typedef enum { + Spv_1_0 = (1 << 16), + Spv_1_1 = (1 << 16) | (1 << 8), + Spv_1_2 = (1 << 16) | (2 << 8), + Spv_1_3 = (1 << 16) | (3 << 8), + Spv_1_4 = (1 << 16) | (4 << 8), + Spv_1_5 = (1 << 16) | (5 << 8), +} SpvVersion; + +class Builder { +public: + Builder(unsigned int spvVersion, unsigned int userNumber, SpvBuildLogger* logger); + virtual ~Builder(); + + static const int maxMatrixSize = 4; + + unsigned int getSpvVersion() const { return spvVersion; } + + void setSource(spv::SourceLanguage lang, int version) + { + source = lang; + sourceVersion = version; + } + spv::Id getStringId(const std::string& str) + { + auto sItr = stringIds.find(str); + if (sItr != stringIds.end()) + return sItr->second; + spv::Id strId = getUniqueId(); + Instruction* fileString = new Instruction(strId, NoType, OpString); + const char* file_c_str = str.c_str(); + fileString->addStringOperand(file_c_str); + strings.push_back(std::unique_ptr(fileString)); + module.mapInstruction(fileString); + stringIds[file_c_str] = strId; + return strId; + } + void setSourceFile(const std::string& file) + { + sourceFileStringId = getStringId(file); + } + void setSourceText(const std::string& text) { sourceText = text; } + void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); } + void addModuleProcessed(const std::string& p) { moduleProcesses.push_back(p.c_str()); } + void setEmitOpLines() { emitOpLines = true; } + void addExtension(const char* ext) { extensions.insert(ext); } + void removeExtension(const char* ext) + { + extensions.erase(ext); + } + void addIncorporatedExtension(const char* ext, SpvVersion incorporatedVersion) + { + if (getSpvVersion() < static_cast(incorporatedVersion)) + addExtension(ext); + } + void promoteIncorporatedExtension(const char* baseExt, const char* promoExt, SpvVersion incorporatedVersion) + { + removeExtension(baseExt); + addIncorporatedExtension(promoExt, incorporatedVersion); + } + void addInclude(const std::string& name, const std::string& text) + { + spv::Id incId = getStringId(name); + includeFiles[incId] = &text; + } + Id import(const char*); + void setMemoryModel(spv::AddressingModel addr, spv::MemoryModel mem) + { + addressModel = addr; + memoryModel = mem; + } + + void addCapability(spv::Capability cap) { capabilities.insert(cap); } + + // To get a new for anything needing a new one. + Id getUniqueId() { return ++uniqueId; } + + // To get a set of new s, e.g., for a set of function parameters + Id getUniqueIds(int numIds) + { + Id id = uniqueId + 1; + uniqueId += numIds; + return id; + } + + // Generate OpLine for non-filename-based #line directives (ie no filename + // seen yet): Log the current line, and if different than the last one, + // issue a new OpLine using the new line and current source file name. + void setLine(int line); + + // If filename null, generate OpLine for non-filename-based line directives, + // else do filename-based: Log the current line and file, and if different + // than the last one, issue a new OpLine using the new line and file + // name. + void setLine(int line, const char* filename); + // Low-level OpLine. See setLine() for a layered helper. + void addLine(Id fileName, int line, int column); + + // For creating new types (will return old type if the requested one was already made). + Id makeVoidType(); + Id makeBoolType(); + Id makePointer(StorageClass, Id pointee); + Id makeForwardPointer(StorageClass); + Id makePointerFromForwardPointer(StorageClass, Id forwardPointerType, Id pointee); + Id makeIntegerType(int width, bool hasSign); // generic + Id makeIntType(int width) { return makeIntegerType(width, true); } + Id makeUintType(int width) { return makeIntegerType(width, false); } + Id makeFloatType(int width); + Id makeStructType(const std::vector& members, const char*); + Id makeStructResultType(Id type0, Id type1); + Id makeVectorType(Id component, int size); + Id makeMatrixType(Id component, int cols, int rows); + Id makeArrayType(Id element, Id sizeId, int stride); // 0 stride means no stride decoration + Id makeRuntimeArray(Id element); + Id makeFunctionType(Id returnType, const std::vector& paramTypes); + Id makeImageType(Id sampledType, Dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format); + Id makeSamplerType(); + Id makeSampledImageType(Id imageType); + Id makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols); + + // accelerationStructureNV type + Id makeAccelerationStructureType(); + // rayQueryEXT type + Id makeRayQueryType(); + + // For querying about types. + Id getTypeId(Id resultId) const { return module.getTypeId(resultId); } + Id getDerefTypeId(Id resultId) const; + Op getOpCode(Id id) const { return module.getInstruction(id)->getOpCode(); } + Op getTypeClass(Id typeId) const { return getOpCode(typeId); } + Op getMostBasicTypeClass(Id typeId) const; + int getNumComponents(Id resultId) const { return getNumTypeComponents(getTypeId(resultId)); } + int getNumTypeConstituents(Id typeId) const; + int getNumTypeComponents(Id typeId) const { return getNumTypeConstituents(typeId); } + Id getScalarTypeId(Id typeId) const; + Id getContainedTypeId(Id typeId) const; + Id getContainedTypeId(Id typeId, int) const; + StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); } + ImageFormat getImageTypeFormat(Id typeId) const + { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); } + + bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); } + bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); } + bool isVector(Id resultId) const { return isVectorType(getTypeId(resultId)); } + bool isMatrix(Id resultId) const { return isMatrixType(getTypeId(resultId)); } + bool isCooperativeMatrix(Id resultId)const { return isCooperativeMatrixType(getTypeId(resultId)); } + bool isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); } + bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); } + + bool isBoolType(Id typeId) + { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); } + bool isIntType(Id typeId) const + { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; } + bool isUintType(Id typeId) const + { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; } + bool isFloatType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat; } + bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; } + bool isScalarType(Id typeId) const + { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt || + getTypeClass(typeId) == OpTypeBool; } + bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; } + bool isMatrixType(Id typeId) const { return getTypeClass(typeId) == OpTypeMatrix; } + bool isStructType(Id typeId) const { return getTypeClass(typeId) == OpTypeStruct; } + bool isArrayType(Id typeId) const { return getTypeClass(typeId) == OpTypeArray; } +#ifdef GLSLANG_WEB + bool isCooperativeMatrixType(Id typeId)const { return false; } +#else + bool isCooperativeMatrixType(Id typeId)const { return getTypeClass(typeId) == OpTypeCooperativeMatrixNV; } +#endif + bool isAggregateType(Id typeId) const + { return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); } + bool isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; } + bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; } + bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; } + bool containsType(Id typeId, Op typeOp, unsigned int width) const; + bool containsPhysicalStorageBufferOrArray(Id typeId) const; + + bool isConstantOpCode(Op opcode) const; + bool isSpecConstantOpCode(Op opcode) const; + bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); } + bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; } + bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); } + unsigned int getConstantScalar(Id resultId) const + { return module.getInstruction(resultId)->getImmediateOperand(0); } + StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); } + + int getScalarTypeWidth(Id typeId) const + { + Id scalarTypeId = getScalarTypeId(typeId); + assert(getTypeClass(scalarTypeId) == OpTypeInt || getTypeClass(scalarTypeId) == OpTypeFloat); + return module.getInstruction(scalarTypeId)->getImmediateOperand(0); + } + + int getTypeNumColumns(Id typeId) const + { + assert(isMatrixType(typeId)); + return getNumTypeConstituents(typeId); + } + int getNumColumns(Id resultId) const { return getTypeNumColumns(getTypeId(resultId)); } + int getTypeNumRows(Id typeId) const + { + assert(isMatrixType(typeId)); + return getNumTypeComponents(getContainedTypeId(typeId)); + } + int getNumRows(Id resultId) const { return getTypeNumRows(getTypeId(resultId)); } + + Dim getTypeDimensionality(Id typeId) const + { + assert(isImageType(typeId)); + return (Dim)module.getInstruction(typeId)->getImmediateOperand(1); + } + Id getImageType(Id resultId) const + { + Id typeId = getTypeId(resultId); + assert(isImageType(typeId) || isSampledImageType(typeId)); + return isSampledImageType(typeId) ? module.getInstruction(typeId)->getIdOperand(0) : typeId; + } + bool isArrayedImageType(Id typeId) const + { + assert(isImageType(typeId)); + return module.getInstruction(typeId)->getImmediateOperand(3) != 0; + } + + // For making new constants (will return old constant if the requested one was already made). + Id makeBoolConstant(bool b, bool specConstant = false); + Id makeInt8Constant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); } + Id makeUint8Constant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(8), u, specConstant); } + Id makeInt16Constant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(16), (unsigned)i, specConstant); } + Id makeUint16Constant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(16), u, specConstant); } + Id makeIntConstant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); } + Id makeUintConstant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(32), u, specConstant); } + Id makeInt64Constant(long long i, bool specConstant = false) + { return makeInt64Constant(makeIntType(64), (unsigned long long)i, specConstant); } + Id makeUint64Constant(unsigned long long u, bool specConstant = false) + { return makeInt64Constant(makeUintType(64), u, specConstant); } + Id makeFloatConstant(float f, bool specConstant = false); + Id makeDoubleConstant(double d, bool specConstant = false); + Id makeFloat16Constant(float f16, bool specConstant = false); + Id makeFpConstant(Id type, double d, bool specConstant = false); + + // Turn the array of constants into a proper spv constant of the requested type. + Id makeCompositeConstant(Id type, const std::vector& comps, bool specConst = false); + + // Methods for adding information outside the CFG. + Instruction* addEntryPoint(ExecutionModel, Function*, const char* name); + void addExecutionMode(Function*, ExecutionMode mode, int value1 = -1, int value2 = -1, int value3 = -1); + void addName(Id, const char* name); + void addMemberName(Id, int member, const char* name); + void addDecoration(Id, Decoration, int num = -1); + void addDecoration(Id, Decoration, const char*); + void addDecorationId(Id id, Decoration, Id idDecoration); + void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1); + void addMemberDecoration(Id, unsigned int member, Decoration, const char*); + + // At the end of what block do the next create*() instructions go? + void setBuildPoint(Block* bp) { buildPoint = bp; } + Block* getBuildPoint() const { return buildPoint; } + + // Make the entry-point function. The returned pointer is only valid + // for the lifetime of this builder. + Function* makeEntryPoint(const char*); + + // Make a shader-style function, and create its entry block if entry is non-zero. + // Return the function, pass back the entry. + // The returned pointer is only valid for the lifetime of this builder. + Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, + const std::vector& paramTypes, const std::vector>& precisions, Block **entry = 0); + + // Create a return. An 'implicit' return is one not appearing in the source + // code. In the case of an implicit return, no post-return block is inserted. + void makeReturn(bool implicit, Id retVal = 0); + + // Generate all the code needed to finish up a function. + void leaveFunction(); + + // Create a discard. + void makeDiscard(); + + // Create a global or function local or IO variable. + Id createVariable(StorageClass, Id type, const char* name = 0, Id initializer = NoResult); + + // Create an intermediate with an undefined value. + Id createUndefined(Id type); + + // Store into an Id and return the l-value + void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + + // Load from an Id and return it + Id createLoad(Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + + // Create an OpAccessChain instruction + Id createAccessChain(StorageClass, Id base, const std::vector& offsets); + + // Create an OpArrayLength instruction + Id createArrayLength(Id base, unsigned int member); + + // Create an OpCooperativeMatrixLengthNV instruction + Id createCooperativeMatrixLength(Id type); + + // Create an OpCompositeExtract instruction + Id createCompositeExtract(Id composite, Id typeId, unsigned index); + Id createCompositeExtract(Id composite, Id typeId, const std::vector& indexes); + Id createCompositeInsert(Id object, Id composite, Id typeId, unsigned index); + Id createCompositeInsert(Id object, Id composite, Id typeId, const std::vector& indexes); + + Id createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex); + Id createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex); + + void createNoResultOp(Op); + void createNoResultOp(Op, Id operand); + void createNoResultOp(Op, const std::vector& operands); + void createNoResultOp(Op, const std::vector& operands); + void createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask); + void createMemoryBarrier(unsigned executionScope, unsigned memorySemantics); + Id createUnaryOp(Op, Id typeId, Id operand); + Id createBinOp(Op, Id typeId, Id operand1, Id operand2); + Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3); + Id createOp(Op, Id typeId, const std::vector& operands); + Id createOp(Op, Id typeId, const std::vector& operands); + Id createFunctionCall(spv::Function*, const std::vector&); + Id createSpecConstantOp(Op, Id typeId, const std::vector& operands, const std::vector& literals); + + // Take an rvalue (source) and a set of channels to extract from it to + // make a new rvalue, which is returned. + Id createRvalueSwizzle(Decoration precision, Id typeId, Id source, const std::vector& channels); + + // Take a copy of an lvalue (target) and a source of components, and set the + // source components into the lvalue where the 'channels' say to put them. + // An updated version of the target is returned. + // (No true lvalue or stores are used.) + Id createLvalueSwizzle(Id typeId, Id target, Id source, const std::vector& channels); + + // If both the id and precision are valid, the id + // gets tagged with the requested precision. + // The passed in id is always the returned id, to simplify use patterns. + Id setPrecision(Id id, Decoration precision) + { + if (precision != NoPrecision && id != NoResult) + addDecoration(id, precision); + + return id; + } + + // Can smear a scalar to a vector for the following forms: + // - promoteScalar(scalar, vector) // smear scalar to width of vector + // - promoteScalar(vector, scalar) // smear scalar to width of vector + // - promoteScalar(pointer, scalar) // smear scalar to width of what pointer points to + // - promoteScalar(scalar, scalar) // do nothing + // Other forms are not allowed. + // + // Generally, the type of 'scalar' does not need to be the same type as the components in 'vector'. + // The type of the created vector is a vector of components of the same type as the scalar. + // + // Note: One of the arguments will change, with the result coming back that way rather than + // through the return value. + void promoteScalar(Decoration precision, Id& left, Id& right); + + // Make a value by smearing the scalar to fill the type. + // vectorType should be the correct type for making a vector of scalarVal. + // (No conversions are done.) + Id smearScalar(Decoration precision, Id scalarVal, Id vectorType); + + // Create a call to a built-in function. + Id createBuiltinCall(Id resultType, Id builtins, int entryPoint, const std::vector& args); + + // List of parameters used to create a texture operation + struct TextureParameters { + Id sampler; + Id coords; + Id bias; + Id lod; + Id Dref; + Id offset; + Id offsets; + Id gradX; + Id gradY; + Id sample; + Id component; + Id texelOut; + Id lodClamp; + Id granularity; + Id coarse; + bool nonprivate; + bool volatil; + }; + + // Select the correct texture operation based on all inputs, and emit the correct instruction + Id createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, + bool noImplicit, const TextureParameters&, ImageOperandsMask); + + // Emit the OpTextureQuery* instruction that was passed in. + // Figure out the right return value and type, and return it. + Id createTextureQueryCall(Op, const TextureParameters&, bool isUnsignedResult); + + Id createSamplePositionCall(Decoration precision, Id, Id); + + Id createBitFieldExtractCall(Decoration precision, Id, Id, Id, bool isSigned); + Id createBitFieldInsertCall(Decoration precision, Id, Id, Id, Id); + + // Reduction comparison for composites: For equal and not-equal resulting in a scalar. + Id createCompositeCompare(Decoration precision, Id, Id, bool /* true if for equal, false if for not-equal */); + + // OpCompositeConstruct + Id createCompositeConstruct(Id typeId, const std::vector& constituents); + + // vector or scalar constructor + Id createConstructor(Decoration precision, const std::vector& sources, Id resultTypeId); + + // matrix constructor + Id createMatrixConstructor(Decoration precision, const std::vector& sources, Id constructee); + + // Helper to use for building nested control flow with if-then-else. + class If { + public: + If(Id condition, unsigned int ctrl, Builder& builder); + ~If() {} + + void makeBeginElse(); + void makeEndIf(); + + private: + If(const If&); + If& operator=(If&); + + Builder& builder; + Id condition; + unsigned int control; + Function* function; + Block* headerBlock; + Block* thenBlock; + Block* elseBlock; + Block* mergeBlock; + }; + + // Make a switch statement. A switch has 'numSegments' of pieces of code, not containing + // any case/default labels, all separated by one or more case/default labels. Each possible + // case value v is a jump to the caseValues[v] segment. The defaultSegment is also in this + // number space. How to compute the value is given by 'condition', as in switch(condition). + // + // The SPIR-V Builder will maintain the stack of post-switch merge blocks for nested switches. + // + // Use a defaultSegment < 0 if there is no default segment (to branch to post switch). + // + // Returns the right set of basic blocks to start each code segment with, so that the caller's + // recursion stack can hold the memory for it. + // + void makeSwitch(Id condition, unsigned int control, int numSegments, const std::vector& caseValues, + const std::vector& valueToSegment, int defaultSegment, std::vector& segmentBB); + + // Add a branch to the innermost switch's merge block. + void addSwitchBreak(); + + // Move to the next code segment, passing in the return argument in makeSwitch() + void nextSwitchSegment(std::vector& segmentBB, int segment); + + // Finish off the innermost switch. + void endSwitch(std::vector& segmentBB); + + struct LoopBlocks { + LoopBlocks(Block& head, Block& body, Block& merge, Block& continue_target) : + head(head), body(body), merge(merge), continue_target(continue_target) { } + Block &head, &body, &merge, &continue_target; + private: + LoopBlocks(); + LoopBlocks& operator=(const LoopBlocks&) = delete; + }; + + // Start a new loop and prepare the builder to generate code for it. Until + // closeLoop() is called for this loop, createLoopContinue() and + // createLoopExit() will target its corresponding blocks. + LoopBlocks& makeNewLoop(); + + // Create a new block in the function containing the build point. Memory is + // owned by the function object. + Block& makeNewBlock(); + + // Add a branch to the continue_target of the current (innermost) loop. + void createLoopContinue(); + + // Add an exit (e.g. "break") from the innermost loop that we're currently + // in. + void createLoopExit(); + + // Close the innermost loop that you're in + void closeLoop(); + + // + // Access chain design for an R-Value vs. L-Value: + // + // There is a single access chain the builder is building at + // any particular time. Such a chain can be used to either to a load or + // a store, when desired. + // + // Expressions can be r-values, l-values, or both, or only r-values: + // a[b.c].d = .... // l-value + // ... = a[b.c].d; // r-value, that also looks like an l-value + // ++a[b.c].d; // r-value and l-value + // (x + y)[2]; // r-value only, can't possibly be l-value + // + // Computing an r-value means generating code. Hence, + // r-values should only be computed when they are needed, not speculatively. + // + // Computing an l-value means saving away information for later use in the compiler, + // no code is generated until the l-value is later dereferenced. It is okay + // to speculatively generate an l-value, just not okay to speculatively dereference it. + // + // The base of the access chain (the left-most variable or expression + // from which everything is based) can be set either as an l-value + // or as an r-value. Most efficient would be to set an l-value if one + // is available. If an expression was evaluated, the resulting r-value + // can be set as the chain base. + // + // The users of this single access chain can save and restore if they + // want to nest or manage multiple chains. + // + + struct AccessChain { + Id base; // for l-values, pointer to the base object, for r-values, the base object + std::vector indexChain; + Id instr; // cache the instruction that generates this access chain + std::vector swizzle; // each std::vector element selects the next GLSL component number + Id component; // a dynamic component index, can coexist with a swizzle, + // done after the swizzle, NoResult if not present + Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied; + // NoType unless a swizzle or component is present + bool isRValue; // true if 'base' is an r-value, otherwise, base is an l-value + unsigned int alignment; // bitwise OR of alignment values passed in. Accumulates worst alignment. + // Only tracks base and (optional) component selection alignment. + + // Accumulate whether anything in the chain of structures has coherent decorations. + struct CoherentFlags { + CoherentFlags() { clear(); } +#ifdef GLSLANG_WEB + void clear() { } + bool isVolatile() const { return false; } + CoherentFlags operator |=(const CoherentFlags &other) { return *this; } +#else + bool isVolatile() const { return volatil; } + bool anyCoherent() const { + return coherent || devicecoherent || queuefamilycoherent || workgroupcoherent || + subgroupcoherent || shadercallcoherent; + } + + unsigned coherent : 1; + unsigned devicecoherent : 1; + unsigned queuefamilycoherent : 1; + unsigned workgroupcoherent : 1; + unsigned subgroupcoherent : 1; + unsigned shadercallcoherent : 1; + unsigned nonprivate : 1; + unsigned volatil : 1; + unsigned isImage : 1; + + void clear() { + coherent = 0; + devicecoherent = 0; + queuefamilycoherent = 0; + workgroupcoherent = 0; + subgroupcoherent = 0; + shadercallcoherent = 0; + nonprivate = 0; + volatil = 0; + isImage = 0; + } + + CoherentFlags operator |=(const CoherentFlags &other) { + coherent |= other.coherent; + devicecoherent |= other.devicecoherent; + queuefamilycoherent |= other.queuefamilycoherent; + workgroupcoherent |= other.workgroupcoherent; + subgroupcoherent |= other.subgroupcoherent; + shadercallcoherent |= other.shadercallcoherent; + nonprivate |= other.nonprivate; + volatil |= other.volatil; + isImage |= other.isImage; + return *this; + } +#endif + }; + CoherentFlags coherentFlags; + }; + + // + // the SPIR-V builder maintains a single active chain that + // the following methods operate on + // + + // for external save and restore + AccessChain getAccessChain() { return accessChain; } + void setAccessChain(AccessChain newChain) { accessChain = newChain; } + + // clear accessChain + void clearAccessChain(); + + // set new base as an l-value base + void setAccessChainLValue(Id lValue) + { + assert(isPointer(lValue)); + accessChain.base = lValue; + } + + // set new base value as an r-value + void setAccessChainRValue(Id rValue) + { + accessChain.isRValue = true; + accessChain.base = rValue; + } + + // push offset onto the end of the chain + void accessChainPush(Id offset, AccessChain::CoherentFlags coherentFlags, unsigned int alignment) + { + accessChain.indexChain.push_back(offset); + accessChain.coherentFlags |= coherentFlags; + accessChain.alignment |= alignment; + } + + // push new swizzle onto the end of any existing swizzle, merging into a single swizzle + void accessChainPushSwizzle(std::vector& swizzle, Id preSwizzleBaseType, + AccessChain::CoherentFlags coherentFlags, unsigned int alignment); + + // push a dynamic component selection onto the access chain, only applicable with a + // non-trivial swizzle or no swizzle + void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, + unsigned int alignment) + { + if (accessChain.swizzle.size() != 1) { + accessChain.component = component; + if (accessChain.preSwizzleBaseType == NoType) + accessChain.preSwizzleBaseType = preSwizzleBaseType; + } + accessChain.coherentFlags |= coherentFlags; + accessChain.alignment |= alignment; + } + + // use accessChain and swizzle to store value + void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + + // use accessChain and swizzle to load an r-value + Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType, + spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, + unsigned int alignment = 0); + + // Return whether or not the access chain can be represented in SPIR-V + // as an l-value. + // E.g., a[3].yx cannot be, while a[3].y and a[3].y[x] can be. + bool isSpvLvalue() const { return accessChain.swizzle.size() <= 1; } + + // get the direct pointer for an l-value + Id accessChainGetLValue(); + + // Get the inferred SPIR-V type of the result of the current access chain, + // based on the type of the base and the chain of dereferences. + Id accessChainGetInferredType(); + + // Add capabilities, extensions, remove unneeded decorations, etc., + // based on the resulting SPIR-V. + void postProcess(); + + // Prune unreachable blocks in the CFG and remove unneeded decorations. + void postProcessCFG(); + +#ifndef GLSLANG_WEB + // Add capabilities, extensions based on instructions in the module. + void postProcessFeatures(); + // Hook to visit each instruction in a block in a function + void postProcess(Instruction&); + // Hook to visit each non-32-bit sized float/int operation in a block. + void postProcessType(const Instruction&, spv::Id typeId); +#endif + + void dump(std::vector&) const; + + void createBranch(Block* block); + void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock); + void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, + const std::vector& operands); + + // Sets to generate opcode for specialization constants. + void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; } + // Sets to generate opcode for non-specialization constants (normal mode). + void setToNormalCodeGenMode() { generatingOpCodeForSpecConst = false; } + // Check if the builder is generating code for spec constants. + bool isInSpecConstCodeGenMode() { return generatingOpCodeForSpecConst; } + + protected: + Id makeIntConstant(Id typeId, unsigned value, bool specConstant); + Id makeInt64Constant(Id typeId, unsigned long long value, bool specConstant); + Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value); + Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2); + Id findCompositeConstant(Op typeClass, Id typeId, const std::vector& comps); + Id findStructConstant(Id typeId, const std::vector& comps); + Id collapseAccessChain(); + void remapDynamicSwizzle(); + void transferAccessChainSwizzle(bool dynamic); + void simplifyAccessChainSwizzle(); + void createAndSetNoPredecessorBlock(const char*); + void createSelectionMerge(Block* mergeBlock, unsigned int control); + void dumpSourceInstructions(std::vector&) const; + void dumpSourceInstructions(const spv::Id fileId, const std::string& text, std::vector&) const; + void dumpInstructions(std::vector&, const std::vector >&) const; + void dumpModuleProcesses(std::vector&) const; + spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) + const; + + unsigned int spvVersion; // the version of SPIR-V to emit in the header + SourceLanguage source; + int sourceVersion; + spv::Id sourceFileStringId; + std::string sourceText; + int currentLine; + const char* currentFile; + bool emitOpLines; + std::set extensions; + std::vector sourceExtensions; + std::vector moduleProcesses; + AddressingModel addressModel; + MemoryModel memoryModel; + std::set capabilities; + int builderNumber; + Module module; + Block* buildPoint; + Id uniqueId; + Function* entryPointFunction; + bool generatingOpCodeForSpecConst; + AccessChain accessChain; + + // special blocks of instructions for output + std::vector > strings; + std::vector > imports; + std::vector > entryPoints; + std::vector > executionModes; + std::vector > names; + std::vector > decorations; + std::vector > constantsTypesGlobals; + std::vector > externals; + std::vector > functions; + + // not output, internally used for quick & dirty canonical (unique) creation + + // map type opcodes to constant inst. + std::unordered_map> groupedConstants; + // map struct-id to constant instructions + std::unordered_map> groupedStructConstants; + // map type opcodes to type instructions + std::unordered_map> groupedTypes; + + // stack of switches + std::stack switchMerges; + + // Our loop stack. + std::stack loops; + + // map from strings to their string ids + std::unordered_map stringIds; + + // map from include file name ids to their contents + std::map includeFiles; + + // The stream for outputting warnings and errors. + SpvBuildLogger* logger; +}; // end Builder class + +}; // end spv namespace + +#endif // SpvBuilder_H diff --git a/android/arm64-v8a/include/glslang/SPIRV/SpvTools.h b/android/arm64-v8a/include/glslang/SPIRV/SpvTools.h new file mode 100644 index 00000000..59c914da --- /dev/null +++ b/android/arm64-v8a/include/glslang/SPIRV/SpvTools.h @@ -0,0 +1,82 @@ +// +// Copyright (C) 2014-2016 LunarG, Inc. +// Copyright (C) 2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Call into SPIRV-Tools to disassemble, validate, and optimize. +// + +#pragma once +#ifndef GLSLANG_SPV_TOOLS_H +#define GLSLANG_SPV_TOOLS_H + +#ifdef ENABLE_OPT +#include +#include +#endif + +#include "glslang/MachineIndependent/localintermediate.h" +#include "Logger.h" + +namespace glslang { + +struct SpvOptions { + SpvOptions() : generateDebugInfo(false), disableOptimizer(true), + optimizeSize(false), disassemble(false), validate(false) { } + bool generateDebugInfo; + bool disableOptimizer; + bool optimizeSize; + bool disassemble; + bool validate; +}; + +#ifdef ENABLE_OPT + +// Use the SPIRV-Tools disassembler to print SPIR-V. +void SpirvToolsDisassemble(std::ostream& out, const std::vector& spirv); + +// Apply the SPIRV-Tools validator to generated SPIR-V. +void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger*, bool prelegalization); + +// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of +// legalizing HLSL SPIR-V. +void SpirvToolsLegalize(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger*, const SpvOptions*); + +#endif + +} // end namespace glslang + +#endif // GLSLANG_SPV_TOOLS_H diff --git a/android/arm64-v8a/include/glslang/SPIRV/bitutils.h b/android/arm64-v8a/include/glslang/SPIRV/bitutils.h new file mode 100644 index 00000000..22e44cec --- /dev/null +++ b/android/arm64-v8a/include/glslang/SPIRV/bitutils.h @@ -0,0 +1,81 @@ +// Copyright (c) 2015-2016 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef LIBSPIRV_UTIL_BITUTILS_H_ +#define LIBSPIRV_UTIL_BITUTILS_H_ + +#include +#include + +namespace spvutils { + +// Performs a bitwise copy of source to the destination type Dest. +template +Dest BitwiseCast(Src source) { + Dest dest; + static_assert(sizeof(source) == sizeof(dest), + "BitwiseCast: Source and destination must have the same size"); + std::memcpy(static_cast(&dest), &source, sizeof(dest)); + return dest; +} + +// SetBits returns an integer of type with bits set +// for position through , counting from the least +// significant bit. In particular when Num == 0, no positions are set to 1. +// A static assert will be triggered if First + Num > sizeof(T) * 8, that is, +// a bit that will not fit in the underlying type is set. +template +struct SetBits { + static_assert(First < sizeof(T) * 8, + "Tried to set a bit that is shifted too far."); + const static T get = (T(1) << First) | SetBits::get; +}; + +template +struct SetBits { + const static T get = T(0); +}; + +// This is all compile-time so we can put our tests right here. +static_assert(SetBits::get == uint32_t(0x00000000), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x00000001), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x80000000), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x00000006), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0xc0000000), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x7FFFFFFF), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0xFFFFFFFF), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0xFFFF0000), + "SetBits failed"); + +static_assert(SetBits::get == uint64_t(0x0000000000000001LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0x8000000000000000LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0xc000000000000000LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0x0000000080000000LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0x00000000FFFF0000LL), + "SetBits failed"); + +} // namespace spvutils + +#endif // LIBSPIRV_UTIL_BITUTILS_H_ diff --git a/android/arm64-v8a/include/glslang/SPIRV/disassemble.h b/android/arm64-v8a/include/glslang/SPIRV/disassemble.h new file mode 100644 index 00000000..b6a46357 --- /dev/null +++ b/android/arm64-v8a/include/glslang/SPIRV/disassemble.h @@ -0,0 +1,53 @@ +// +// Copyright (C) 2014-2015 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Disassembler for SPIR-V. +// + +#pragma once +#ifndef disassembler_H +#define disassembler_H + +#include +#include + +namespace spv { + + // disassemble with glslang custom disassembler + void Disassemble(std::ostream& out, const std::vector&); + +} // end namespace spv + +#endif // disassembler_H diff --git a/android/arm64-v8a/include/glslang/SPIRV/doc.h b/android/arm64-v8a/include/glslang/SPIRV/doc.h new file mode 100644 index 00000000..293256a2 --- /dev/null +++ b/android/arm64-v8a/include/glslang/SPIRV/doc.h @@ -0,0 +1,258 @@ +// +// Copyright (C) 2014-2015 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Parameterize the SPIR-V enumerants. +// + +#pragma once + +#include "spirv.hpp" + +#include + +namespace spv { + +// Fill in all the parameters +void Parameterize(); + +// Return the English names of all the enums. +const char* SourceString(int); +const char* AddressingString(int); +const char* MemoryString(int); +const char* ExecutionModelString(int); +const char* ExecutionModeString(int); +const char* StorageClassString(int); +const char* DecorationString(int); +const char* BuiltInString(int); +const char* DimensionString(int); +const char* SelectControlString(int); +const char* LoopControlString(int); +const char* FunctionControlString(int); +const char* SamplerAddressingModeString(int); +const char* SamplerFilterModeString(int); +const char* ImageFormatString(int); +const char* ImageChannelOrderString(int); +const char* ImageChannelTypeString(int); +const char* ImageChannelDataTypeString(int type); +const char* ImageOperandsString(int format); +const char* ImageOperands(int); +const char* FPFastMathString(int); +const char* FPRoundingModeString(int); +const char* LinkageTypeString(int); +const char* FuncParamAttrString(int); +const char* AccessQualifierString(int); +const char* MemorySemanticsString(int); +const char* MemoryAccessString(int); +const char* ExecutionScopeString(int); +const char* GroupOperationString(int); +const char* KernelEnqueueFlagsString(int); +const char* KernelProfilingInfoString(int); +const char* CapabilityString(int); +const char* OpcodeString(int); +const char* ScopeString(int mem); + +// For grouping opcodes into subsections +enum OpcodeClass { + OpClassMisc, + OpClassDebug, + OpClassAnnotate, + OpClassExtension, + OpClassMode, + OpClassType, + OpClassConstant, + OpClassMemory, + OpClassFunction, + OpClassImage, + OpClassConvert, + OpClassComposite, + OpClassArithmetic, + OpClassBit, + OpClassRelationalLogical, + OpClassDerivative, + OpClassFlowControl, + OpClassAtomic, + OpClassPrimitive, + OpClassBarrier, + OpClassGroup, + OpClassDeviceSideEnqueue, + OpClassPipe, + + OpClassCount, + OpClassMissing // all instructions start out as missing +}; + +// For parameterizing operands. +enum OperandClass { + OperandNone, + OperandId, + OperandVariableIds, + OperandOptionalLiteral, + OperandOptionalLiteralString, + OperandVariableLiterals, + OperandVariableIdLiteral, + OperandVariableLiteralId, + OperandLiteralNumber, + OperandLiteralString, + OperandSource, + OperandExecutionModel, + OperandAddressing, + OperandMemory, + OperandExecutionMode, + OperandStorage, + OperandDimensionality, + OperandSamplerAddressingMode, + OperandSamplerFilterMode, + OperandSamplerImageFormat, + OperandImageChannelOrder, + OperandImageChannelDataType, + OperandImageOperands, + OperandFPFastMath, + OperandFPRoundingMode, + OperandLinkageType, + OperandAccessQualifier, + OperandFuncParamAttr, + OperandDecoration, + OperandBuiltIn, + OperandSelect, + OperandLoop, + OperandFunction, + OperandMemorySemantics, + OperandMemoryAccess, + OperandScope, + OperandGroupOperation, + OperandKernelEnqueueFlags, + OperandKernelProfilingInfo, + OperandCapability, + + OperandOpcode, + + OperandCount +}; + +// Any specific enum can have a set of capabilities that allow it: +typedef std::vector EnumCaps; + +// Parameterize a set of operands with their OperandClass(es) and descriptions. +class OperandParameters { +public: + OperandParameters() { } + void push(OperandClass oc, const char* d, bool opt = false) + { + opClass.push_back(oc); + desc.push_back(d); + optional.push_back(opt); + } + void setOptional(); + OperandClass getClass(int op) const { return opClass[op]; } + const char* getDesc(int op) const { return desc[op]; } + bool isOptional(int op) const { return optional[op]; } + int getNum() const { return (int)opClass.size(); } + +protected: + std::vector opClass; + std::vector desc; + std::vector optional; +}; + +// Parameterize an enumerant +class EnumParameters { +public: + EnumParameters() : desc(0) { } + const char* desc; +}; + +// Parameterize a set of enumerants that form an enum +class EnumDefinition : public EnumParameters { +public: + EnumDefinition() : + ceiling(0), bitmask(false), getName(0), enumParams(0), operandParams(0) { } + void set(int ceil, const char* (*name)(int), EnumParameters* ep, bool mask = false) + { + ceiling = ceil; + getName = name; + bitmask = mask; + enumParams = ep; + } + void setOperands(OperandParameters* op) { operandParams = op; } + int ceiling; // ceiling of enumerants + bool bitmask; // true if these enumerants combine into a bitmask + const char* (*getName)(int); // a function that returns the name for each enumerant value (or shift) + EnumParameters* enumParams; // parameters for each individual enumerant + OperandParameters* operandParams; // sets of operands +}; + +// Parameterize an instruction's logical format, including its known set of operands, +// per OperandParameters above. +class InstructionParameters { +public: + InstructionParameters() : + opDesc("TBD"), + opClass(OpClassMissing), + typePresent(true), // most normal, only exceptions have to be spelled out + resultPresent(true) // most normal, only exceptions have to be spelled out + { } + + void setResultAndType(bool r, bool t) + { + resultPresent = r; + typePresent = t; + } + + bool hasResult() const { return resultPresent != 0; } + bool hasType() const { return typePresent != 0; } + + const char* opDesc; + OpcodeClass opClass; + OperandParameters operands; + +protected: + int typePresent : 1; + int resultPresent : 1; +}; + +// The set of objects that hold all the instruction/operand +// parameterization information. +extern InstructionParameters InstructionDesc[]; + +// These hold definitions of the enumerants used for operands +extern EnumDefinition OperandClassParams[]; + +const char* GetOperandDesc(OperandClass operand); +void PrintImmediateRow(int imm, const char* name, const EnumParameters* enumParams, bool caps, bool hex = false); +const char* AccessQualifierString(int attr); + +void PrintOperands(const OperandParameters& operands, int reservedOperands); + +} // end namespace spv diff --git a/android/arm64-v8a/include/glslang/SPIRV/hex_float.h b/android/arm64-v8a/include/glslang/SPIRV/hex_float.h new file mode 100644 index 00000000..8be8e9f7 --- /dev/null +++ b/android/arm64-v8a/include/glslang/SPIRV/hex_float.h @@ -0,0 +1,1078 @@ +// Copyright (c) 2015-2016 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef LIBSPIRV_UTIL_HEX_FLOAT_H_ +#define LIBSPIRV_UTIL_HEX_FLOAT_H_ + +#include +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) && _MSC_VER < 1800 +namespace std { +bool isnan(double f) +{ + return ::_isnan(f) != 0; +} +bool isinf(double f) +{ + return ::_finite(f) == 0; +} +} +#endif + +#include "bitutils.h" + +namespace spvutils { + +class Float16 { + public: + Float16(uint16_t v) : val(v) {} + Float16() {} + static bool isNan(const Float16& val) { + return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) != 0); + } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(const Float16& val) { + return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) == 0); + } + Float16(const Float16& other) { val = other.val; } + uint16_t get_value() const { return val; } + + // Returns the maximum normal value. + static Float16 max() { return Float16(0x7bff); } + // Returns the lowest normal value. + static Float16 lowest() { return Float16(0xfbff); } + + private: + uint16_t val; +}; + +// To specialize this type, you must override uint_type to define +// an unsigned integer that can fit your floating point type. +// You must also add a isNan function that returns true if +// a value is Nan. +template +struct FloatProxyTraits { + typedef void uint_type; +}; + +template <> +struct FloatProxyTraits { + typedef uint32_t uint_type; + static bool isNan(float f) { return std::isnan(f); } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(float f) { return std::isinf(f); } + // Returns the maximum normal value. + static float max() { return std::numeric_limits::max(); } + // Returns the lowest normal value. + static float lowest() { return std::numeric_limits::lowest(); } +}; + +template <> +struct FloatProxyTraits { + typedef uint64_t uint_type; + static bool isNan(double f) { return std::isnan(f); } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(double f) { return std::isinf(f); } + // Returns the maximum normal value. + static double max() { return std::numeric_limits::max(); } + // Returns the lowest normal value. + static double lowest() { return std::numeric_limits::lowest(); } +}; + +template <> +struct FloatProxyTraits { + typedef uint16_t uint_type; + static bool isNan(Float16 f) { return Float16::isNan(f); } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(Float16 f) { return Float16::isInfinity(f); } + // Returns the maximum normal value. + static Float16 max() { return Float16::max(); } + // Returns the lowest normal value. + static Float16 lowest() { return Float16::lowest(); } +}; + +// Since copying a floating point number (especially if it is NaN) +// does not guarantee that bits are preserved, this class lets us +// store the type and use it as a float when necessary. +template +class FloatProxy { + public: + typedef typename FloatProxyTraits::uint_type uint_type; + + // Since this is to act similar to the normal floats, + // do not initialize the data by default. + FloatProxy() {} + + // Intentionally non-explicit. This is a proxy type so + // implicit conversions allow us to use it more transparently. + FloatProxy(T val) { data_ = BitwiseCast(val); } + + // Intentionally non-explicit. This is a proxy type so + // implicit conversions allow us to use it more transparently. + FloatProxy(uint_type val) { data_ = val; } + + // This is helpful to have and is guaranteed not to stomp bits. + FloatProxy operator-() const { + return static_cast(data_ ^ + (uint_type(0x1) << (sizeof(T) * 8 - 1))); + } + + // Returns the data as a floating point value. + T getAsFloat() const { return BitwiseCast(data_); } + + // Returns the raw data. + uint_type data() const { return data_; } + + // Returns true if the value represents any type of NaN. + bool isNan() { return FloatProxyTraits::isNan(getAsFloat()); } + // Returns true if the value represents any type of infinity. + bool isInfinity() { return FloatProxyTraits::isInfinity(getAsFloat()); } + + // Returns the maximum normal value. + static FloatProxy max() { + return FloatProxy(FloatProxyTraits::max()); + } + // Returns the lowest normal value. + static FloatProxy lowest() { + return FloatProxy(FloatProxyTraits::lowest()); + } + + private: + uint_type data_; +}; + +template +bool operator==(const FloatProxy& first, const FloatProxy& second) { + return first.data() == second.data(); +} + +// Reads a FloatProxy value as a normal float from a stream. +template +std::istream& operator>>(std::istream& is, FloatProxy& value) { + T float_val; + is >> float_val; + value = FloatProxy(float_val); + return is; +} + +// This is an example traits. It is not meant to be used in practice, but will +// be the default for any non-specialized type. +template +struct HexFloatTraits { + // Integer type that can store this hex-float. + typedef void uint_type; + // Signed integer type that can store this hex-float. + typedef void int_type; + // The numerical type that this HexFloat represents. + typedef void underlying_type; + // The type needed to construct the underlying type. + typedef void native_type; + // The number of bits that are actually relevant in the uint_type. + // This allows us to deal with, for example, 24-bit values in a 32-bit + // integer. + static const uint32_t num_used_bits = 0; + // Number of bits that represent the exponent. + static const uint32_t num_exponent_bits = 0; + // Number of bits that represent the fractional part. + static const uint32_t num_fraction_bits = 0; + // The bias of the exponent. (How much we need to subtract from the stored + // value to get the correct value.) + static const uint32_t exponent_bias = 0; +}; + +// Traits for IEEE float. +// 1 sign bit, 8 exponent bits, 23 fractional bits. +template <> +struct HexFloatTraits> { + typedef uint32_t uint_type; + typedef int32_t int_type; + typedef FloatProxy underlying_type; + typedef float native_type; + static const uint_type num_used_bits = 32; + static const uint_type num_exponent_bits = 8; + static const uint_type num_fraction_bits = 23; + static const uint_type exponent_bias = 127; +}; + +// Traits for IEEE double. +// 1 sign bit, 11 exponent bits, 52 fractional bits. +template <> +struct HexFloatTraits> { + typedef uint64_t uint_type; + typedef int64_t int_type; + typedef FloatProxy underlying_type; + typedef double native_type; + static const uint_type num_used_bits = 64; + static const uint_type num_exponent_bits = 11; + static const uint_type num_fraction_bits = 52; + static const uint_type exponent_bias = 1023; +}; + +// Traits for IEEE half. +// 1 sign bit, 5 exponent bits, 10 fractional bits. +template <> +struct HexFloatTraits> { + typedef uint16_t uint_type; + typedef int16_t int_type; + typedef uint16_t underlying_type; + typedef uint16_t native_type; + static const uint_type num_used_bits = 16; + static const uint_type num_exponent_bits = 5; + static const uint_type num_fraction_bits = 10; + static const uint_type exponent_bias = 15; +}; + +enum round_direction { + kRoundToZero, + kRoundToNearestEven, + kRoundToPositiveInfinity, + kRoundToNegativeInfinity +}; + +// Template class that houses a floating pointer number. +// It exposes a number of constants based on the provided traits to +// assist in interpreting the bits of the value. +template > +class HexFloat { + public: + typedef typename Traits::uint_type uint_type; + typedef typename Traits::int_type int_type; + typedef typename Traits::underlying_type underlying_type; + typedef typename Traits::native_type native_type; + + explicit HexFloat(T f) : value_(f) {} + + T value() const { return value_; } + void set_value(T f) { value_ = f; } + + // These are all written like this because it is convenient to have + // compile-time constants for all of these values. + + // Pass-through values to save typing. + static const uint32_t num_used_bits = Traits::num_used_bits; + static const uint32_t exponent_bias = Traits::exponent_bias; + static const uint32_t num_exponent_bits = Traits::num_exponent_bits; + static const uint32_t num_fraction_bits = Traits::num_fraction_bits; + + // Number of bits to shift left to set the highest relevant bit. + static const uint32_t top_bit_left_shift = num_used_bits - 1; + // How many nibbles (hex characters) the fractional part takes up. + static const uint32_t fraction_nibbles = (num_fraction_bits + 3) / 4; + // If the fractional part does not fit evenly into a hex character (4-bits) + // then we have to left-shift to get rid of leading 0s. This is the amount + // we have to shift (might be 0). + static const uint32_t num_overflow_bits = + fraction_nibbles * 4 - num_fraction_bits; + + // The representation of the fraction, not the actual bits. This + // includes the leading bit that is usually implicit. + static const uint_type fraction_represent_mask = + spvutils::SetBits::get; + + // The topmost bit in the nibble-aligned fraction. + static const uint_type fraction_top_bit = + uint_type(1) << (num_fraction_bits + num_overflow_bits - 1); + + // The least significant bit in the exponent, which is also the bit + // immediately to the left of the significand. + static const uint_type first_exponent_bit = uint_type(1) + << (num_fraction_bits); + + // The mask for the encoded fraction. It does not include the + // implicit bit. + static const uint_type fraction_encode_mask = + spvutils::SetBits::get; + + // The bit that is used as a sign. + static const uint_type sign_mask = uint_type(1) << top_bit_left_shift; + + // The bits that represent the exponent. + static const uint_type exponent_mask = + spvutils::SetBits::get; + + // How far left the exponent is shifted. + static const uint32_t exponent_left_shift = num_fraction_bits; + + // How far from the right edge the fraction is shifted. + static const uint32_t fraction_right_shift = + static_cast(sizeof(uint_type) * 8) - num_fraction_bits; + + // The maximum representable unbiased exponent. + static const int_type max_exponent = + (exponent_mask >> num_fraction_bits) - exponent_bias; + // The minimum representable exponent for normalized numbers. + static const int_type min_exponent = -static_cast(exponent_bias); + + // Returns the bits associated with the value. + uint_type getBits() const { return spvutils::BitwiseCast(value_); } + + // Returns the bits associated with the value, without the leading sign bit. + uint_type getUnsignedBits() const { + return static_cast(spvutils::BitwiseCast(value_) & + ~sign_mask); + } + + // Returns the bits associated with the exponent, shifted to start at the + // lsb of the type. + const uint_type getExponentBits() const { + return static_cast((getBits() & exponent_mask) >> + num_fraction_bits); + } + + // Returns the exponent in unbiased form. This is the exponent in the + // human-friendly form. + const int_type getUnbiasedExponent() const { + return static_cast(getExponentBits() - exponent_bias); + } + + // Returns just the significand bits from the value. + const uint_type getSignificandBits() const { + return getBits() & fraction_encode_mask; + } + + // If the number was normalized, returns the unbiased exponent. + // If the number was denormal, normalize the exponent first. + const int_type getUnbiasedNormalizedExponent() const { + if ((getBits() & ~sign_mask) == 0) { // special case if everything is 0 + return 0; + } + int_type exp = getUnbiasedExponent(); + if (exp == min_exponent) { // We are in denorm land. + uint_type significand_bits = getSignificandBits(); + while ((significand_bits & (first_exponent_bit >> 1)) == 0) { + significand_bits = static_cast(significand_bits << 1); + exp = static_cast(exp - 1); + } + significand_bits &= fraction_encode_mask; + } + return exp; + } + + // Returns the signficand after it has been normalized. + const uint_type getNormalizedSignificand() const { + int_type unbiased_exponent = getUnbiasedNormalizedExponent(); + uint_type significand = getSignificandBits(); + for (int_type i = unbiased_exponent; i <= min_exponent; ++i) { + significand = static_cast(significand << 1); + } + significand &= fraction_encode_mask; + return significand; + } + + // Returns true if this number represents a negative value. + bool isNegative() const { return (getBits() & sign_mask) != 0; } + + // Sets this HexFloat from the individual components. + // Note this assumes EVERY significand is normalized, and has an implicit + // leading one. This means that the only way that this method will set 0, + // is if you set a number so denormalized that it underflows. + // Do not use this method with raw bits extracted from a subnormal number, + // since subnormals do not have an implicit leading 1 in the significand. + // The significand is also expected to be in the + // lowest-most num_fraction_bits of the uint_type. + // The exponent is expected to be unbiased, meaning an exponent of + // 0 actually means 0. + // If underflow_round_up is set, then on underflow, if a number is non-0 + // and would underflow, we round up to the smallest denorm. + void setFromSignUnbiasedExponentAndNormalizedSignificand( + bool negative, int_type exponent, uint_type significand, + bool round_denorm_up) { + bool significand_is_zero = significand == 0; + + if (exponent <= min_exponent) { + // If this was denormalized, then we have to shift the bit on, meaning + // the significand is not zero. + significand_is_zero = false; + significand |= first_exponent_bit; + significand = static_cast(significand >> 1); + } + + while (exponent < min_exponent) { + significand = static_cast(significand >> 1); + ++exponent; + } + + if (exponent == min_exponent) { + if (significand == 0 && !significand_is_zero && round_denorm_up) { + significand = static_cast(0x1); + } + } + + uint_type new_value = 0; + if (negative) { + new_value = static_cast(new_value | sign_mask); + } + exponent = static_cast(exponent + exponent_bias); + assert(exponent >= 0); + + // put it all together + exponent = static_cast((exponent << exponent_left_shift) & + exponent_mask); + significand = static_cast(significand & fraction_encode_mask); + new_value = static_cast(new_value | (exponent | significand)); + value_ = BitwiseCast(new_value); + } + + // Increments the significand of this number by the given amount. + // If this would spill the significand into the implicit bit, + // carry is set to true and the significand is shifted to fit into + // the correct location, otherwise carry is set to false. + // All significands and to_increment are assumed to be within the bounds + // for a valid significand. + static uint_type incrementSignificand(uint_type significand, + uint_type to_increment, bool* carry) { + significand = static_cast(significand + to_increment); + *carry = false; + if (significand & first_exponent_bit) { + *carry = true; + // The implicit 1-bit will have carried, so we should zero-out the + // top bit and shift back. + significand = static_cast(significand & ~first_exponent_bit); + significand = static_cast(significand >> 1); + } + return significand; + } + + // These exist because MSVC throws warnings on negative right-shifts + // even if they are not going to be executed. Eg: + // constant_number < 0? 0: constant_number + // These convert the negative left-shifts into right shifts. + + template + uint_type negatable_left_shift(int_type N, uint_type val) + { + if(N >= 0) + return val << N; + + return val >> -N; + } + + template + uint_type negatable_right_shift(int_type N, uint_type val) + { + if(N >= 0) + return val >> N; + + return val << -N; + } + + // Returns the significand, rounded to fit in a significand in + // other_T. This is shifted so that the most significant + // bit of the rounded number lines up with the most significant bit + // of the returned significand. + template + typename other_T::uint_type getRoundedNormalizedSignificand( + round_direction dir, bool* carry_bit) { + typedef typename other_T::uint_type other_uint_type; + static const int_type num_throwaway_bits = + static_cast(num_fraction_bits) - + static_cast(other_T::num_fraction_bits); + + static const uint_type last_significant_bit = + (num_throwaway_bits < 0) + ? 0 + : negatable_left_shift(num_throwaway_bits, 1u); + static const uint_type first_rounded_bit = + (num_throwaway_bits < 1) + ? 0 + : negatable_left_shift(num_throwaway_bits - 1, 1u); + + static const uint_type throwaway_mask_bits = + num_throwaway_bits > 0 ? num_throwaway_bits : 0; + static const uint_type throwaway_mask = + spvutils::SetBits::get; + + *carry_bit = false; + other_uint_type out_val = 0; + uint_type significand = getNormalizedSignificand(); + // If we are up-casting, then we just have to shift to the right location. + if (num_throwaway_bits <= 0) { + out_val = static_cast(significand); + uint_type shift_amount = static_cast(-num_throwaway_bits); + out_val = static_cast(out_val << shift_amount); + return out_val; + } + + // If every non-representable bit is 0, then we don't have any casting to + // do. + if ((significand & throwaway_mask) == 0) { + return static_cast( + negatable_right_shift(num_throwaway_bits, significand)); + } + + bool round_away_from_zero = false; + // We actually have to narrow the significand here, so we have to follow the + // rounding rules. + switch (dir) { + case kRoundToZero: + break; + case kRoundToPositiveInfinity: + round_away_from_zero = !isNegative(); + break; + case kRoundToNegativeInfinity: + round_away_from_zero = isNegative(); + break; + case kRoundToNearestEven: + // Have to round down, round bit is 0 + if ((first_rounded_bit & significand) == 0) { + break; + } + if (((significand & throwaway_mask) & ~first_rounded_bit) != 0) { + // If any subsequent bit of the rounded portion is non-0 then we round + // up. + round_away_from_zero = true; + break; + } + // We are exactly half-way between 2 numbers, pick even. + if ((significand & last_significant_bit) != 0) { + // 1 for our last bit, round up. + round_away_from_zero = true; + break; + } + break; + } + + if (round_away_from_zero) { + return static_cast( + negatable_right_shift(num_throwaway_bits, incrementSignificand( + significand, last_significant_bit, carry_bit))); + } else { + return static_cast( + negatable_right_shift(num_throwaway_bits, significand)); + } + } + + // Casts this value to another HexFloat. If the cast is widening, + // then round_dir is ignored. If the cast is narrowing, then + // the result is rounded in the direction specified. + // This number will retain Nan and Inf values. + // It will also saturate to Inf if the number overflows, and + // underflow to (0 or min depending on rounding) if the number underflows. + template + void castTo(other_T& other, round_direction round_dir) { + other = other_T(static_cast(0)); + bool negate = isNegative(); + if (getUnsignedBits() == 0) { + if (negate) { + other.set_value(-other.value()); + } + return; + } + uint_type significand = getSignificandBits(); + bool carried = false; + typename other_T::uint_type rounded_significand = + getRoundedNormalizedSignificand(round_dir, &carried); + + int_type exponent = getUnbiasedExponent(); + if (exponent == min_exponent) { + // If we are denormal, normalize the exponent, so that we can encode + // easily. + exponent = static_cast(exponent + 1); + for (uint_type check_bit = first_exponent_bit >> 1; check_bit != 0; + check_bit = static_cast(check_bit >> 1)) { + exponent = static_cast(exponent - 1); + if (check_bit & significand) break; + } + } + + bool is_nan = + (getBits() & exponent_mask) == exponent_mask && significand != 0; + bool is_inf = + !is_nan && + ((exponent + carried) > static_cast(other_T::exponent_bias) || + (significand == 0 && (getBits() & exponent_mask) == exponent_mask)); + + // If we are Nan or Inf we should pass that through. + if (is_inf) { + other.set_value(BitwiseCast( + static_cast( + (negate ? other_T::sign_mask : 0) | other_T::exponent_mask))); + return; + } + if (is_nan) { + typename other_T::uint_type shifted_significand; + shifted_significand = static_cast( + negatable_left_shift( + static_cast(other_T::num_fraction_bits) - + static_cast(num_fraction_bits), significand)); + + // We are some sort of Nan. We try to keep the bit-pattern of the Nan + // as close as possible. If we had to shift off bits so we are 0, then we + // just set the last bit. + other.set_value(BitwiseCast( + static_cast( + (negate ? other_T::sign_mask : 0) | other_T::exponent_mask | + (shifted_significand == 0 ? 0x1 : shifted_significand)))); + return; + } + + bool round_underflow_up = + isNegative() ? round_dir == kRoundToNegativeInfinity + : round_dir == kRoundToPositiveInfinity; + typedef typename other_T::int_type other_int_type; + // setFromSignUnbiasedExponentAndNormalizedSignificand will + // zero out any underflowing value (but retain the sign). + other.setFromSignUnbiasedExponentAndNormalizedSignificand( + negate, static_cast(exponent), rounded_significand, + round_underflow_up); + return; + } + + private: + T value_; + + static_assert(num_used_bits == + Traits::num_exponent_bits + Traits::num_fraction_bits + 1, + "The number of bits do not fit"); + static_assert(sizeof(T) == sizeof(uint_type), "The type sizes do not match"); +}; + +// Returns 4 bits represented by the hex character. +inline uint8_t get_nibble_from_character(int character) { + const char* dec = "0123456789"; + const char* lower = "abcdef"; + const char* upper = "ABCDEF"; + const char* p = nullptr; + if ((p = strchr(dec, character))) { + return static_cast(p - dec); + } else if ((p = strchr(lower, character))) { + return static_cast(p - lower + 0xa); + } else if ((p = strchr(upper, character))) { + return static_cast(p - upper + 0xa); + } + + assert(false && "This was called with a non-hex character"); + return 0; +} + +// Outputs the given HexFloat to the stream. +template +std::ostream& operator<<(std::ostream& os, const HexFloat& value) { + typedef HexFloat HF; + typedef typename HF::uint_type uint_type; + typedef typename HF::int_type int_type; + + static_assert(HF::num_used_bits != 0, + "num_used_bits must be non-zero for a valid float"); + static_assert(HF::num_exponent_bits != 0, + "num_exponent_bits must be non-zero for a valid float"); + static_assert(HF::num_fraction_bits != 0, + "num_fractin_bits must be non-zero for a valid float"); + + const uint_type bits = spvutils::BitwiseCast(value.value()); + const char* const sign = (bits & HF::sign_mask) ? "-" : ""; + const uint_type exponent = static_cast( + (bits & HF::exponent_mask) >> HF::num_fraction_bits); + + uint_type fraction = static_cast((bits & HF::fraction_encode_mask) + << HF::num_overflow_bits); + + const bool is_zero = exponent == 0 && fraction == 0; + const bool is_denorm = exponent == 0 && !is_zero; + + // exponent contains the biased exponent we have to convert it back into + // the normal range. + int_type int_exponent = static_cast(exponent - HF::exponent_bias); + // If the number is all zeros, then we actually have to NOT shift the + // exponent. + int_exponent = is_zero ? 0 : int_exponent; + + // If we are denorm, then start shifting, and decreasing the exponent until + // our leading bit is 1. + + if (is_denorm) { + while ((fraction & HF::fraction_top_bit) == 0) { + fraction = static_cast(fraction << 1); + int_exponent = static_cast(int_exponent - 1); + } + // Since this is denormalized, we have to consume the leading 1 since it + // will end up being implicit. + fraction = static_cast(fraction << 1); // eat the leading 1 + fraction &= HF::fraction_represent_mask; + } + + uint_type fraction_nibbles = HF::fraction_nibbles; + // We do not have to display any trailing 0s, since this represents the + // fractional part. + while (fraction_nibbles > 0 && (fraction & 0xF) == 0) { + // Shift off any trailing values; + fraction = static_cast(fraction >> 4); + --fraction_nibbles; + } + + const auto saved_flags = os.flags(); + const auto saved_fill = os.fill(); + + os << sign << "0x" << (is_zero ? '0' : '1'); + if (fraction_nibbles) { + // Make sure to keep the leading 0s in place, since this is the fractional + // part. + os << "." << std::setw(static_cast(fraction_nibbles)) + << std::setfill('0') << std::hex << fraction; + } + os << "p" << std::dec << (int_exponent >= 0 ? "+" : "") << int_exponent; + + os.flags(saved_flags); + os.fill(saved_fill); + + return os; +} + +// Returns true if negate_value is true and the next character on the +// input stream is a plus or minus sign. In that case we also set the fail bit +// on the stream and set the value to the zero value for its type. +template +inline bool RejectParseDueToLeadingSign(std::istream& is, bool negate_value, + HexFloat& value) { + if (negate_value) { + auto next_char = is.peek(); + if (next_char == '-' || next_char == '+') { + // Fail the parse. Emulate standard behaviour by setting the value to + // the zero value, and set the fail bit on the stream. + value = HexFloat(typename HexFloat::uint_type(0)); + is.setstate(std::ios_base::failbit); + return true; + } + } + return false; +} + +// Parses a floating point number from the given stream and stores it into the +// value parameter. +// If negate_value is true then the number may not have a leading minus or +// plus, and if it successfully parses, then the number is negated before +// being stored into the value parameter. +// If the value cannot be correctly parsed or overflows the target floating +// point type, then set the fail bit on the stream. +// TODO(dneto): Promise C++11 standard behavior in how the value is set in +// the error case, but only after all target platforms implement it correctly. +// In particular, the Microsoft C++ runtime appears to be out of spec. +template +inline std::istream& ParseNormalFloat(std::istream& is, bool negate_value, + HexFloat& value) { + if (RejectParseDueToLeadingSign(is, negate_value, value)) { + return is; + } + T val; + is >> val; + if (negate_value) { + val = -val; + } + value.set_value(val); + // In the failure case, map -0.0 to 0.0. + if (is.fail() && value.getUnsignedBits() == 0u) { + value = HexFloat(typename HexFloat::uint_type(0)); + } + if (val.isInfinity()) { + // Fail the parse. Emulate standard behaviour by setting the value to + // the closest normal value, and set the fail bit on the stream. + value.set_value((value.isNegative() || negate_value) ? T::lowest() + : T::max()); + is.setstate(std::ios_base::failbit); + } + return is; +} + +// Specialization of ParseNormalFloat for FloatProxy values. +// This will parse the float as it were a 32-bit floating point number, +// and then round it down to fit into a Float16 value. +// The number is rounded towards zero. +// If negate_value is true then the number may not have a leading minus or +// plus, and if it successfully parses, then the number is negated before +// being stored into the value parameter. +// If the value cannot be correctly parsed or overflows the target floating +// point type, then set the fail bit on the stream. +// TODO(dneto): Promise C++11 standard behavior in how the value is set in +// the error case, but only after all target platforms implement it correctly. +// In particular, the Microsoft C++ runtime appears to be out of spec. +template <> +inline std::istream& +ParseNormalFloat, HexFloatTraits>>( + std::istream& is, bool negate_value, + HexFloat, HexFloatTraits>>& value) { + // First parse as a 32-bit float. + HexFloat> float_val(0.0f); + ParseNormalFloat(is, negate_value, float_val); + + // Then convert to 16-bit float, saturating at infinities, and + // rounding toward zero. + float_val.castTo(value, kRoundToZero); + + // Overflow on 16-bit behaves the same as for 32- and 64-bit: set the + // fail bit and set the lowest or highest value. + if (Float16::isInfinity(value.value().getAsFloat())) { + value.set_value(value.isNegative() ? Float16::lowest() : Float16::max()); + is.setstate(std::ios_base::failbit); + } + return is; +} + +// Reads a HexFloat from the given stream. +// If the float is not encoded as a hex-float then it will be parsed +// as a regular float. +// This may fail if your stream does not support at least one unget. +// Nan values can be encoded with "0x1.p+exponent_bias". +// This would normally overflow a float and round to +// infinity but this special pattern is the exact representation for a NaN, +// and therefore is actually encoded as the correct NaN. To encode inf, +// either 0x0p+exponent_bias can be specified or any exponent greater than +// exponent_bias. +// Examples using IEEE 32-bit float encoding. +// 0x1.0p+128 (+inf) +// -0x1.0p-128 (-inf) +// +// 0x1.1p+128 (+Nan) +// -0x1.1p+128 (-Nan) +// +// 0x1p+129 (+inf) +// -0x1p+129 (-inf) +template +std::istream& operator>>(std::istream& is, HexFloat& value) { + using HF = HexFloat; + using uint_type = typename HF::uint_type; + using int_type = typename HF::int_type; + + value.set_value(static_cast(0.f)); + + if (is.flags() & std::ios::skipws) { + // If the user wants to skip whitespace , then we should obey that. + while (std::isspace(is.peek())) { + is.get(); + } + } + + auto next_char = is.peek(); + bool negate_value = false; + + if (next_char != '-' && next_char != '0') { + return ParseNormalFloat(is, negate_value, value); + } + + if (next_char == '-') { + negate_value = true; + is.get(); + next_char = is.peek(); + } + + if (next_char == '0') { + is.get(); // We may have to unget this. + auto maybe_hex_start = is.peek(); + if (maybe_hex_start != 'x' && maybe_hex_start != 'X') { + is.unget(); + return ParseNormalFloat(is, negate_value, value); + } else { + is.get(); // Throw away the 'x'; + } + } else { + return ParseNormalFloat(is, negate_value, value); + } + + // This "looks" like a hex-float so treat it as one. + bool seen_p = false; + bool seen_dot = false; + uint_type fraction_index = 0; + + uint_type fraction = 0; + int_type exponent = HF::exponent_bias; + + // Strip off leading zeros so we don't have to special-case them later. + while ((next_char = is.peek()) == '0') { + is.get(); + } + + bool is_denorm = + true; // Assume denorm "representation" until we hear otherwise. + // NB: This does not mean the value is actually denorm, + // it just means that it was written 0. + bool bits_written = false; // Stays false until we write a bit. + while (!seen_p && !seen_dot) { + // Handle characters that are left of the fractional part. + if (next_char == '.') { + seen_dot = true; + } else if (next_char == 'p') { + seen_p = true; + } else if (::isxdigit(next_char)) { + // We know this is not denormalized since we have stripped all leading + // zeroes and we are not a ".". + is_denorm = false; + int number = get_nibble_from_character(next_char); + for (int i = 0; i < 4; ++i, number <<= 1) { + uint_type write_bit = (number & 0x8) ? 0x1 : 0x0; + if (bits_written) { + // If we are here the bits represented belong in the fractional + // part of the float, and we have to adjust the exponent accordingly. + fraction = static_cast( + fraction | + static_cast( + write_bit << (HF::top_bit_left_shift - fraction_index++))); + exponent = static_cast(exponent + 1); + } + bits_written |= write_bit != 0; + } + } else { + // We have not found our exponent yet, so we have to fail. + is.setstate(std::ios::failbit); + return is; + } + is.get(); + next_char = is.peek(); + } + bits_written = false; + while (seen_dot && !seen_p) { + // Handle only fractional parts now. + if (next_char == 'p') { + seen_p = true; + } else if (::isxdigit(next_char)) { + int number = get_nibble_from_character(next_char); + for (int i = 0; i < 4; ++i, number <<= 1) { + uint_type write_bit = (number & 0x8) ? 0x01 : 0x00; + bits_written |= write_bit != 0; + if (is_denorm && !bits_written) { + // Handle modifying the exponent here this way we can handle + // an arbitrary number of hex values without overflowing our + // integer. + exponent = static_cast(exponent - 1); + } else { + fraction = static_cast( + fraction | + static_cast( + write_bit << (HF::top_bit_left_shift - fraction_index++))); + } + } + } else { + // We still have not found our 'p' exponent yet, so this is not a valid + // hex-float. + is.setstate(std::ios::failbit); + return is; + } + is.get(); + next_char = is.peek(); + } + + bool seen_sign = false; + int8_t exponent_sign = 1; + int_type written_exponent = 0; + while (true) { + if ((next_char == '-' || next_char == '+')) { + if (seen_sign) { + is.setstate(std::ios::failbit); + return is; + } + seen_sign = true; + exponent_sign = (next_char == '-') ? -1 : 1; + } else if (::isdigit(next_char)) { + // Hex-floats express their exponent as decimal. + written_exponent = static_cast(written_exponent * 10); + written_exponent = + static_cast(written_exponent + (next_char - '0')); + } else { + break; + } + is.get(); + next_char = is.peek(); + } + + written_exponent = static_cast(written_exponent * exponent_sign); + exponent = static_cast(exponent + written_exponent); + + bool is_zero = is_denorm && (fraction == 0); + if (is_denorm && !is_zero) { + fraction = static_cast(fraction << 1); + exponent = static_cast(exponent - 1); + } else if (is_zero) { + exponent = 0; + } + + if (exponent <= 0 && !is_zero) { + fraction = static_cast(fraction >> 1); + fraction |= static_cast(1) << HF::top_bit_left_shift; + } + + fraction = (fraction >> HF::fraction_right_shift) & HF::fraction_encode_mask; + + const int_type max_exponent = + SetBits::get; + + // Handle actual denorm numbers + while (exponent < 0 && !is_zero) { + fraction = static_cast(fraction >> 1); + exponent = static_cast(exponent + 1); + + fraction &= HF::fraction_encode_mask; + if (fraction == 0) { + // We have underflowed our fraction. We should clamp to zero. + is_zero = true; + exponent = 0; + } + } + + // We have overflowed so we should be inf/-inf. + if (exponent > max_exponent) { + exponent = max_exponent; + fraction = 0; + } + + uint_type output_bits = static_cast( + static_cast(negate_value ? 1 : 0) << HF::top_bit_left_shift); + output_bits |= fraction; + + uint_type shifted_exponent = static_cast( + static_cast(exponent << HF::exponent_left_shift) & + HF::exponent_mask); + output_bits |= shifted_exponent; + + T output_float = spvutils::BitwiseCast(output_bits); + value.set_value(output_float); + + return is; +} + +// Writes a FloatProxy value to a stream. +// Zero and normal numbers are printed in the usual notation, but with +// enough digits to fully reproduce the value. Other values (subnormal, +// NaN, and infinity) are printed as a hex float. +template +std::ostream& operator<<(std::ostream& os, const FloatProxy& value) { + auto float_val = value.getAsFloat(); + switch (std::fpclassify(float_val)) { + case FP_ZERO: + case FP_NORMAL: { + auto saved_precision = os.precision(); + os.precision(std::numeric_limits::digits10); + os << float_val; + os.precision(saved_precision); + } break; + default: + os << HexFloat>(value); + break; + } + return os; +} + +template <> +inline std::ostream& operator<<(std::ostream& os, + const FloatProxy& value) { + os << HexFloat>(value); + return os; +} +} + +#endif // LIBSPIRV_UTIL_HEX_FLOAT_H_ diff --git a/android/arm64-v8a/include/glslang/SPIRV/spirv.hpp b/android/arm64-v8a/include/glslang/SPIRV/spirv.hpp new file mode 100644 index 00000000..dae36cf2 --- /dev/null +++ b/android/arm64-v8a/include/glslang/SPIRV/spirv.hpp @@ -0,0 +1,2114 @@ +// Copyright (c) 2014-2020 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and/or associated documentation files (the "Materials"), +// to deal in the Materials without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Materials, and to permit persons to whom the +// Materials are furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +// IN THE MATERIALS. + +// This header is automatically generated by the same tool that creates +// the Binary Section of the SPIR-V specification. + +// Enumeration tokens for SPIR-V, in various styles: +// C, C++, C++11, JSON, Lua, Python, C#, D +// +// - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL +// - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL +// - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL +// - Lua will use tables, e.g.: spv.SourceLanguage.GLSL +// - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] +// - C# will use enum classes in the Specification class located in the "Spv" namespace, +// e.g.: Spv.Specification.SourceLanguage.GLSL +// - D will have tokens under the "spv" module, e.g: spv.SourceLanguage.GLSL +// +// Some tokens act like mask values, which can be OR'd together, +// while others are mutually exclusive. The mask-like ones have +// "Mask" in their name, and a parallel enum that has the shift +// amount (1 << x) for each corresponding enumerant. + +#ifndef spirv_HPP +#define spirv_HPP + +namespace spv { + +typedef unsigned int Id; + +#define SPV_VERSION 0x10500 +#define SPV_REVISION 3 + +static const unsigned int MagicNumber = 0x07230203; +static const unsigned int Version = 0x00010500; +static const unsigned int Revision = 3; +static const unsigned int OpCodeMask = 0xffff; +static const unsigned int WordCountShift = 16; + +enum SourceLanguage { + SourceLanguageUnknown = 0, + SourceLanguageESSL = 1, + SourceLanguageGLSL = 2, + SourceLanguageOpenCL_C = 3, + SourceLanguageOpenCL_CPP = 4, + SourceLanguageHLSL = 5, + SourceLanguageMax = 0x7fffffff, +}; + +enum ExecutionModel { + ExecutionModelVertex = 0, + ExecutionModelTessellationControl = 1, + ExecutionModelTessellationEvaluation = 2, + ExecutionModelGeometry = 3, + ExecutionModelFragment = 4, + ExecutionModelGLCompute = 5, + ExecutionModelKernel = 6, + ExecutionModelTaskNV = 5267, + ExecutionModelMeshNV = 5268, + ExecutionModelRayGenerationKHR = 5313, + ExecutionModelRayGenerationNV = 5313, + ExecutionModelIntersectionKHR = 5314, + ExecutionModelIntersectionNV = 5314, + ExecutionModelAnyHitKHR = 5315, + ExecutionModelAnyHitNV = 5315, + ExecutionModelClosestHitKHR = 5316, + ExecutionModelClosestHitNV = 5316, + ExecutionModelMissKHR = 5317, + ExecutionModelMissNV = 5317, + ExecutionModelCallableKHR = 5318, + ExecutionModelCallableNV = 5318, + ExecutionModelMax = 0x7fffffff, +}; + +enum AddressingModel { + AddressingModelLogical = 0, + AddressingModelPhysical32 = 1, + AddressingModelPhysical64 = 2, + AddressingModelPhysicalStorageBuffer64 = 5348, + AddressingModelPhysicalStorageBuffer64EXT = 5348, + AddressingModelMax = 0x7fffffff, +}; + +enum MemoryModel { + MemoryModelSimple = 0, + MemoryModelGLSL450 = 1, + MemoryModelOpenCL = 2, + MemoryModelVulkan = 3, + MemoryModelVulkanKHR = 3, + MemoryModelMax = 0x7fffffff, +}; + +enum ExecutionMode { + ExecutionModeInvocations = 0, + ExecutionModeSpacingEqual = 1, + ExecutionModeSpacingFractionalEven = 2, + ExecutionModeSpacingFractionalOdd = 3, + ExecutionModeVertexOrderCw = 4, + ExecutionModeVertexOrderCcw = 5, + ExecutionModePixelCenterInteger = 6, + ExecutionModeOriginUpperLeft = 7, + ExecutionModeOriginLowerLeft = 8, + ExecutionModeEarlyFragmentTests = 9, + ExecutionModePointMode = 10, + ExecutionModeXfb = 11, + ExecutionModeDepthReplacing = 12, + ExecutionModeDepthGreater = 14, + ExecutionModeDepthLess = 15, + ExecutionModeDepthUnchanged = 16, + ExecutionModeLocalSize = 17, + ExecutionModeLocalSizeHint = 18, + ExecutionModeInputPoints = 19, + ExecutionModeInputLines = 20, + ExecutionModeInputLinesAdjacency = 21, + ExecutionModeTriangles = 22, + ExecutionModeInputTrianglesAdjacency = 23, + ExecutionModeQuads = 24, + ExecutionModeIsolines = 25, + ExecutionModeOutputVertices = 26, + ExecutionModeOutputPoints = 27, + ExecutionModeOutputLineStrip = 28, + ExecutionModeOutputTriangleStrip = 29, + ExecutionModeVecTypeHint = 30, + ExecutionModeContractionOff = 31, + ExecutionModeInitializer = 33, + ExecutionModeFinalizer = 34, + ExecutionModeSubgroupSize = 35, + ExecutionModeSubgroupsPerWorkgroup = 36, + ExecutionModeSubgroupsPerWorkgroupId = 37, + ExecutionModeLocalSizeId = 38, + ExecutionModeLocalSizeHintId = 39, + ExecutionModePostDepthCoverage = 4446, + ExecutionModeDenormPreserve = 4459, + ExecutionModeDenormFlushToZero = 4460, + ExecutionModeSignedZeroInfNanPreserve = 4461, + ExecutionModeRoundingModeRTE = 4462, + ExecutionModeRoundingModeRTZ = 4463, + ExecutionModeStencilRefReplacingEXT = 5027, + ExecutionModeOutputLinesNV = 5269, + ExecutionModeOutputPrimitivesNV = 5270, + ExecutionModeDerivativeGroupQuadsNV = 5289, + ExecutionModeDerivativeGroupLinearNV = 5290, + ExecutionModeOutputTrianglesNV = 5298, + ExecutionModePixelInterlockOrderedEXT = 5366, + ExecutionModePixelInterlockUnorderedEXT = 5367, + ExecutionModeSampleInterlockOrderedEXT = 5368, + ExecutionModeSampleInterlockUnorderedEXT = 5369, + ExecutionModeShadingRateInterlockOrderedEXT = 5370, + ExecutionModeShadingRateInterlockUnorderedEXT = 5371, + ExecutionModeMax = 0x7fffffff, +}; + +enum StorageClass { + StorageClassUniformConstant = 0, + StorageClassInput = 1, + StorageClassUniform = 2, + StorageClassOutput = 3, + StorageClassWorkgroup = 4, + StorageClassCrossWorkgroup = 5, + StorageClassPrivate = 6, + StorageClassFunction = 7, + StorageClassGeneric = 8, + StorageClassPushConstant = 9, + StorageClassAtomicCounter = 10, + StorageClassImage = 11, + StorageClassStorageBuffer = 12, + StorageClassCallableDataKHR = 5328, + StorageClassCallableDataNV = 5328, + StorageClassIncomingCallableDataKHR = 5329, + StorageClassIncomingCallableDataNV = 5329, + StorageClassRayPayloadKHR = 5338, + StorageClassRayPayloadNV = 5338, + StorageClassHitAttributeKHR = 5339, + StorageClassHitAttributeNV = 5339, + StorageClassIncomingRayPayloadKHR = 5342, + StorageClassIncomingRayPayloadNV = 5342, + StorageClassShaderRecordBufferKHR = 5343, + StorageClassShaderRecordBufferNV = 5343, + StorageClassPhysicalStorageBuffer = 5349, + StorageClassPhysicalStorageBufferEXT = 5349, + StorageClassMax = 0x7fffffff, +}; + +enum Dim { + Dim1D = 0, + Dim2D = 1, + Dim3D = 2, + DimCube = 3, + DimRect = 4, + DimBuffer = 5, + DimSubpassData = 6, + DimMax = 0x7fffffff, +}; + +enum SamplerAddressingMode { + SamplerAddressingModeNone = 0, + SamplerAddressingModeClampToEdge = 1, + SamplerAddressingModeClamp = 2, + SamplerAddressingModeRepeat = 3, + SamplerAddressingModeRepeatMirrored = 4, + SamplerAddressingModeMax = 0x7fffffff, +}; + +enum SamplerFilterMode { + SamplerFilterModeNearest = 0, + SamplerFilterModeLinear = 1, + SamplerFilterModeMax = 0x7fffffff, +}; + +enum ImageFormat { + ImageFormatUnknown = 0, + ImageFormatRgba32f = 1, + ImageFormatRgba16f = 2, + ImageFormatR32f = 3, + ImageFormatRgba8 = 4, + ImageFormatRgba8Snorm = 5, + ImageFormatRg32f = 6, + ImageFormatRg16f = 7, + ImageFormatR11fG11fB10f = 8, + ImageFormatR16f = 9, + ImageFormatRgba16 = 10, + ImageFormatRgb10A2 = 11, + ImageFormatRg16 = 12, + ImageFormatRg8 = 13, + ImageFormatR16 = 14, + ImageFormatR8 = 15, + ImageFormatRgba16Snorm = 16, + ImageFormatRg16Snorm = 17, + ImageFormatRg8Snorm = 18, + ImageFormatR16Snorm = 19, + ImageFormatR8Snorm = 20, + ImageFormatRgba32i = 21, + ImageFormatRgba16i = 22, + ImageFormatRgba8i = 23, + ImageFormatR32i = 24, + ImageFormatRg32i = 25, + ImageFormatRg16i = 26, + ImageFormatRg8i = 27, + ImageFormatR16i = 28, + ImageFormatR8i = 29, + ImageFormatRgba32ui = 30, + ImageFormatRgba16ui = 31, + ImageFormatRgba8ui = 32, + ImageFormatR32ui = 33, + ImageFormatRgb10a2ui = 34, + ImageFormatRg32ui = 35, + ImageFormatRg16ui = 36, + ImageFormatRg8ui = 37, + ImageFormatR16ui = 38, + ImageFormatR8ui = 39, + ImageFormatMax = 0x7fffffff, +}; + +enum ImageChannelOrder { + ImageChannelOrderR = 0, + ImageChannelOrderA = 1, + ImageChannelOrderRG = 2, + ImageChannelOrderRA = 3, + ImageChannelOrderRGB = 4, + ImageChannelOrderRGBA = 5, + ImageChannelOrderBGRA = 6, + ImageChannelOrderARGB = 7, + ImageChannelOrderIntensity = 8, + ImageChannelOrderLuminance = 9, + ImageChannelOrderRx = 10, + ImageChannelOrderRGx = 11, + ImageChannelOrderRGBx = 12, + ImageChannelOrderDepth = 13, + ImageChannelOrderDepthStencil = 14, + ImageChannelOrdersRGB = 15, + ImageChannelOrdersRGBx = 16, + ImageChannelOrdersRGBA = 17, + ImageChannelOrdersBGRA = 18, + ImageChannelOrderABGR = 19, + ImageChannelOrderMax = 0x7fffffff, +}; + +enum ImageChannelDataType { + ImageChannelDataTypeSnormInt8 = 0, + ImageChannelDataTypeSnormInt16 = 1, + ImageChannelDataTypeUnormInt8 = 2, + ImageChannelDataTypeUnormInt16 = 3, + ImageChannelDataTypeUnormShort565 = 4, + ImageChannelDataTypeUnormShort555 = 5, + ImageChannelDataTypeUnormInt101010 = 6, + ImageChannelDataTypeSignedInt8 = 7, + ImageChannelDataTypeSignedInt16 = 8, + ImageChannelDataTypeSignedInt32 = 9, + ImageChannelDataTypeUnsignedInt8 = 10, + ImageChannelDataTypeUnsignedInt16 = 11, + ImageChannelDataTypeUnsignedInt32 = 12, + ImageChannelDataTypeHalfFloat = 13, + ImageChannelDataTypeFloat = 14, + ImageChannelDataTypeUnormInt24 = 15, + ImageChannelDataTypeUnormInt101010_2 = 16, + ImageChannelDataTypeMax = 0x7fffffff, +}; + +enum ImageOperandsShift { + ImageOperandsBiasShift = 0, + ImageOperandsLodShift = 1, + ImageOperandsGradShift = 2, + ImageOperandsConstOffsetShift = 3, + ImageOperandsOffsetShift = 4, + ImageOperandsConstOffsetsShift = 5, + ImageOperandsSampleShift = 6, + ImageOperandsMinLodShift = 7, + ImageOperandsMakeTexelAvailableShift = 8, + ImageOperandsMakeTexelAvailableKHRShift = 8, + ImageOperandsMakeTexelVisibleShift = 9, + ImageOperandsMakeTexelVisibleKHRShift = 9, + ImageOperandsNonPrivateTexelShift = 10, + ImageOperandsNonPrivateTexelKHRShift = 10, + ImageOperandsVolatileTexelShift = 11, + ImageOperandsVolatileTexelKHRShift = 11, + ImageOperandsSignExtendShift = 12, + ImageOperandsZeroExtendShift = 13, + ImageOperandsMax = 0x7fffffff, +}; + +enum ImageOperandsMask { + ImageOperandsMaskNone = 0, + ImageOperandsBiasMask = 0x00000001, + ImageOperandsLodMask = 0x00000002, + ImageOperandsGradMask = 0x00000004, + ImageOperandsConstOffsetMask = 0x00000008, + ImageOperandsOffsetMask = 0x00000010, + ImageOperandsConstOffsetsMask = 0x00000020, + ImageOperandsSampleMask = 0x00000040, + ImageOperandsMinLodMask = 0x00000080, + ImageOperandsMakeTexelAvailableMask = 0x00000100, + ImageOperandsMakeTexelAvailableKHRMask = 0x00000100, + ImageOperandsMakeTexelVisibleMask = 0x00000200, + ImageOperandsMakeTexelVisibleKHRMask = 0x00000200, + ImageOperandsNonPrivateTexelMask = 0x00000400, + ImageOperandsNonPrivateTexelKHRMask = 0x00000400, + ImageOperandsVolatileTexelMask = 0x00000800, + ImageOperandsVolatileTexelKHRMask = 0x00000800, + ImageOperandsSignExtendMask = 0x00001000, + ImageOperandsZeroExtendMask = 0x00002000, +}; + +enum FPFastMathModeShift { + FPFastMathModeNotNaNShift = 0, + FPFastMathModeNotInfShift = 1, + FPFastMathModeNSZShift = 2, + FPFastMathModeAllowRecipShift = 3, + FPFastMathModeFastShift = 4, + FPFastMathModeMax = 0x7fffffff, +}; + +enum FPFastMathModeMask { + FPFastMathModeMaskNone = 0, + FPFastMathModeNotNaNMask = 0x00000001, + FPFastMathModeNotInfMask = 0x00000002, + FPFastMathModeNSZMask = 0x00000004, + FPFastMathModeAllowRecipMask = 0x00000008, + FPFastMathModeFastMask = 0x00000010, +}; + +enum FPRoundingMode { + FPRoundingModeRTE = 0, + FPRoundingModeRTZ = 1, + FPRoundingModeRTP = 2, + FPRoundingModeRTN = 3, + FPRoundingModeMax = 0x7fffffff, +}; + +enum LinkageType { + LinkageTypeExport = 0, + LinkageTypeImport = 1, + LinkageTypeMax = 0x7fffffff, +}; + +enum AccessQualifier { + AccessQualifierReadOnly = 0, + AccessQualifierWriteOnly = 1, + AccessQualifierReadWrite = 2, + AccessQualifierMax = 0x7fffffff, +}; + +enum FunctionParameterAttribute { + FunctionParameterAttributeZext = 0, + FunctionParameterAttributeSext = 1, + FunctionParameterAttributeByVal = 2, + FunctionParameterAttributeSret = 3, + FunctionParameterAttributeNoAlias = 4, + FunctionParameterAttributeNoCapture = 5, + FunctionParameterAttributeNoWrite = 6, + FunctionParameterAttributeNoReadWrite = 7, + FunctionParameterAttributeMax = 0x7fffffff, +}; + +enum Decoration { + DecorationRelaxedPrecision = 0, + DecorationSpecId = 1, + DecorationBlock = 2, + DecorationBufferBlock = 3, + DecorationRowMajor = 4, + DecorationColMajor = 5, + DecorationArrayStride = 6, + DecorationMatrixStride = 7, + DecorationGLSLShared = 8, + DecorationGLSLPacked = 9, + DecorationCPacked = 10, + DecorationBuiltIn = 11, + DecorationNoPerspective = 13, + DecorationFlat = 14, + DecorationPatch = 15, + DecorationCentroid = 16, + DecorationSample = 17, + DecorationInvariant = 18, + DecorationRestrict = 19, + DecorationAliased = 20, + DecorationVolatile = 21, + DecorationConstant = 22, + DecorationCoherent = 23, + DecorationNonWritable = 24, + DecorationNonReadable = 25, + DecorationUniform = 26, + DecorationUniformId = 27, + DecorationSaturatedConversion = 28, + DecorationStream = 29, + DecorationLocation = 30, + DecorationComponent = 31, + DecorationIndex = 32, + DecorationBinding = 33, + DecorationDescriptorSet = 34, + DecorationOffset = 35, + DecorationXfbBuffer = 36, + DecorationXfbStride = 37, + DecorationFuncParamAttr = 38, + DecorationFPRoundingMode = 39, + DecorationFPFastMathMode = 40, + DecorationLinkageAttributes = 41, + DecorationNoContraction = 42, + DecorationInputAttachmentIndex = 43, + DecorationAlignment = 44, + DecorationMaxByteOffset = 45, + DecorationAlignmentId = 46, + DecorationMaxByteOffsetId = 47, + DecorationNoSignedWrap = 4469, + DecorationNoUnsignedWrap = 4470, + DecorationExplicitInterpAMD = 4999, + DecorationOverrideCoverageNV = 5248, + DecorationPassthroughNV = 5250, + DecorationViewportRelativeNV = 5252, + DecorationSecondaryViewportRelativeNV = 5256, + DecorationPerPrimitiveNV = 5271, + DecorationPerViewNV = 5272, + DecorationPerTaskNV = 5273, + DecorationPerVertexNV = 5285, + DecorationNonUniform = 5300, + DecorationNonUniformEXT = 5300, + DecorationRestrictPointer = 5355, + DecorationRestrictPointerEXT = 5355, + DecorationAliasedPointer = 5356, + DecorationAliasedPointerEXT = 5356, + DecorationCounterBuffer = 5634, + DecorationHlslCounterBufferGOOGLE = 5634, + DecorationHlslSemanticGOOGLE = 5635, + DecorationUserSemantic = 5635, + DecorationUserTypeGOOGLE = 5636, + DecorationMax = 0x7fffffff, +}; + +enum BuiltIn { + BuiltInPosition = 0, + BuiltInPointSize = 1, + BuiltInClipDistance = 3, + BuiltInCullDistance = 4, + BuiltInVertexId = 5, + BuiltInInstanceId = 6, + BuiltInPrimitiveId = 7, + BuiltInInvocationId = 8, + BuiltInLayer = 9, + BuiltInViewportIndex = 10, + BuiltInTessLevelOuter = 11, + BuiltInTessLevelInner = 12, + BuiltInTessCoord = 13, + BuiltInPatchVertices = 14, + BuiltInFragCoord = 15, + BuiltInPointCoord = 16, + BuiltInFrontFacing = 17, + BuiltInSampleId = 18, + BuiltInSamplePosition = 19, + BuiltInSampleMask = 20, + BuiltInFragDepth = 22, + BuiltInHelperInvocation = 23, + BuiltInNumWorkgroups = 24, + BuiltInWorkgroupSize = 25, + BuiltInWorkgroupId = 26, + BuiltInLocalInvocationId = 27, + BuiltInGlobalInvocationId = 28, + BuiltInLocalInvocationIndex = 29, + BuiltInWorkDim = 30, + BuiltInGlobalSize = 31, + BuiltInEnqueuedWorkgroupSize = 32, + BuiltInGlobalOffset = 33, + BuiltInGlobalLinearId = 34, + BuiltInSubgroupSize = 36, + BuiltInSubgroupMaxSize = 37, + BuiltInNumSubgroups = 38, + BuiltInNumEnqueuedSubgroups = 39, + BuiltInSubgroupId = 40, + BuiltInSubgroupLocalInvocationId = 41, + BuiltInVertexIndex = 42, + BuiltInInstanceIndex = 43, + BuiltInSubgroupEqMask = 4416, + BuiltInSubgroupEqMaskKHR = 4416, + BuiltInSubgroupGeMask = 4417, + BuiltInSubgroupGeMaskKHR = 4417, + BuiltInSubgroupGtMask = 4418, + BuiltInSubgroupGtMaskKHR = 4418, + BuiltInSubgroupLeMask = 4419, + BuiltInSubgroupLeMaskKHR = 4419, + BuiltInSubgroupLtMask = 4420, + BuiltInSubgroupLtMaskKHR = 4420, + BuiltInBaseVertex = 4424, + BuiltInBaseInstance = 4425, + BuiltInDrawIndex = 4426, + BuiltInDeviceIndex = 4438, + BuiltInViewIndex = 4440, + BuiltInBaryCoordNoPerspAMD = 4992, + BuiltInBaryCoordNoPerspCentroidAMD = 4993, + BuiltInBaryCoordNoPerspSampleAMD = 4994, + BuiltInBaryCoordSmoothAMD = 4995, + BuiltInBaryCoordSmoothCentroidAMD = 4996, + BuiltInBaryCoordSmoothSampleAMD = 4997, + BuiltInBaryCoordPullModelAMD = 4998, + BuiltInFragStencilRefEXT = 5014, + BuiltInViewportMaskNV = 5253, + BuiltInSecondaryPositionNV = 5257, + BuiltInSecondaryViewportMaskNV = 5258, + BuiltInPositionPerViewNV = 5261, + BuiltInViewportMaskPerViewNV = 5262, + BuiltInFullyCoveredEXT = 5264, + BuiltInTaskCountNV = 5274, + BuiltInPrimitiveCountNV = 5275, + BuiltInPrimitiveIndicesNV = 5276, + BuiltInClipDistancePerViewNV = 5277, + BuiltInCullDistancePerViewNV = 5278, + BuiltInLayerPerViewNV = 5279, + BuiltInMeshViewCountNV = 5280, + BuiltInMeshViewIndicesNV = 5281, + BuiltInBaryCoordNV = 5286, + BuiltInBaryCoordNoPerspNV = 5287, + BuiltInFragSizeEXT = 5292, + BuiltInFragmentSizeNV = 5292, + BuiltInFragInvocationCountEXT = 5293, + BuiltInInvocationsPerPixelNV = 5293, + BuiltInLaunchIdKHR = 5319, + BuiltInLaunchIdNV = 5319, + BuiltInLaunchSizeKHR = 5320, + BuiltInLaunchSizeNV = 5320, + BuiltInWorldRayOriginKHR = 5321, + BuiltInWorldRayOriginNV = 5321, + BuiltInWorldRayDirectionKHR = 5322, + BuiltInWorldRayDirectionNV = 5322, + BuiltInObjectRayOriginKHR = 5323, + BuiltInObjectRayOriginNV = 5323, + BuiltInObjectRayDirectionKHR = 5324, + BuiltInObjectRayDirectionNV = 5324, + BuiltInRayTminKHR = 5325, + BuiltInRayTminNV = 5325, + BuiltInRayTmaxKHR = 5326, + BuiltInRayTmaxNV = 5326, + BuiltInInstanceCustomIndexKHR = 5327, + BuiltInInstanceCustomIndexNV = 5327, + BuiltInObjectToWorldKHR = 5330, + BuiltInObjectToWorldNV = 5330, + BuiltInWorldToObjectKHR = 5331, + BuiltInWorldToObjectNV = 5331, + BuiltInHitTKHR = 5332, + BuiltInHitTNV = 5332, + BuiltInHitKindKHR = 5333, + BuiltInHitKindNV = 5333, + BuiltInIncomingRayFlagsKHR = 5351, + BuiltInIncomingRayFlagsNV = 5351, + BuiltInRayGeometryIndexKHR = 5352, + BuiltInWarpsPerSMNV = 5374, + BuiltInSMCountNV = 5375, + BuiltInWarpIDNV = 5376, + BuiltInSMIDNV = 5377, + BuiltInMax = 0x7fffffff, +}; + +enum SelectionControlShift { + SelectionControlFlattenShift = 0, + SelectionControlDontFlattenShift = 1, + SelectionControlMax = 0x7fffffff, +}; + +enum SelectionControlMask { + SelectionControlMaskNone = 0, + SelectionControlFlattenMask = 0x00000001, + SelectionControlDontFlattenMask = 0x00000002, +}; + +enum LoopControlShift { + LoopControlUnrollShift = 0, + LoopControlDontUnrollShift = 1, + LoopControlDependencyInfiniteShift = 2, + LoopControlDependencyLengthShift = 3, + LoopControlMinIterationsShift = 4, + LoopControlMaxIterationsShift = 5, + LoopControlIterationMultipleShift = 6, + LoopControlPeelCountShift = 7, + LoopControlPartialCountShift = 8, + LoopControlMax = 0x7fffffff, +}; + +enum LoopControlMask { + LoopControlMaskNone = 0, + LoopControlUnrollMask = 0x00000001, + LoopControlDontUnrollMask = 0x00000002, + LoopControlDependencyInfiniteMask = 0x00000004, + LoopControlDependencyLengthMask = 0x00000008, + LoopControlMinIterationsMask = 0x00000010, + LoopControlMaxIterationsMask = 0x00000020, + LoopControlIterationMultipleMask = 0x00000040, + LoopControlPeelCountMask = 0x00000080, + LoopControlPartialCountMask = 0x00000100, +}; + +enum FunctionControlShift { + FunctionControlInlineShift = 0, + FunctionControlDontInlineShift = 1, + FunctionControlPureShift = 2, + FunctionControlConstShift = 3, + FunctionControlMax = 0x7fffffff, +}; + +enum FunctionControlMask { + FunctionControlMaskNone = 0, + FunctionControlInlineMask = 0x00000001, + FunctionControlDontInlineMask = 0x00000002, + FunctionControlPureMask = 0x00000004, + FunctionControlConstMask = 0x00000008, +}; + +enum MemorySemanticsShift { + MemorySemanticsAcquireShift = 1, + MemorySemanticsReleaseShift = 2, + MemorySemanticsAcquireReleaseShift = 3, + MemorySemanticsSequentiallyConsistentShift = 4, + MemorySemanticsUniformMemoryShift = 6, + MemorySemanticsSubgroupMemoryShift = 7, + MemorySemanticsWorkgroupMemoryShift = 8, + MemorySemanticsCrossWorkgroupMemoryShift = 9, + MemorySemanticsAtomicCounterMemoryShift = 10, + MemorySemanticsImageMemoryShift = 11, + MemorySemanticsOutputMemoryShift = 12, + MemorySemanticsOutputMemoryKHRShift = 12, + MemorySemanticsMakeAvailableShift = 13, + MemorySemanticsMakeAvailableKHRShift = 13, + MemorySemanticsMakeVisibleShift = 14, + MemorySemanticsMakeVisibleKHRShift = 14, + MemorySemanticsVolatileShift = 15, + MemorySemanticsMax = 0x7fffffff, +}; + +enum MemorySemanticsMask { + MemorySemanticsMaskNone = 0, + MemorySemanticsAcquireMask = 0x00000002, + MemorySemanticsReleaseMask = 0x00000004, + MemorySemanticsAcquireReleaseMask = 0x00000008, + MemorySemanticsSequentiallyConsistentMask = 0x00000010, + MemorySemanticsUniformMemoryMask = 0x00000040, + MemorySemanticsSubgroupMemoryMask = 0x00000080, + MemorySemanticsWorkgroupMemoryMask = 0x00000100, + MemorySemanticsCrossWorkgroupMemoryMask = 0x00000200, + MemorySemanticsAtomicCounterMemoryMask = 0x00000400, + MemorySemanticsImageMemoryMask = 0x00000800, + MemorySemanticsOutputMemoryMask = 0x00001000, + MemorySemanticsOutputMemoryKHRMask = 0x00001000, + MemorySemanticsMakeAvailableMask = 0x00002000, + MemorySemanticsMakeAvailableKHRMask = 0x00002000, + MemorySemanticsMakeVisibleMask = 0x00004000, + MemorySemanticsMakeVisibleKHRMask = 0x00004000, + MemorySemanticsVolatileMask = 0x00008000, +}; + +enum MemoryAccessShift { + MemoryAccessVolatileShift = 0, + MemoryAccessAlignedShift = 1, + MemoryAccessNontemporalShift = 2, + MemoryAccessMakePointerAvailableShift = 3, + MemoryAccessMakePointerAvailableKHRShift = 3, + MemoryAccessMakePointerVisibleShift = 4, + MemoryAccessMakePointerVisibleKHRShift = 4, + MemoryAccessNonPrivatePointerShift = 5, + MemoryAccessNonPrivatePointerKHRShift = 5, + MemoryAccessMax = 0x7fffffff, +}; + +enum MemoryAccessMask { + MemoryAccessMaskNone = 0, + MemoryAccessVolatileMask = 0x00000001, + MemoryAccessAlignedMask = 0x00000002, + MemoryAccessNontemporalMask = 0x00000004, + MemoryAccessMakePointerAvailableMask = 0x00000008, + MemoryAccessMakePointerAvailableKHRMask = 0x00000008, + MemoryAccessMakePointerVisibleMask = 0x00000010, + MemoryAccessMakePointerVisibleKHRMask = 0x00000010, + MemoryAccessNonPrivatePointerMask = 0x00000020, + MemoryAccessNonPrivatePointerKHRMask = 0x00000020, +}; + +enum Scope { + ScopeCrossDevice = 0, + ScopeDevice = 1, + ScopeWorkgroup = 2, + ScopeSubgroup = 3, + ScopeInvocation = 4, + ScopeQueueFamily = 5, + ScopeQueueFamilyKHR = 5, + ScopeShaderCallKHR = 6, + ScopeMax = 0x7fffffff, +}; + +enum GroupOperation { + GroupOperationReduce = 0, + GroupOperationInclusiveScan = 1, + GroupOperationExclusiveScan = 2, + GroupOperationClusteredReduce = 3, + GroupOperationPartitionedReduceNV = 6, + GroupOperationPartitionedInclusiveScanNV = 7, + GroupOperationPartitionedExclusiveScanNV = 8, + GroupOperationMax = 0x7fffffff, +}; + +enum KernelEnqueueFlags { + KernelEnqueueFlagsNoWait = 0, + KernelEnqueueFlagsWaitKernel = 1, + KernelEnqueueFlagsWaitWorkGroup = 2, + KernelEnqueueFlagsMax = 0x7fffffff, +}; + +enum KernelProfilingInfoShift { + KernelProfilingInfoCmdExecTimeShift = 0, + KernelProfilingInfoMax = 0x7fffffff, +}; + +enum KernelProfilingInfoMask { + KernelProfilingInfoMaskNone = 0, + KernelProfilingInfoCmdExecTimeMask = 0x00000001, +}; + +enum Capability { + CapabilityMatrix = 0, + CapabilityShader = 1, + CapabilityGeometry = 2, + CapabilityTessellation = 3, + CapabilityAddresses = 4, + CapabilityLinkage = 5, + CapabilityKernel = 6, + CapabilityVector16 = 7, + CapabilityFloat16Buffer = 8, + CapabilityFloat16 = 9, + CapabilityFloat64 = 10, + CapabilityInt64 = 11, + CapabilityInt64Atomics = 12, + CapabilityImageBasic = 13, + CapabilityImageReadWrite = 14, + CapabilityImageMipmap = 15, + CapabilityPipes = 17, + CapabilityGroups = 18, + CapabilityDeviceEnqueue = 19, + CapabilityLiteralSampler = 20, + CapabilityAtomicStorage = 21, + CapabilityInt16 = 22, + CapabilityTessellationPointSize = 23, + CapabilityGeometryPointSize = 24, + CapabilityImageGatherExtended = 25, + CapabilityStorageImageMultisample = 27, + CapabilityUniformBufferArrayDynamicIndexing = 28, + CapabilitySampledImageArrayDynamicIndexing = 29, + CapabilityStorageBufferArrayDynamicIndexing = 30, + CapabilityStorageImageArrayDynamicIndexing = 31, + CapabilityClipDistance = 32, + CapabilityCullDistance = 33, + CapabilityImageCubeArray = 34, + CapabilitySampleRateShading = 35, + CapabilityImageRect = 36, + CapabilitySampledRect = 37, + CapabilityGenericPointer = 38, + CapabilityInt8 = 39, + CapabilityInputAttachment = 40, + CapabilitySparseResidency = 41, + CapabilityMinLod = 42, + CapabilitySampled1D = 43, + CapabilityImage1D = 44, + CapabilitySampledCubeArray = 45, + CapabilitySampledBuffer = 46, + CapabilityImageBuffer = 47, + CapabilityImageMSArray = 48, + CapabilityStorageImageExtendedFormats = 49, + CapabilityImageQuery = 50, + CapabilityDerivativeControl = 51, + CapabilityInterpolationFunction = 52, + CapabilityTransformFeedback = 53, + CapabilityGeometryStreams = 54, + CapabilityStorageImageReadWithoutFormat = 55, + CapabilityStorageImageWriteWithoutFormat = 56, + CapabilityMultiViewport = 57, + CapabilitySubgroupDispatch = 58, + CapabilityNamedBarrier = 59, + CapabilityPipeStorage = 60, + CapabilityGroupNonUniform = 61, + CapabilityGroupNonUniformVote = 62, + CapabilityGroupNonUniformArithmetic = 63, + CapabilityGroupNonUniformBallot = 64, + CapabilityGroupNonUniformShuffle = 65, + CapabilityGroupNonUniformShuffleRelative = 66, + CapabilityGroupNonUniformClustered = 67, + CapabilityGroupNonUniformQuad = 68, + CapabilityShaderLayer = 69, + CapabilityShaderViewportIndex = 70, + CapabilitySubgroupBallotKHR = 4423, + CapabilityDrawParameters = 4427, + CapabilitySubgroupVoteKHR = 4431, + CapabilityStorageBuffer16BitAccess = 4433, + CapabilityStorageUniformBufferBlock16 = 4433, + CapabilityStorageUniform16 = 4434, + CapabilityUniformAndStorageBuffer16BitAccess = 4434, + CapabilityStoragePushConstant16 = 4435, + CapabilityStorageInputOutput16 = 4436, + CapabilityDeviceGroup = 4437, + CapabilityMultiView = 4439, + CapabilityVariablePointersStorageBuffer = 4441, + CapabilityVariablePointers = 4442, + CapabilityAtomicStorageOps = 4445, + CapabilitySampleMaskPostDepthCoverage = 4447, + CapabilityStorageBuffer8BitAccess = 4448, + CapabilityUniformAndStorageBuffer8BitAccess = 4449, + CapabilityStoragePushConstant8 = 4450, + CapabilityDenormPreserve = 4464, + CapabilityDenormFlushToZero = 4465, + CapabilitySignedZeroInfNanPreserve = 4466, + CapabilityRoundingModeRTE = 4467, + CapabilityRoundingModeRTZ = 4468, + CapabilityRayQueryProvisionalKHR = 4471, + CapabilityRayTraversalPrimitiveCullingProvisionalKHR = 4478, + CapabilityFloat16ImageAMD = 5008, + CapabilityImageGatherBiasLodAMD = 5009, + CapabilityFragmentMaskAMD = 5010, + CapabilityStencilExportEXT = 5013, + CapabilityImageReadWriteLodAMD = 5015, + CapabilityShaderClockKHR = 5055, + CapabilitySampleMaskOverrideCoverageNV = 5249, + CapabilityGeometryShaderPassthroughNV = 5251, + CapabilityShaderViewportIndexLayerEXT = 5254, + CapabilityShaderViewportIndexLayerNV = 5254, + CapabilityShaderViewportMaskNV = 5255, + CapabilityShaderStereoViewNV = 5259, + CapabilityPerViewAttributesNV = 5260, + CapabilityFragmentFullyCoveredEXT = 5265, + CapabilityMeshShadingNV = 5266, + CapabilityImageFootprintNV = 5282, + CapabilityFragmentBarycentricNV = 5284, + CapabilityComputeDerivativeGroupQuadsNV = 5288, + CapabilityFragmentDensityEXT = 5291, + CapabilityShadingRateNV = 5291, + CapabilityGroupNonUniformPartitionedNV = 5297, + CapabilityShaderNonUniform = 5301, + CapabilityShaderNonUniformEXT = 5301, + CapabilityRuntimeDescriptorArray = 5302, + CapabilityRuntimeDescriptorArrayEXT = 5302, + CapabilityInputAttachmentArrayDynamicIndexing = 5303, + CapabilityInputAttachmentArrayDynamicIndexingEXT = 5303, + CapabilityUniformTexelBufferArrayDynamicIndexing = 5304, + CapabilityUniformTexelBufferArrayDynamicIndexingEXT = 5304, + CapabilityStorageTexelBufferArrayDynamicIndexing = 5305, + CapabilityStorageTexelBufferArrayDynamicIndexingEXT = 5305, + CapabilityUniformBufferArrayNonUniformIndexing = 5306, + CapabilityUniformBufferArrayNonUniformIndexingEXT = 5306, + CapabilitySampledImageArrayNonUniformIndexing = 5307, + CapabilitySampledImageArrayNonUniformIndexingEXT = 5307, + CapabilityStorageBufferArrayNonUniformIndexing = 5308, + CapabilityStorageBufferArrayNonUniformIndexingEXT = 5308, + CapabilityStorageImageArrayNonUniformIndexing = 5309, + CapabilityStorageImageArrayNonUniformIndexingEXT = 5309, + CapabilityInputAttachmentArrayNonUniformIndexing = 5310, + CapabilityInputAttachmentArrayNonUniformIndexingEXT = 5310, + CapabilityUniformTexelBufferArrayNonUniformIndexing = 5311, + CapabilityUniformTexelBufferArrayNonUniformIndexingEXT = 5311, + CapabilityStorageTexelBufferArrayNonUniformIndexing = 5312, + CapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312, + CapabilityRayTracingNV = 5340, + CapabilityVulkanMemoryModel = 5345, + CapabilityVulkanMemoryModelKHR = 5345, + CapabilityVulkanMemoryModelDeviceScope = 5346, + CapabilityVulkanMemoryModelDeviceScopeKHR = 5346, + CapabilityPhysicalStorageBufferAddresses = 5347, + CapabilityPhysicalStorageBufferAddressesEXT = 5347, + CapabilityComputeDerivativeGroupLinearNV = 5350, + CapabilityRayTracingProvisionalKHR = 5353, + CapabilityCooperativeMatrixNV = 5357, + CapabilityFragmentShaderSampleInterlockEXT = 5363, + CapabilityFragmentShaderShadingRateInterlockEXT = 5372, + CapabilityShaderSMBuiltinsNV = 5373, + CapabilityFragmentShaderPixelInterlockEXT = 5378, + CapabilityDemoteToHelperInvocationEXT = 5379, + CapabilitySubgroupShuffleINTEL = 5568, + CapabilitySubgroupBufferBlockIOINTEL = 5569, + CapabilitySubgroupImageBlockIOINTEL = 5570, + CapabilitySubgroupImageMediaBlockIOINTEL = 5579, + CapabilityIntegerFunctions2INTEL = 5584, + CapabilitySubgroupAvcMotionEstimationINTEL = 5696, + CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697, + CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698, + CapabilityMax = 0x7fffffff, +}; + +enum RayFlagsShift { + RayFlagsOpaqueKHRShift = 0, + RayFlagsNoOpaqueKHRShift = 1, + RayFlagsTerminateOnFirstHitKHRShift = 2, + RayFlagsSkipClosestHitShaderKHRShift = 3, + RayFlagsCullBackFacingTrianglesKHRShift = 4, + RayFlagsCullFrontFacingTrianglesKHRShift = 5, + RayFlagsCullOpaqueKHRShift = 6, + RayFlagsCullNoOpaqueKHRShift = 7, + RayFlagsSkipTrianglesKHRShift = 8, + RayFlagsSkipAABBsKHRShift = 9, + RayFlagsMax = 0x7fffffff, +}; + +enum RayFlagsMask { + RayFlagsMaskNone = 0, + RayFlagsOpaqueKHRMask = 0x00000001, + RayFlagsNoOpaqueKHRMask = 0x00000002, + RayFlagsTerminateOnFirstHitKHRMask = 0x00000004, + RayFlagsSkipClosestHitShaderKHRMask = 0x00000008, + RayFlagsCullBackFacingTrianglesKHRMask = 0x00000010, + RayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020, + RayFlagsCullOpaqueKHRMask = 0x00000040, + RayFlagsCullNoOpaqueKHRMask = 0x00000080, + RayFlagsSkipTrianglesKHRMask = 0x00000100, + RayFlagsSkipAABBsKHRMask = 0x00000200, +}; + +enum RayQueryIntersection { + RayQueryIntersectionRayQueryCandidateIntersectionKHR = 0, + RayQueryIntersectionRayQueryCommittedIntersectionKHR = 1, + RayQueryIntersectionMax = 0x7fffffff, +}; + +enum RayQueryCommittedIntersectionType { + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR = 0, + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR = 1, + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR = 2, + RayQueryCommittedIntersectionTypeMax = 0x7fffffff, +}; + +enum RayQueryCandidateIntersectionType { + RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR = 0, + RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR = 1, + RayQueryCandidateIntersectionTypeMax = 0x7fffffff, +}; + +enum Op { + OpNop = 0, + OpUndef = 1, + OpSourceContinued = 2, + OpSource = 3, + OpSourceExtension = 4, + OpName = 5, + OpMemberName = 6, + OpString = 7, + OpLine = 8, + OpExtension = 10, + OpExtInstImport = 11, + OpExtInst = 12, + OpMemoryModel = 14, + OpEntryPoint = 15, + OpExecutionMode = 16, + OpCapability = 17, + OpTypeVoid = 19, + OpTypeBool = 20, + OpTypeInt = 21, + OpTypeFloat = 22, + OpTypeVector = 23, + OpTypeMatrix = 24, + OpTypeImage = 25, + OpTypeSampler = 26, + OpTypeSampledImage = 27, + OpTypeArray = 28, + OpTypeRuntimeArray = 29, + OpTypeStruct = 30, + OpTypeOpaque = 31, + OpTypePointer = 32, + OpTypeFunction = 33, + OpTypeEvent = 34, + OpTypeDeviceEvent = 35, + OpTypeReserveId = 36, + OpTypeQueue = 37, + OpTypePipe = 38, + OpTypeForwardPointer = 39, + OpConstantTrue = 41, + OpConstantFalse = 42, + OpConstant = 43, + OpConstantComposite = 44, + OpConstantSampler = 45, + OpConstantNull = 46, + OpSpecConstantTrue = 48, + OpSpecConstantFalse = 49, + OpSpecConstant = 50, + OpSpecConstantComposite = 51, + OpSpecConstantOp = 52, + OpFunction = 54, + OpFunctionParameter = 55, + OpFunctionEnd = 56, + OpFunctionCall = 57, + OpVariable = 59, + OpImageTexelPointer = 60, + OpLoad = 61, + OpStore = 62, + OpCopyMemory = 63, + OpCopyMemorySized = 64, + OpAccessChain = 65, + OpInBoundsAccessChain = 66, + OpPtrAccessChain = 67, + OpArrayLength = 68, + OpGenericPtrMemSemantics = 69, + OpInBoundsPtrAccessChain = 70, + OpDecorate = 71, + OpMemberDecorate = 72, + OpDecorationGroup = 73, + OpGroupDecorate = 74, + OpGroupMemberDecorate = 75, + OpVectorExtractDynamic = 77, + OpVectorInsertDynamic = 78, + OpVectorShuffle = 79, + OpCompositeConstruct = 80, + OpCompositeExtract = 81, + OpCompositeInsert = 82, + OpCopyObject = 83, + OpTranspose = 84, + OpSampledImage = 86, + OpImageSampleImplicitLod = 87, + OpImageSampleExplicitLod = 88, + OpImageSampleDrefImplicitLod = 89, + OpImageSampleDrefExplicitLod = 90, + OpImageSampleProjImplicitLod = 91, + OpImageSampleProjExplicitLod = 92, + OpImageSampleProjDrefImplicitLod = 93, + OpImageSampleProjDrefExplicitLod = 94, + OpImageFetch = 95, + OpImageGather = 96, + OpImageDrefGather = 97, + OpImageRead = 98, + OpImageWrite = 99, + OpImage = 100, + OpImageQueryFormat = 101, + OpImageQueryOrder = 102, + OpImageQuerySizeLod = 103, + OpImageQuerySize = 104, + OpImageQueryLod = 105, + OpImageQueryLevels = 106, + OpImageQuerySamples = 107, + OpConvertFToU = 109, + OpConvertFToS = 110, + OpConvertSToF = 111, + OpConvertUToF = 112, + OpUConvert = 113, + OpSConvert = 114, + OpFConvert = 115, + OpQuantizeToF16 = 116, + OpConvertPtrToU = 117, + OpSatConvertSToU = 118, + OpSatConvertUToS = 119, + OpConvertUToPtr = 120, + OpPtrCastToGeneric = 121, + OpGenericCastToPtr = 122, + OpGenericCastToPtrExplicit = 123, + OpBitcast = 124, + OpSNegate = 126, + OpFNegate = 127, + OpIAdd = 128, + OpFAdd = 129, + OpISub = 130, + OpFSub = 131, + OpIMul = 132, + OpFMul = 133, + OpUDiv = 134, + OpSDiv = 135, + OpFDiv = 136, + OpUMod = 137, + OpSRem = 138, + OpSMod = 139, + OpFRem = 140, + OpFMod = 141, + OpVectorTimesScalar = 142, + OpMatrixTimesScalar = 143, + OpVectorTimesMatrix = 144, + OpMatrixTimesVector = 145, + OpMatrixTimesMatrix = 146, + OpOuterProduct = 147, + OpDot = 148, + OpIAddCarry = 149, + OpISubBorrow = 150, + OpUMulExtended = 151, + OpSMulExtended = 152, + OpAny = 154, + OpAll = 155, + OpIsNan = 156, + OpIsInf = 157, + OpIsFinite = 158, + OpIsNormal = 159, + OpSignBitSet = 160, + OpLessOrGreater = 161, + OpOrdered = 162, + OpUnordered = 163, + OpLogicalEqual = 164, + OpLogicalNotEqual = 165, + OpLogicalOr = 166, + OpLogicalAnd = 167, + OpLogicalNot = 168, + OpSelect = 169, + OpIEqual = 170, + OpINotEqual = 171, + OpUGreaterThan = 172, + OpSGreaterThan = 173, + OpUGreaterThanEqual = 174, + OpSGreaterThanEqual = 175, + OpULessThan = 176, + OpSLessThan = 177, + OpULessThanEqual = 178, + OpSLessThanEqual = 179, + OpFOrdEqual = 180, + OpFUnordEqual = 181, + OpFOrdNotEqual = 182, + OpFUnordNotEqual = 183, + OpFOrdLessThan = 184, + OpFUnordLessThan = 185, + OpFOrdGreaterThan = 186, + OpFUnordGreaterThan = 187, + OpFOrdLessThanEqual = 188, + OpFUnordLessThanEqual = 189, + OpFOrdGreaterThanEqual = 190, + OpFUnordGreaterThanEqual = 191, + OpShiftRightLogical = 194, + OpShiftRightArithmetic = 195, + OpShiftLeftLogical = 196, + OpBitwiseOr = 197, + OpBitwiseXor = 198, + OpBitwiseAnd = 199, + OpNot = 200, + OpBitFieldInsert = 201, + OpBitFieldSExtract = 202, + OpBitFieldUExtract = 203, + OpBitReverse = 204, + OpBitCount = 205, + OpDPdx = 207, + OpDPdy = 208, + OpFwidth = 209, + OpDPdxFine = 210, + OpDPdyFine = 211, + OpFwidthFine = 212, + OpDPdxCoarse = 213, + OpDPdyCoarse = 214, + OpFwidthCoarse = 215, + OpEmitVertex = 218, + OpEndPrimitive = 219, + OpEmitStreamVertex = 220, + OpEndStreamPrimitive = 221, + OpControlBarrier = 224, + OpMemoryBarrier = 225, + OpAtomicLoad = 227, + OpAtomicStore = 228, + OpAtomicExchange = 229, + OpAtomicCompareExchange = 230, + OpAtomicCompareExchangeWeak = 231, + OpAtomicIIncrement = 232, + OpAtomicIDecrement = 233, + OpAtomicIAdd = 234, + OpAtomicISub = 235, + OpAtomicSMin = 236, + OpAtomicUMin = 237, + OpAtomicSMax = 238, + OpAtomicUMax = 239, + OpAtomicAnd = 240, + OpAtomicOr = 241, + OpAtomicXor = 242, + OpPhi = 245, + OpLoopMerge = 246, + OpSelectionMerge = 247, + OpLabel = 248, + OpBranch = 249, + OpBranchConditional = 250, + OpSwitch = 251, + OpKill = 252, + OpReturn = 253, + OpReturnValue = 254, + OpUnreachable = 255, + OpLifetimeStart = 256, + OpLifetimeStop = 257, + OpGroupAsyncCopy = 259, + OpGroupWaitEvents = 260, + OpGroupAll = 261, + OpGroupAny = 262, + OpGroupBroadcast = 263, + OpGroupIAdd = 264, + OpGroupFAdd = 265, + OpGroupFMin = 266, + OpGroupUMin = 267, + OpGroupSMin = 268, + OpGroupFMax = 269, + OpGroupUMax = 270, + OpGroupSMax = 271, + OpReadPipe = 274, + OpWritePipe = 275, + OpReservedReadPipe = 276, + OpReservedWritePipe = 277, + OpReserveReadPipePackets = 278, + OpReserveWritePipePackets = 279, + OpCommitReadPipe = 280, + OpCommitWritePipe = 281, + OpIsValidReserveId = 282, + OpGetNumPipePackets = 283, + OpGetMaxPipePackets = 284, + OpGroupReserveReadPipePackets = 285, + OpGroupReserveWritePipePackets = 286, + OpGroupCommitReadPipe = 287, + OpGroupCommitWritePipe = 288, + OpEnqueueMarker = 291, + OpEnqueueKernel = 292, + OpGetKernelNDrangeSubGroupCount = 293, + OpGetKernelNDrangeMaxSubGroupSize = 294, + OpGetKernelWorkGroupSize = 295, + OpGetKernelPreferredWorkGroupSizeMultiple = 296, + OpRetainEvent = 297, + OpReleaseEvent = 298, + OpCreateUserEvent = 299, + OpIsValidEvent = 300, + OpSetUserEventStatus = 301, + OpCaptureEventProfilingInfo = 302, + OpGetDefaultQueue = 303, + OpBuildNDRange = 304, + OpImageSparseSampleImplicitLod = 305, + OpImageSparseSampleExplicitLod = 306, + OpImageSparseSampleDrefImplicitLod = 307, + OpImageSparseSampleDrefExplicitLod = 308, + OpImageSparseSampleProjImplicitLod = 309, + OpImageSparseSampleProjExplicitLod = 310, + OpImageSparseSampleProjDrefImplicitLod = 311, + OpImageSparseSampleProjDrefExplicitLod = 312, + OpImageSparseFetch = 313, + OpImageSparseGather = 314, + OpImageSparseDrefGather = 315, + OpImageSparseTexelsResident = 316, + OpNoLine = 317, + OpAtomicFlagTestAndSet = 318, + OpAtomicFlagClear = 319, + OpImageSparseRead = 320, + OpSizeOf = 321, + OpTypePipeStorage = 322, + OpConstantPipeStorage = 323, + OpCreatePipeFromPipeStorage = 324, + OpGetKernelLocalSizeForSubgroupCount = 325, + OpGetKernelMaxNumSubgroups = 326, + OpTypeNamedBarrier = 327, + OpNamedBarrierInitialize = 328, + OpMemoryNamedBarrier = 329, + OpModuleProcessed = 330, + OpExecutionModeId = 331, + OpDecorateId = 332, + OpGroupNonUniformElect = 333, + OpGroupNonUniformAll = 334, + OpGroupNonUniformAny = 335, + OpGroupNonUniformAllEqual = 336, + OpGroupNonUniformBroadcast = 337, + OpGroupNonUniformBroadcastFirst = 338, + OpGroupNonUniformBallot = 339, + OpGroupNonUniformInverseBallot = 340, + OpGroupNonUniformBallotBitExtract = 341, + OpGroupNonUniformBallotBitCount = 342, + OpGroupNonUniformBallotFindLSB = 343, + OpGroupNonUniformBallotFindMSB = 344, + OpGroupNonUniformShuffle = 345, + OpGroupNonUniformShuffleXor = 346, + OpGroupNonUniformShuffleUp = 347, + OpGroupNonUniformShuffleDown = 348, + OpGroupNonUniformIAdd = 349, + OpGroupNonUniformFAdd = 350, + OpGroupNonUniformIMul = 351, + OpGroupNonUniformFMul = 352, + OpGroupNonUniformSMin = 353, + OpGroupNonUniformUMin = 354, + OpGroupNonUniformFMin = 355, + OpGroupNonUniformSMax = 356, + OpGroupNonUniformUMax = 357, + OpGroupNonUniformFMax = 358, + OpGroupNonUniformBitwiseAnd = 359, + OpGroupNonUniformBitwiseOr = 360, + OpGroupNonUniformBitwiseXor = 361, + OpGroupNonUniformLogicalAnd = 362, + OpGroupNonUniformLogicalOr = 363, + OpGroupNonUniformLogicalXor = 364, + OpGroupNonUniformQuadBroadcast = 365, + OpGroupNonUniformQuadSwap = 366, + OpCopyLogical = 400, + OpPtrEqual = 401, + OpPtrNotEqual = 402, + OpPtrDiff = 403, + OpSubgroupBallotKHR = 4421, + OpSubgroupFirstInvocationKHR = 4422, + OpSubgroupAllKHR = 4428, + OpSubgroupAnyKHR = 4429, + OpSubgroupAllEqualKHR = 4430, + OpSubgroupReadInvocationKHR = 4432, + OpTypeRayQueryProvisionalKHR = 4472, + OpRayQueryInitializeKHR = 4473, + OpRayQueryTerminateKHR = 4474, + OpRayQueryGenerateIntersectionKHR = 4475, + OpRayQueryConfirmIntersectionKHR = 4476, + OpRayQueryProceedKHR = 4477, + OpRayQueryGetIntersectionTypeKHR = 4479, + OpGroupIAddNonUniformAMD = 5000, + OpGroupFAddNonUniformAMD = 5001, + OpGroupFMinNonUniformAMD = 5002, + OpGroupUMinNonUniformAMD = 5003, + OpGroupSMinNonUniformAMD = 5004, + OpGroupFMaxNonUniformAMD = 5005, + OpGroupUMaxNonUniformAMD = 5006, + OpGroupSMaxNonUniformAMD = 5007, + OpFragmentMaskFetchAMD = 5011, + OpFragmentFetchAMD = 5012, + OpReadClockKHR = 5056, + OpImageSampleFootprintNV = 5283, + OpGroupNonUniformPartitionNV = 5296, + OpWritePackedPrimitiveIndices4x8NV = 5299, + OpReportIntersectionKHR = 5334, + OpReportIntersectionNV = 5334, + OpIgnoreIntersectionKHR = 5335, + OpIgnoreIntersectionNV = 5335, + OpTerminateRayKHR = 5336, + OpTerminateRayNV = 5336, + OpTraceNV = 5337, + OpTraceRayKHR = 5337, + OpTypeAccelerationStructureKHR = 5341, + OpTypeAccelerationStructureNV = 5341, + OpExecuteCallableKHR = 5344, + OpExecuteCallableNV = 5344, + OpTypeCooperativeMatrixNV = 5358, + OpCooperativeMatrixLoadNV = 5359, + OpCooperativeMatrixStoreNV = 5360, + OpCooperativeMatrixMulAddNV = 5361, + OpCooperativeMatrixLengthNV = 5362, + OpBeginInvocationInterlockEXT = 5364, + OpEndInvocationInterlockEXT = 5365, + OpDemoteToHelperInvocationEXT = 5380, + OpIsHelperInvocationEXT = 5381, + OpSubgroupShuffleINTEL = 5571, + OpSubgroupShuffleDownINTEL = 5572, + OpSubgroupShuffleUpINTEL = 5573, + OpSubgroupShuffleXorINTEL = 5574, + OpSubgroupBlockReadINTEL = 5575, + OpSubgroupBlockWriteINTEL = 5576, + OpSubgroupImageBlockReadINTEL = 5577, + OpSubgroupImageBlockWriteINTEL = 5578, + OpSubgroupImageMediaBlockReadINTEL = 5580, + OpSubgroupImageMediaBlockWriteINTEL = 5581, + OpUCountLeadingZerosINTEL = 5585, + OpUCountTrailingZerosINTEL = 5586, + OpAbsISubINTEL = 5587, + OpAbsUSubINTEL = 5588, + OpIAddSatINTEL = 5589, + OpUAddSatINTEL = 5590, + OpIAverageINTEL = 5591, + OpUAverageINTEL = 5592, + OpIAverageRoundedINTEL = 5593, + OpUAverageRoundedINTEL = 5594, + OpISubSatINTEL = 5595, + OpUSubSatINTEL = 5596, + OpIMul32x16INTEL = 5597, + OpUMul32x16INTEL = 5598, + OpDecorateString = 5632, + OpDecorateStringGOOGLE = 5632, + OpMemberDecorateString = 5633, + OpMemberDecorateStringGOOGLE = 5633, + OpVmeImageINTEL = 5699, + OpTypeVmeImageINTEL = 5700, + OpTypeAvcImePayloadINTEL = 5701, + OpTypeAvcRefPayloadINTEL = 5702, + OpTypeAvcSicPayloadINTEL = 5703, + OpTypeAvcMcePayloadINTEL = 5704, + OpTypeAvcMceResultINTEL = 5705, + OpTypeAvcImeResultINTEL = 5706, + OpTypeAvcImeResultSingleReferenceStreamoutINTEL = 5707, + OpTypeAvcImeResultDualReferenceStreamoutINTEL = 5708, + OpTypeAvcImeSingleReferenceStreaminINTEL = 5709, + OpTypeAvcImeDualReferenceStreaminINTEL = 5710, + OpTypeAvcRefResultINTEL = 5711, + OpTypeAvcSicResultINTEL = 5712, + OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL = 5713, + OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL = 5714, + OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL = 5715, + OpSubgroupAvcMceSetInterShapePenaltyINTEL = 5716, + OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL = 5717, + OpSubgroupAvcMceSetInterDirectionPenaltyINTEL = 5718, + OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL = 5719, + OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL = 5720, + OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL = 5721, + OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL = 5722, + OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL = 5723, + OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL = 5724, + OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL = 5725, + OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL = 5726, + OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL = 5727, + OpSubgroupAvcMceSetAcOnlyHaarINTEL = 5728, + OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL = 5729, + OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL = 5730, + OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL = 5731, + OpSubgroupAvcMceConvertToImePayloadINTEL = 5732, + OpSubgroupAvcMceConvertToImeResultINTEL = 5733, + OpSubgroupAvcMceConvertToRefPayloadINTEL = 5734, + OpSubgroupAvcMceConvertToRefResultINTEL = 5735, + OpSubgroupAvcMceConvertToSicPayloadINTEL = 5736, + OpSubgroupAvcMceConvertToSicResultINTEL = 5737, + OpSubgroupAvcMceGetMotionVectorsINTEL = 5738, + OpSubgroupAvcMceGetInterDistortionsINTEL = 5739, + OpSubgroupAvcMceGetBestInterDistortionsINTEL = 5740, + OpSubgroupAvcMceGetInterMajorShapeINTEL = 5741, + OpSubgroupAvcMceGetInterMinorShapeINTEL = 5742, + OpSubgroupAvcMceGetInterDirectionsINTEL = 5743, + OpSubgroupAvcMceGetInterMotionVectorCountINTEL = 5744, + OpSubgroupAvcMceGetInterReferenceIdsINTEL = 5745, + OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL = 5746, + OpSubgroupAvcImeInitializeINTEL = 5747, + OpSubgroupAvcImeSetSingleReferenceINTEL = 5748, + OpSubgroupAvcImeSetDualReferenceINTEL = 5749, + OpSubgroupAvcImeRefWindowSizeINTEL = 5750, + OpSubgroupAvcImeAdjustRefOffsetINTEL = 5751, + OpSubgroupAvcImeConvertToMcePayloadINTEL = 5752, + OpSubgroupAvcImeSetMaxMotionVectorCountINTEL = 5753, + OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL = 5754, + OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL = 5755, + OpSubgroupAvcImeSetWeightedSadINTEL = 5756, + OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL = 5757, + OpSubgroupAvcImeEvaluateWithDualReferenceINTEL = 5758, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL = 5759, + OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL = 5760, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL = 5761, + OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL = 5762, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL = 5763, + OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL = 5764, + OpSubgroupAvcImeConvertToMceResultINTEL = 5765, + OpSubgroupAvcImeGetSingleReferenceStreaminINTEL = 5766, + OpSubgroupAvcImeGetDualReferenceStreaminINTEL = 5767, + OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL = 5768, + OpSubgroupAvcImeStripDualReferenceStreamoutINTEL = 5769, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL = 5770, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL = 5771, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL = 5772, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL = 5773, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL = 5774, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL = 5775, + OpSubgroupAvcImeGetBorderReachedINTEL = 5776, + OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL = 5777, + OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL = 5778, + OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL = 5779, + OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL = 5780, + OpSubgroupAvcFmeInitializeINTEL = 5781, + OpSubgroupAvcBmeInitializeINTEL = 5782, + OpSubgroupAvcRefConvertToMcePayloadINTEL = 5783, + OpSubgroupAvcRefSetBidirectionalMixDisableINTEL = 5784, + OpSubgroupAvcRefSetBilinearFilterEnableINTEL = 5785, + OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL = 5786, + OpSubgroupAvcRefEvaluateWithDualReferenceINTEL = 5787, + OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL = 5788, + OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL = 5789, + OpSubgroupAvcRefConvertToMceResultINTEL = 5790, + OpSubgroupAvcSicInitializeINTEL = 5791, + OpSubgroupAvcSicConfigureSkcINTEL = 5792, + OpSubgroupAvcSicConfigureIpeLumaINTEL = 5793, + OpSubgroupAvcSicConfigureIpeLumaChromaINTEL = 5794, + OpSubgroupAvcSicGetMotionVectorMaskINTEL = 5795, + OpSubgroupAvcSicConvertToMcePayloadINTEL = 5796, + OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL = 5797, + OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL = 5798, + OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL = 5799, + OpSubgroupAvcSicSetBilinearFilterEnableINTEL = 5800, + OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL = 5801, + OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL = 5802, + OpSubgroupAvcSicEvaluateIpeINTEL = 5803, + OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL = 5804, + OpSubgroupAvcSicEvaluateWithDualReferenceINTEL = 5805, + OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL = 5806, + OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL = 5807, + OpSubgroupAvcSicConvertToMceResultINTEL = 5808, + OpSubgroupAvcSicGetIpeLumaShapeINTEL = 5809, + OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL = 5810, + OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL = 5811, + OpSubgroupAvcSicGetPackedIpeLumaModesINTEL = 5812, + OpSubgroupAvcSicGetIpeChromaModeINTEL = 5813, + OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, + OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, + OpSubgroupAvcSicGetInterRawSadsINTEL = 5816, + OpRayQueryGetRayTMinKHR = 6016, + OpRayQueryGetRayFlagsKHR = 6017, + OpRayQueryGetIntersectionTKHR = 6018, + OpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019, + OpRayQueryGetIntersectionInstanceIdKHR = 6020, + OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021, + OpRayQueryGetIntersectionGeometryIndexKHR = 6022, + OpRayQueryGetIntersectionPrimitiveIndexKHR = 6023, + OpRayQueryGetIntersectionBarycentricsKHR = 6024, + OpRayQueryGetIntersectionFrontFaceKHR = 6025, + OpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026, + OpRayQueryGetIntersectionObjectRayDirectionKHR = 6027, + OpRayQueryGetIntersectionObjectRayOriginKHR = 6028, + OpRayQueryGetWorldRayDirectionKHR = 6029, + OpRayQueryGetWorldRayOriginKHR = 6030, + OpRayQueryGetIntersectionObjectToWorldKHR = 6031, + OpRayQueryGetIntersectionWorldToObjectKHR = 6032, + OpMax = 0x7fffffff, +}; + +#ifdef SPV_ENABLE_UTILITY_CODE +inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) { + *hasResult = *hasResultType = false; + switch (opcode) { + default: /* unknown opcode */ break; + case OpNop: *hasResult = false; *hasResultType = false; break; + case OpUndef: *hasResult = true; *hasResultType = true; break; + case OpSourceContinued: *hasResult = false; *hasResultType = false; break; + case OpSource: *hasResult = false; *hasResultType = false; break; + case OpSourceExtension: *hasResult = false; *hasResultType = false; break; + case OpName: *hasResult = false; *hasResultType = false; break; + case OpMemberName: *hasResult = false; *hasResultType = false; break; + case OpString: *hasResult = true; *hasResultType = false; break; + case OpLine: *hasResult = false; *hasResultType = false; break; + case OpExtension: *hasResult = false; *hasResultType = false; break; + case OpExtInstImport: *hasResult = true; *hasResultType = false; break; + case OpExtInst: *hasResult = true; *hasResultType = true; break; + case OpMemoryModel: *hasResult = false; *hasResultType = false; break; + case OpEntryPoint: *hasResult = false; *hasResultType = false; break; + case OpExecutionMode: *hasResult = false; *hasResultType = false; break; + case OpCapability: *hasResult = false; *hasResultType = false; break; + case OpTypeVoid: *hasResult = true; *hasResultType = false; break; + case OpTypeBool: *hasResult = true; *hasResultType = false; break; + case OpTypeInt: *hasResult = true; *hasResultType = false; break; + case OpTypeFloat: *hasResult = true; *hasResultType = false; break; + case OpTypeVector: *hasResult = true; *hasResultType = false; break; + case OpTypeMatrix: *hasResult = true; *hasResultType = false; break; + case OpTypeImage: *hasResult = true; *hasResultType = false; break; + case OpTypeSampler: *hasResult = true; *hasResultType = false; break; + case OpTypeSampledImage: *hasResult = true; *hasResultType = false; break; + case OpTypeArray: *hasResult = true; *hasResultType = false; break; + case OpTypeRuntimeArray: *hasResult = true; *hasResultType = false; break; + case OpTypeStruct: *hasResult = true; *hasResultType = false; break; + case OpTypeOpaque: *hasResult = true; *hasResultType = false; break; + case OpTypePointer: *hasResult = true; *hasResultType = false; break; + case OpTypeFunction: *hasResult = true; *hasResultType = false; break; + case OpTypeEvent: *hasResult = true; *hasResultType = false; break; + case OpTypeDeviceEvent: *hasResult = true; *hasResultType = false; break; + case OpTypeReserveId: *hasResult = true; *hasResultType = false; break; + case OpTypeQueue: *hasResult = true; *hasResultType = false; break; + case OpTypePipe: *hasResult = true; *hasResultType = false; break; + case OpTypeForwardPointer: *hasResult = false; *hasResultType = false; break; + case OpConstantTrue: *hasResult = true; *hasResultType = true; break; + case OpConstantFalse: *hasResult = true; *hasResultType = true; break; + case OpConstant: *hasResult = true; *hasResultType = true; break; + case OpConstantComposite: *hasResult = true; *hasResultType = true; break; + case OpConstantSampler: *hasResult = true; *hasResultType = true; break; + case OpConstantNull: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantTrue: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantFalse: *hasResult = true; *hasResultType = true; break; + case OpSpecConstant: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantComposite: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantOp: *hasResult = true; *hasResultType = true; break; + case OpFunction: *hasResult = true; *hasResultType = true; break; + case OpFunctionParameter: *hasResult = true; *hasResultType = true; break; + case OpFunctionEnd: *hasResult = false; *hasResultType = false; break; + case OpFunctionCall: *hasResult = true; *hasResultType = true; break; + case OpVariable: *hasResult = true; *hasResultType = true; break; + case OpImageTexelPointer: *hasResult = true; *hasResultType = true; break; + case OpLoad: *hasResult = true; *hasResultType = true; break; + case OpStore: *hasResult = false; *hasResultType = false; break; + case OpCopyMemory: *hasResult = false; *hasResultType = false; break; + case OpCopyMemorySized: *hasResult = false; *hasResultType = false; break; + case OpAccessChain: *hasResult = true; *hasResultType = true; break; + case OpInBoundsAccessChain: *hasResult = true; *hasResultType = true; break; + case OpPtrAccessChain: *hasResult = true; *hasResultType = true; break; + case OpArrayLength: *hasResult = true; *hasResultType = true; break; + case OpGenericPtrMemSemantics: *hasResult = true; *hasResultType = true; break; + case OpInBoundsPtrAccessChain: *hasResult = true; *hasResultType = true; break; + case OpDecorate: *hasResult = false; *hasResultType = false; break; + case OpMemberDecorate: *hasResult = false; *hasResultType = false; break; + case OpDecorationGroup: *hasResult = true; *hasResultType = false; break; + case OpGroupDecorate: *hasResult = false; *hasResultType = false; break; + case OpGroupMemberDecorate: *hasResult = false; *hasResultType = false; break; + case OpVectorExtractDynamic: *hasResult = true; *hasResultType = true; break; + case OpVectorInsertDynamic: *hasResult = true; *hasResultType = true; break; + case OpVectorShuffle: *hasResult = true; *hasResultType = true; break; + case OpCompositeConstruct: *hasResult = true; *hasResultType = true; break; + case OpCompositeExtract: *hasResult = true; *hasResultType = true; break; + case OpCompositeInsert: *hasResult = true; *hasResultType = true; break; + case OpCopyObject: *hasResult = true; *hasResultType = true; break; + case OpTranspose: *hasResult = true; *hasResultType = true; break; + case OpSampledImage: *hasResult = true; *hasResultType = true; break; + case OpImageSampleImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageFetch: *hasResult = true; *hasResultType = true; break; + case OpImageGather: *hasResult = true; *hasResultType = true; break; + case OpImageDrefGather: *hasResult = true; *hasResultType = true; break; + case OpImageRead: *hasResult = true; *hasResultType = true; break; + case OpImageWrite: *hasResult = false; *hasResultType = false; break; + case OpImage: *hasResult = true; *hasResultType = true; break; + case OpImageQueryFormat: *hasResult = true; *hasResultType = true; break; + case OpImageQueryOrder: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySizeLod: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySize: *hasResult = true; *hasResultType = true; break; + case OpImageQueryLod: *hasResult = true; *hasResultType = true; break; + case OpImageQueryLevels: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySamples: *hasResult = true; *hasResultType = true; break; + case OpConvertFToU: *hasResult = true; *hasResultType = true; break; + case OpConvertFToS: *hasResult = true; *hasResultType = true; break; + case OpConvertSToF: *hasResult = true; *hasResultType = true; break; + case OpConvertUToF: *hasResult = true; *hasResultType = true; break; + case OpUConvert: *hasResult = true; *hasResultType = true; break; + case OpSConvert: *hasResult = true; *hasResultType = true; break; + case OpFConvert: *hasResult = true; *hasResultType = true; break; + case OpQuantizeToF16: *hasResult = true; *hasResultType = true; break; + case OpConvertPtrToU: *hasResult = true; *hasResultType = true; break; + case OpSatConvertSToU: *hasResult = true; *hasResultType = true; break; + case OpSatConvertUToS: *hasResult = true; *hasResultType = true; break; + case OpConvertUToPtr: *hasResult = true; *hasResultType = true; break; + case OpPtrCastToGeneric: *hasResult = true; *hasResultType = true; break; + case OpGenericCastToPtr: *hasResult = true; *hasResultType = true; break; + case OpGenericCastToPtrExplicit: *hasResult = true; *hasResultType = true; break; + case OpBitcast: *hasResult = true; *hasResultType = true; break; + case OpSNegate: *hasResult = true; *hasResultType = true; break; + case OpFNegate: *hasResult = true; *hasResultType = true; break; + case OpIAdd: *hasResult = true; *hasResultType = true; break; + case OpFAdd: *hasResult = true; *hasResultType = true; break; + case OpISub: *hasResult = true; *hasResultType = true; break; + case OpFSub: *hasResult = true; *hasResultType = true; break; + case OpIMul: *hasResult = true; *hasResultType = true; break; + case OpFMul: *hasResult = true; *hasResultType = true; break; + case OpUDiv: *hasResult = true; *hasResultType = true; break; + case OpSDiv: *hasResult = true; *hasResultType = true; break; + case OpFDiv: *hasResult = true; *hasResultType = true; break; + case OpUMod: *hasResult = true; *hasResultType = true; break; + case OpSRem: *hasResult = true; *hasResultType = true; break; + case OpSMod: *hasResult = true; *hasResultType = true; break; + case OpFRem: *hasResult = true; *hasResultType = true; break; + case OpFMod: *hasResult = true; *hasResultType = true; break; + case OpVectorTimesScalar: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesScalar: *hasResult = true; *hasResultType = true; break; + case OpVectorTimesMatrix: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesVector: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesMatrix: *hasResult = true; *hasResultType = true; break; + case OpOuterProduct: *hasResult = true; *hasResultType = true; break; + case OpDot: *hasResult = true; *hasResultType = true; break; + case OpIAddCarry: *hasResult = true; *hasResultType = true; break; + case OpISubBorrow: *hasResult = true; *hasResultType = true; break; + case OpUMulExtended: *hasResult = true; *hasResultType = true; break; + case OpSMulExtended: *hasResult = true; *hasResultType = true; break; + case OpAny: *hasResult = true; *hasResultType = true; break; + case OpAll: *hasResult = true; *hasResultType = true; break; + case OpIsNan: *hasResult = true; *hasResultType = true; break; + case OpIsInf: *hasResult = true; *hasResultType = true; break; + case OpIsFinite: *hasResult = true; *hasResultType = true; break; + case OpIsNormal: *hasResult = true; *hasResultType = true; break; + case OpSignBitSet: *hasResult = true; *hasResultType = true; break; + case OpLessOrGreater: *hasResult = true; *hasResultType = true; break; + case OpOrdered: *hasResult = true; *hasResultType = true; break; + case OpUnordered: *hasResult = true; *hasResultType = true; break; + case OpLogicalEqual: *hasResult = true; *hasResultType = true; break; + case OpLogicalNotEqual: *hasResult = true; *hasResultType = true; break; + case OpLogicalOr: *hasResult = true; *hasResultType = true; break; + case OpLogicalAnd: *hasResult = true; *hasResultType = true; break; + case OpLogicalNot: *hasResult = true; *hasResultType = true; break; + case OpSelect: *hasResult = true; *hasResultType = true; break; + case OpIEqual: *hasResult = true; *hasResultType = true; break; + case OpINotEqual: *hasResult = true; *hasResultType = true; break; + case OpUGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpSGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpUGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpSGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpULessThan: *hasResult = true; *hasResultType = true; break; + case OpSLessThan: *hasResult = true; *hasResultType = true; break; + case OpULessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpSLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdNotEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordNotEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdLessThan: *hasResult = true; *hasResultType = true; break; + case OpFUnordLessThan: *hasResult = true; *hasResultType = true; break; + case OpFOrdGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpFUnordGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpFOrdLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpShiftRightLogical: *hasResult = true; *hasResultType = true; break; + case OpShiftRightArithmetic: *hasResult = true; *hasResultType = true; break; + case OpShiftLeftLogical: *hasResult = true; *hasResultType = true; break; + case OpBitwiseOr: *hasResult = true; *hasResultType = true; break; + case OpBitwiseXor: *hasResult = true; *hasResultType = true; break; + case OpBitwiseAnd: *hasResult = true; *hasResultType = true; break; + case OpNot: *hasResult = true; *hasResultType = true; break; + case OpBitFieldInsert: *hasResult = true; *hasResultType = true; break; + case OpBitFieldSExtract: *hasResult = true; *hasResultType = true; break; + case OpBitFieldUExtract: *hasResult = true; *hasResultType = true; break; + case OpBitReverse: *hasResult = true; *hasResultType = true; break; + case OpBitCount: *hasResult = true; *hasResultType = true; break; + case OpDPdx: *hasResult = true; *hasResultType = true; break; + case OpDPdy: *hasResult = true; *hasResultType = true; break; + case OpFwidth: *hasResult = true; *hasResultType = true; break; + case OpDPdxFine: *hasResult = true; *hasResultType = true; break; + case OpDPdyFine: *hasResult = true; *hasResultType = true; break; + case OpFwidthFine: *hasResult = true; *hasResultType = true; break; + case OpDPdxCoarse: *hasResult = true; *hasResultType = true; break; + case OpDPdyCoarse: *hasResult = true; *hasResultType = true; break; + case OpFwidthCoarse: *hasResult = true; *hasResultType = true; break; + case OpEmitVertex: *hasResult = false; *hasResultType = false; break; + case OpEndPrimitive: *hasResult = false; *hasResultType = false; break; + case OpEmitStreamVertex: *hasResult = false; *hasResultType = false; break; + case OpEndStreamPrimitive: *hasResult = false; *hasResultType = false; break; + case OpControlBarrier: *hasResult = false; *hasResultType = false; break; + case OpMemoryBarrier: *hasResult = false; *hasResultType = false; break; + case OpAtomicLoad: *hasResult = true; *hasResultType = true; break; + case OpAtomicStore: *hasResult = false; *hasResultType = false; break; + case OpAtomicExchange: *hasResult = true; *hasResultType = true; break; + case OpAtomicCompareExchange: *hasResult = true; *hasResultType = true; break; + case OpAtomicCompareExchangeWeak: *hasResult = true; *hasResultType = true; break; + case OpAtomicIIncrement: *hasResult = true; *hasResultType = true; break; + case OpAtomicIDecrement: *hasResult = true; *hasResultType = true; break; + case OpAtomicIAdd: *hasResult = true; *hasResultType = true; break; + case OpAtomicISub: *hasResult = true; *hasResultType = true; break; + case OpAtomicSMin: *hasResult = true; *hasResultType = true; break; + case OpAtomicUMin: *hasResult = true; *hasResultType = true; break; + case OpAtomicSMax: *hasResult = true; *hasResultType = true; break; + case OpAtomicUMax: *hasResult = true; *hasResultType = true; break; + case OpAtomicAnd: *hasResult = true; *hasResultType = true; break; + case OpAtomicOr: *hasResult = true; *hasResultType = true; break; + case OpAtomicXor: *hasResult = true; *hasResultType = true; break; + case OpPhi: *hasResult = true; *hasResultType = true; break; + case OpLoopMerge: *hasResult = false; *hasResultType = false; break; + case OpSelectionMerge: *hasResult = false; *hasResultType = false; break; + case OpLabel: *hasResult = true; *hasResultType = false; break; + case OpBranch: *hasResult = false; *hasResultType = false; break; + case OpBranchConditional: *hasResult = false; *hasResultType = false; break; + case OpSwitch: *hasResult = false; *hasResultType = false; break; + case OpKill: *hasResult = false; *hasResultType = false; break; + case OpReturn: *hasResult = false; *hasResultType = false; break; + case OpReturnValue: *hasResult = false; *hasResultType = false; break; + case OpUnreachable: *hasResult = false; *hasResultType = false; break; + case OpLifetimeStart: *hasResult = false; *hasResultType = false; break; + case OpLifetimeStop: *hasResult = false; *hasResultType = false; break; + case OpGroupAsyncCopy: *hasResult = true; *hasResultType = true; break; + case OpGroupWaitEvents: *hasResult = false; *hasResultType = false; break; + case OpGroupAll: *hasResult = true; *hasResultType = true; break; + case OpGroupAny: *hasResult = true; *hasResultType = true; break; + case OpGroupBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupIAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupFAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupFMin: *hasResult = true; *hasResultType = true; break; + case OpGroupUMin: *hasResult = true; *hasResultType = true; break; + case OpGroupSMin: *hasResult = true; *hasResultType = true; break; + case OpGroupFMax: *hasResult = true; *hasResultType = true; break; + case OpGroupUMax: *hasResult = true; *hasResultType = true; break; + case OpGroupSMax: *hasResult = true; *hasResultType = true; break; + case OpReadPipe: *hasResult = true; *hasResultType = true; break; + case OpWritePipe: *hasResult = true; *hasResultType = true; break; + case OpReservedReadPipe: *hasResult = true; *hasResultType = true; break; + case OpReservedWritePipe: *hasResult = true; *hasResultType = true; break; + case OpReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; + case OpReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; + case OpCommitReadPipe: *hasResult = false; *hasResultType = false; break; + case OpCommitWritePipe: *hasResult = false; *hasResultType = false; break; + case OpIsValidReserveId: *hasResult = true; *hasResultType = true; break; + case OpGetNumPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGetMaxPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupCommitReadPipe: *hasResult = false; *hasResultType = false; break; + case OpGroupCommitWritePipe: *hasResult = false; *hasResultType = false; break; + case OpEnqueueMarker: *hasResult = true; *hasResultType = true; break; + case OpEnqueueKernel: *hasResult = true; *hasResultType = true; break; + case OpGetKernelNDrangeSubGroupCount: *hasResult = true; *hasResultType = true; break; + case OpGetKernelNDrangeMaxSubGroupSize: *hasResult = true; *hasResultType = true; break; + case OpGetKernelWorkGroupSize: *hasResult = true; *hasResultType = true; break; + case OpGetKernelPreferredWorkGroupSizeMultiple: *hasResult = true; *hasResultType = true; break; + case OpRetainEvent: *hasResult = false; *hasResultType = false; break; + case OpReleaseEvent: *hasResult = false; *hasResultType = false; break; + case OpCreateUserEvent: *hasResult = true; *hasResultType = true; break; + case OpIsValidEvent: *hasResult = true; *hasResultType = true; break; + case OpSetUserEventStatus: *hasResult = false; *hasResultType = false; break; + case OpCaptureEventProfilingInfo: *hasResult = false; *hasResultType = false; break; + case OpGetDefaultQueue: *hasResult = true; *hasResultType = true; break; + case OpBuildNDRange: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseFetch: *hasResult = true; *hasResultType = true; break; + case OpImageSparseGather: *hasResult = true; *hasResultType = true; break; + case OpImageSparseDrefGather: *hasResult = true; *hasResultType = true; break; + case OpImageSparseTexelsResident: *hasResult = true; *hasResultType = true; break; + case OpNoLine: *hasResult = false; *hasResultType = false; break; + case OpAtomicFlagTestAndSet: *hasResult = true; *hasResultType = true; break; + case OpAtomicFlagClear: *hasResult = false; *hasResultType = false; break; + case OpImageSparseRead: *hasResult = true; *hasResultType = true; break; + case OpSizeOf: *hasResult = true; *hasResultType = true; break; + case OpTypePipeStorage: *hasResult = true; *hasResultType = false; break; + case OpConstantPipeStorage: *hasResult = true; *hasResultType = true; break; + case OpCreatePipeFromPipeStorage: *hasResult = true; *hasResultType = true; break; + case OpGetKernelLocalSizeForSubgroupCount: *hasResult = true; *hasResultType = true; break; + case OpGetKernelMaxNumSubgroups: *hasResult = true; *hasResultType = true; break; + case OpTypeNamedBarrier: *hasResult = true; *hasResultType = false; break; + case OpNamedBarrierInitialize: *hasResult = true; *hasResultType = true; break; + case OpMemoryNamedBarrier: *hasResult = false; *hasResultType = false; break; + case OpModuleProcessed: *hasResult = false; *hasResultType = false; break; + case OpExecutionModeId: *hasResult = false; *hasResultType = false; break; + case OpDecorateId: *hasResult = false; *hasResultType = false; break; + case OpGroupNonUniformElect: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAll: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAny: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAllEqual: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBroadcastFirst: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallot: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformInverseBallot: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotBitExtract: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotBitCount: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotFindLSB: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotFindMSB: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffle: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleUp: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleDown: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformIAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformIMul: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMul: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformSMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformUMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformSMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformUMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseAnd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseOr: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalAnd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalOr: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformQuadBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformQuadSwap: *hasResult = true; *hasResultType = true; break; + case OpCopyLogical: *hasResult = true; *hasResultType = true; break; + case OpPtrEqual: *hasResult = true; *hasResultType = true; break; + case OpPtrNotEqual: *hasResult = true; *hasResultType = true; break; + case OpPtrDiff: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break; + case OpTypeRayQueryProvisionalKHR: *hasResult = true; *hasResultType = false; break; + case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break; + case OpGroupIAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupUMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupSMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupUMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupSMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpFragmentMaskFetchAMD: *hasResult = true; *hasResultType = true; break; + case OpFragmentFetchAMD: *hasResult = true; *hasResultType = true; break; + case OpReadClockKHR: *hasResult = true; *hasResultType = true; break; + case OpImageSampleFootprintNV: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformPartitionNV: *hasResult = true; *hasResultType = true; break; + case OpWritePackedPrimitiveIndices4x8NV: *hasResult = false; *hasResultType = false; break; + case OpReportIntersectionNV: *hasResult = true; *hasResultType = true; break; + case OpIgnoreIntersectionNV: *hasResult = false; *hasResultType = false; break; + case OpTerminateRayNV: *hasResult = false; *hasResultType = false; break; + case OpTraceNV: *hasResult = false; *hasResultType = false; break; + case OpTypeAccelerationStructureNV: *hasResult = true; *hasResultType = false; break; + case OpExecuteCallableNV: *hasResult = false; *hasResultType = false; break; + case OpTypeCooperativeMatrixNV: *hasResult = true; *hasResultType = false; break; + case OpCooperativeMatrixLoadNV: *hasResult = true; *hasResultType = true; break; + case OpCooperativeMatrixStoreNV: *hasResult = false; *hasResultType = false; break; + case OpCooperativeMatrixMulAddNV: *hasResult = true; *hasResultType = true; break; + case OpCooperativeMatrixLengthNV: *hasResult = true; *hasResultType = true; break; + case OpBeginInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; + case OpEndInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; + case OpDemoteToHelperInvocationEXT: *hasResult = false; *hasResultType = false; break; + case OpIsHelperInvocationEXT: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleDownINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleUpINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleXorINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpSubgroupImageBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupImageBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpSubgroupImageMediaBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupImageMediaBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpUCountLeadingZerosINTEL: *hasResult = true; *hasResultType = true; break; + case OpUCountTrailingZerosINTEL: *hasResult = true; *hasResultType = true; break; + case OpAbsISubINTEL: *hasResult = true; *hasResultType = true; break; + case OpAbsUSubINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAddSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAddSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAverageINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAverageINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; + case OpISubSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break; + case OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break; + case OpDecorateString: *hasResult = false; *hasResultType = false; break; + case OpMemberDecorateString: *hasResult = false; *hasResultType = false; break; + case OpVmeImageINTEL: *hasResult = true; *hasResultType = true; break; + case OpTypeVmeImageINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImePayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcRefPayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcSicPayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcMcePayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcMceResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcRefResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcSicResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetAcOnlyHaarINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToImePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToImeResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToRefPayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToRefResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToSicPayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToSicResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetBestInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMajorShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMinorShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterDirectionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeRefWindowSizeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeAdjustRefOffsetINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetMaxMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetWeightedSadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeStripDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetBorderReachedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcFmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcBmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefSetBidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureSkcINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureIpeLumaINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureIpeLumaChromaINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetMotionVectorMaskINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateIpeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetIpeLumaShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedIpeLumaModesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetIpeChromaModeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetRayTMinKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetRayFlagsKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionTKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceCustomIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceIdKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionGeometryIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionPrimitiveIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionBarycentricsKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionFrontFaceKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetWorldRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetWorldRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break; + } +} +#endif /* SPV_ENABLE_UTILITY_CODE */ + +// Overload operator| for mask bit combining + +inline ImageOperandsMask operator|(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) | unsigned(b)); } +inline FPFastMathModeMask operator|(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) | unsigned(b)); } +inline SelectionControlMask operator|(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) | unsigned(b)); } +inline LoopControlMask operator|(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) | unsigned(b)); } +inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) | unsigned(b)); } +inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); } +inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); } +inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); } +inline RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); } + +} // end namespace spv + +#endif // #ifndef spirv_HPP + diff --git a/android/arm64-v8a/include/glslang/SPIRV/spvIR.h b/android/arm64-v8a/include/glslang/SPIRV/spvIR.h new file mode 100644 index 00000000..6523035e --- /dev/null +++ b/android/arm64-v8a/include/glslang/SPIRV/spvIR.h @@ -0,0 +1,485 @@ +// +// Copyright (C) 2014 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// SPIRV-IR +// +// Simple in-memory representation (IR) of SPIRV. Just for holding +// Each function's CFG of blocks. Has this hierarchy: +// - Module, which is a list of +// - Function, which is a list of +// - Block, which is a list of +// - Instruction +// + +#pragma once +#ifndef spvIR_H +#define spvIR_H + +#include "spirv.hpp" + +#include +#include +#include +#include +#include +#include + +namespace spv { + +class Block; +class Function; +class Module; + +const Id NoResult = 0; +const Id NoType = 0; + +const Decoration NoPrecision = DecorationMax; + +#ifdef __GNUC__ +# define POTENTIALLY_UNUSED __attribute__((unused)) +#else +# define POTENTIALLY_UNUSED +#endif + +POTENTIALLY_UNUSED +const MemorySemanticsMask MemorySemanticsAllMemory = + (MemorySemanticsMask)(MemorySemanticsUniformMemoryMask | + MemorySemanticsWorkgroupMemoryMask | + MemorySemanticsAtomicCounterMemoryMask | + MemorySemanticsImageMemoryMask); + +struct IdImmediate { + bool isId; // true if word is an Id, false if word is an immediate + unsigned word; + IdImmediate(bool i, unsigned w) : isId(i), word(w) {} +}; + +// +// SPIR-V IR instruction. +// + +class Instruction { +public: + Instruction(Id resultId, Id typeId, Op opCode) : resultId(resultId), typeId(typeId), opCode(opCode), block(nullptr) { } + explicit Instruction(Op opCode) : resultId(NoResult), typeId(NoType), opCode(opCode), block(nullptr) { } + virtual ~Instruction() {} + void addIdOperand(Id id) { + operands.push_back(id); + idOperand.push_back(true); + } + void addImmediateOperand(unsigned int immediate) { + operands.push_back(immediate); + idOperand.push_back(false); + } + void setImmediateOperand(unsigned idx, unsigned int immediate) { + assert(!idOperand[idx]); + operands[idx] = immediate; + } + + void addStringOperand(const char* str) + { + unsigned int word; + char* wordString = (char*)&word; + char* wordPtr = wordString; + int charCount = 0; + char c; + do { + c = *(str++); + *(wordPtr++) = c; + ++charCount; + if (charCount == 4) { + addImmediateOperand(word); + wordPtr = wordString; + charCount = 0; + } + } while (c != 0); + + // deal with partial last word + if (charCount > 0) { + // pad with 0s + for (; charCount < 4; ++charCount) + *(wordPtr++) = 0; + addImmediateOperand(word); + } + } + bool isIdOperand(int op) const { return idOperand[op]; } + void setBlock(Block* b) { block = b; } + Block* getBlock() const { return block; } + Op getOpCode() const { return opCode; } + int getNumOperands() const + { + assert(operands.size() == idOperand.size()); + return (int)operands.size(); + } + Id getResultId() const { return resultId; } + Id getTypeId() const { return typeId; } + Id getIdOperand(int op) const { + assert(idOperand[op]); + return operands[op]; + } + unsigned int getImmediateOperand(int op) const { + assert(!idOperand[op]); + return operands[op]; + } + + // Write out the binary form. + void dump(std::vector& out) const + { + // Compute the wordCount + unsigned int wordCount = 1; + if (typeId) + ++wordCount; + if (resultId) + ++wordCount; + wordCount += (unsigned int)operands.size(); + + // Write out the beginning of the instruction + out.push_back(((wordCount) << WordCountShift) | opCode); + if (typeId) + out.push_back(typeId); + if (resultId) + out.push_back(resultId); + + // Write out the operands + for (int op = 0; op < (int)operands.size(); ++op) + out.push_back(operands[op]); + } + +protected: + Instruction(const Instruction&); + Id resultId; + Id typeId; + Op opCode; + std::vector operands; // operands, both and immediates (both are unsigned int) + std::vector idOperand; // true for operands that are , false for immediates + Block* block; +}; + +// +// SPIR-V IR block. +// + +class Block { +public: + Block(Id id, Function& parent); + virtual ~Block() + { + } + + Id getId() { return instructions.front()->getResultId(); } + + Function& getParent() const { return parent; } + void addInstruction(std::unique_ptr inst); + void addPredecessor(Block* pred) { predecessors.push_back(pred); pred->successors.push_back(this);} + void addLocalVariable(std::unique_ptr inst) { localVariables.push_back(std::move(inst)); } + const std::vector& getPredecessors() const { return predecessors; } + const std::vector& getSuccessors() const { return successors; } + const std::vector >& getInstructions() const { + return instructions; + } + const std::vector >& getLocalVariables() const { return localVariables; } + void setUnreachable() { unreachable = true; } + bool isUnreachable() const { return unreachable; } + // Returns the block's merge instruction, if one exists (otherwise null). + const Instruction* getMergeInstruction() const { + if (instructions.size() < 2) return nullptr; + const Instruction* nextToLast = (instructions.cend() - 2)->get(); + switch (nextToLast->getOpCode()) { + case OpSelectionMerge: + case OpLoopMerge: + return nextToLast; + default: + return nullptr; + } + return nullptr; + } + + // Change this block into a canonical dead merge block. Delete instructions + // as necessary. A canonical dead merge block has only an OpLabel and an + // OpUnreachable. + void rewriteAsCanonicalUnreachableMerge() { + assert(localVariables.empty()); + // Delete all instructions except for the label. + assert(instructions.size() > 0); + instructions.resize(1); + successors.clear(); + addInstruction(std::unique_ptr(new Instruction(OpUnreachable))); + } + // Change this block into a canonical dead continue target branching to the + // given header ID. Delete instructions as necessary. A canonical dead continue + // target has only an OpLabel and an unconditional branch back to the corresponding + // header. + void rewriteAsCanonicalUnreachableContinue(Block* header) { + assert(localVariables.empty()); + // Delete all instructions except for the label. + assert(instructions.size() > 0); + instructions.resize(1); + successors.clear(); + // Add OpBranch back to the header. + assert(header != nullptr); + Instruction* branch = new Instruction(OpBranch); + branch->addIdOperand(header->getId()); + addInstruction(std::unique_ptr(branch)); + successors.push_back(header); + } + + bool isTerminated() const + { + switch (instructions.back()->getOpCode()) { + case OpBranch: + case OpBranchConditional: + case OpSwitch: + case OpKill: + case OpReturn: + case OpReturnValue: + case OpUnreachable: + return true; + default: + return false; + } + } + + void dump(std::vector& out) const + { + instructions[0]->dump(out); + for (int i = 0; i < (int)localVariables.size(); ++i) + localVariables[i]->dump(out); + for (int i = 1; i < (int)instructions.size(); ++i) + instructions[i]->dump(out); + } + +protected: + Block(const Block&); + Block& operator=(Block&); + + // To enforce keeping parent and ownership in sync: + friend Function; + + std::vector > instructions; + std::vector predecessors, successors; + std::vector > localVariables; + Function& parent; + + // track whether this block is known to be uncreachable (not necessarily + // true for all unreachable blocks, but should be set at least + // for the extraneous ones introduced by the builder). + bool unreachable; +}; + +// The different reasons for reaching a block in the inReadableOrder traversal. +enum ReachReason { + // Reachable from the entry block via transfers of control, i.e. branches. + ReachViaControlFlow = 0, + // A continue target that is not reachable via control flow. + ReachDeadContinue, + // A merge block that is not reachable via control flow. + ReachDeadMerge +}; + +// Traverses the control-flow graph rooted at root in an order suited for +// readable code generation. Invokes callback at every node in the traversal +// order. The callback arguments are: +// - the block, +// - the reason we reached the block, +// - if the reason was that block is an unreachable continue or unreachable merge block +// then the last parameter is the corresponding header block. +void inReadableOrder(Block* root, std::function callback); + +// +// SPIR-V IR Function. +// + +class Function { +public: + Function(Id id, Id resultType, Id functionType, Id firstParam, Module& parent); + virtual ~Function() + { + for (int i = 0; i < (int)parameterInstructions.size(); ++i) + delete parameterInstructions[i]; + + for (int i = 0; i < (int)blocks.size(); ++i) + delete blocks[i]; + } + Id getId() const { return functionInstruction.getResultId(); } + Id getParamId(int p) const { return parameterInstructions[p]->getResultId(); } + Id getParamType(int p) const { return parameterInstructions[p]->getTypeId(); } + + void addBlock(Block* block) { blocks.push_back(block); } + void removeBlock(Block* block) + { + auto found = find(blocks.begin(), blocks.end(), block); + assert(found != blocks.end()); + blocks.erase(found); + delete block; + } + + Module& getParent() const { return parent; } + Block* getEntryBlock() const { return blocks.front(); } + Block* getLastBlock() const { return blocks.back(); } + const std::vector& getBlocks() const { return blocks; } + void addLocalVariable(std::unique_ptr inst); + Id getReturnType() const { return functionInstruction.getTypeId(); } + + void setImplicitThis() { implicitThis = true; } + bool hasImplicitThis() const { return implicitThis; } + + void dump(std::vector& out) const + { + // OpFunction + functionInstruction.dump(out); + + // OpFunctionParameter + for (int p = 0; p < (int)parameterInstructions.size(); ++p) + parameterInstructions[p]->dump(out); + + // Blocks + inReadableOrder(blocks[0], [&out](const Block* b, ReachReason, Block*) { b->dump(out); }); + Instruction end(0, 0, OpFunctionEnd); + end.dump(out); + } + +protected: + Function(const Function&); + Function& operator=(Function&); + + Module& parent; + Instruction functionInstruction; + std::vector parameterInstructions; + std::vector blocks; + bool implicitThis; // true if this is a member function expecting to be passed a 'this' as the first argument +}; + +// +// SPIR-V IR Module. +// + +class Module { +public: + Module() {} + virtual ~Module() + { + // TODO delete things + } + + void addFunction(Function *fun) { functions.push_back(fun); } + + void mapInstruction(Instruction *instruction) + { + spv::Id resultId = instruction->getResultId(); + // map the instruction's result id + if (resultId >= idToInstruction.size()) + idToInstruction.resize(resultId + 16); + idToInstruction[resultId] = instruction; + } + + Instruction* getInstruction(Id id) const { return idToInstruction[id]; } + const std::vector& getFunctions() const { return functions; } + spv::Id getTypeId(Id resultId) const { + return idToInstruction[resultId] == nullptr ? NoType : idToInstruction[resultId]->getTypeId(); + } + StorageClass getStorageClass(Id typeId) const + { + assert(idToInstruction[typeId]->getOpCode() == spv::OpTypePointer); + return (StorageClass)idToInstruction[typeId]->getImmediateOperand(0); + } + + void dump(std::vector& out) const + { + for (int f = 0; f < (int)functions.size(); ++f) + functions[f]->dump(out); + } + +protected: + Module(const Module&); + std::vector functions; + + // map from result id to instruction having that result id + std::vector idToInstruction; + + // map from a result id to its type id +}; + +// +// Implementation (it's here due to circular type definitions). +// + +// Add both +// - the OpFunction instruction +// - all the OpFunctionParameter instructions +__inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, Module& parent) + : parent(parent), functionInstruction(id, resultType, OpFunction), implicitThis(false) +{ + // OpFunction + functionInstruction.addImmediateOperand(FunctionControlMaskNone); + functionInstruction.addIdOperand(functionType); + parent.mapInstruction(&functionInstruction); + parent.addFunction(this); + + // OpFunctionParameter + Instruction* typeInst = parent.getInstruction(functionType); + int numParams = typeInst->getNumOperands() - 1; + for (int p = 0; p < numParams; ++p) { + Instruction* param = new Instruction(firstParamId + p, typeInst->getIdOperand(p + 1), OpFunctionParameter); + parent.mapInstruction(param); + parameterInstructions.push_back(param); + } +} + +__inline void Function::addLocalVariable(std::unique_ptr inst) +{ + Instruction* raw_instruction = inst.get(); + blocks[0]->addLocalVariable(std::move(inst)); + parent.mapInstruction(raw_instruction); +} + +__inline Block::Block(Id id, Function& parent) : parent(parent), unreachable(false) +{ + instructions.push_back(std::unique_ptr(new Instruction(id, NoType, OpLabel))); + instructions.back()->setBlock(this); + parent.getParent().mapInstruction(instructions.back().get()); +} + +__inline void Block::addInstruction(std::unique_ptr inst) +{ + Instruction* raw_instruction = inst.get(); + instructions.push_back(std::move(inst)); + raw_instruction->setBlock(this); + if (raw_instruction->getResultId()) + parent.getParent().mapInstruction(raw_instruction); +} + +} // end spv namespace + +#endif // spvIR_H diff --git a/android/arm64-v8a/include/glslang/glslang/Include/BaseTypes.h b/android/arm64-v8a/include/glslang/glslang/Include/BaseTypes.h new file mode 100644 index 00000000..816b1794 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/Include/BaseTypes.h @@ -0,0 +1,565 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 LunarG, Inc. +// Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _BASICTYPES_INCLUDED_ +#define _BASICTYPES_INCLUDED_ + +namespace glslang { + +// +// Basic type. Arrays, vectors, sampler details, etc., are orthogonal to this. +// +enum TBasicType { + EbtVoid, + EbtFloat, + EbtDouble, + EbtFloat16, + EbtInt8, + EbtUint8, + EbtInt16, + EbtUint16, + EbtInt, + EbtUint, + EbtInt64, + EbtUint64, + EbtBool, + EbtAtomicUint, + EbtSampler, + EbtStruct, + EbtBlock, + EbtAccStruct, + EbtReference, + EbtRayQuery, + + // HLSL types that live only temporarily. + EbtString, + + EbtNumTypes +}; + +// +// Storage qualifiers. Should align with different kinds of storage or +// resource or GLSL storage qualifier. Expansion is deprecated. +// +// N.B.: You probably DON'T want to add anything here, but rather just add it +// to the built-in variables. See the comment above TBuiltInVariable. +// +// A new built-in variable will normally be an existing qualifier, like 'in', 'out', etc. +// DO NOT follow the design pattern of, say EvqInstanceId, etc. +// +enum TStorageQualifier { + EvqTemporary, // For temporaries (within a function), read/write + EvqGlobal, // For globals read/write + EvqConst, // User-defined constant values, will be semantically constant and constant folded + EvqVaryingIn, // pipeline input, read only, also supercategory for all built-ins not included in this enum (see TBuiltInVariable) + EvqVaryingOut, // pipeline output, read/write, also supercategory for all built-ins not included in this enum (see TBuiltInVariable) + EvqUniform, // read only, shared with app + EvqBuffer, // read/write, shared with app + EvqShared, // compute shader's read/write 'shared' qualifier + + EvqPayload, + EvqPayloadIn, + EvqHitAttr, + EvqCallableData, + EvqCallableDataIn, + + // parameters + EvqIn, // also, for 'in' in the grammar before we know if it's a pipeline input or an 'in' parameter + EvqOut, // also, for 'out' in the grammar before we know if it's a pipeline output or an 'out' parameter + EvqInOut, + EvqConstReadOnly, // input; also other read-only types having neither a constant value nor constant-value semantics + + // built-ins read by vertex shader + EvqVertexId, + EvqInstanceId, + + // built-ins written by vertex shader + EvqPosition, + EvqPointSize, + EvqClipVertex, + + // built-ins read by fragment shader + EvqFace, + EvqFragCoord, + EvqPointCoord, + + // built-ins written by fragment shader + EvqFragColor, + EvqFragDepth, + + // end of list + EvqLast +}; + +// +// Subcategories of the TStorageQualifier, simply to give a direct mapping +// between built-in variable names and an numerical value (the enum). +// +// For backward compatibility, there is some redundancy between the +// TStorageQualifier and these. Existing members should both be maintained accurately. +// However, any new built-in variable (and any existing non-redundant one) +// must follow the pattern that the specific built-in is here, and only its +// general qualifier is in TStorageQualifier. +// +// Something like gl_Position, which is sometimes 'in' and sometimes 'out' +// shows up as two different built-in variables in a single stage, but +// only has a single enum in TBuiltInVariable, so both the +// TStorageQualifier and the TBuitinVariable are needed to distinguish +// between them. +// +enum TBuiltInVariable { + EbvNone, + EbvNumWorkGroups, + EbvWorkGroupSize, + EbvWorkGroupId, + EbvLocalInvocationId, + EbvGlobalInvocationId, + EbvLocalInvocationIndex, + EbvNumSubgroups, + EbvSubgroupID, + EbvSubGroupSize, + EbvSubGroupInvocation, + EbvSubGroupEqMask, + EbvSubGroupGeMask, + EbvSubGroupGtMask, + EbvSubGroupLeMask, + EbvSubGroupLtMask, + EbvSubgroupSize2, + EbvSubgroupInvocation2, + EbvSubgroupEqMask2, + EbvSubgroupGeMask2, + EbvSubgroupGtMask2, + EbvSubgroupLeMask2, + EbvSubgroupLtMask2, + EbvVertexId, + EbvInstanceId, + EbvVertexIndex, + EbvInstanceIndex, + EbvBaseVertex, + EbvBaseInstance, + EbvDrawId, + EbvPosition, + EbvPointSize, + EbvClipVertex, + EbvClipDistance, + EbvCullDistance, + EbvNormal, + EbvVertex, + EbvMultiTexCoord0, + EbvMultiTexCoord1, + EbvMultiTexCoord2, + EbvMultiTexCoord3, + EbvMultiTexCoord4, + EbvMultiTexCoord5, + EbvMultiTexCoord6, + EbvMultiTexCoord7, + EbvFrontColor, + EbvBackColor, + EbvFrontSecondaryColor, + EbvBackSecondaryColor, + EbvTexCoord, + EbvFogFragCoord, + EbvInvocationId, + EbvPrimitiveId, + EbvLayer, + EbvViewportIndex, + EbvPatchVertices, + EbvTessLevelOuter, + EbvTessLevelInner, + EbvBoundingBox, + EbvTessCoord, + EbvColor, + EbvSecondaryColor, + EbvFace, + EbvFragCoord, + EbvPointCoord, + EbvFragColor, + EbvFragData, + EbvFragDepth, + EbvFragStencilRef, + EbvSampleId, + EbvSamplePosition, + EbvSampleMask, + EbvHelperInvocation, + + EbvBaryCoordNoPersp, + EbvBaryCoordNoPerspCentroid, + EbvBaryCoordNoPerspSample, + EbvBaryCoordSmooth, + EbvBaryCoordSmoothCentroid, + EbvBaryCoordSmoothSample, + EbvBaryCoordPullModel, + + EbvViewIndex, + EbvDeviceIndex, + + EbvFragSizeEXT, + EbvFragInvocationCountEXT, + + EbvViewportMaskNV, + EbvSecondaryPositionNV, + EbvSecondaryViewportMaskNV, + EbvPositionPerViewNV, + EbvViewportMaskPerViewNV, + EbvFragFullyCoveredNV, + EbvFragmentSizeNV, + EbvInvocationsPerPixelNV, + // ray tracing + EbvLaunchId, + EbvLaunchSize, + EbvInstanceCustomIndex, + EbvGeometryIndex, + EbvWorldRayOrigin, + EbvWorldRayDirection, + EbvObjectRayOrigin, + EbvObjectRayDirection, + EbvRayTmin, + EbvRayTmax, + EbvHitT, + EbvHitKind, + EbvObjectToWorld, + EbvObjectToWorld3x4, + EbvWorldToObject, + EbvWorldToObject3x4, + EbvIncomingRayFlags, + // barycentrics + EbvBaryCoordNV, + EbvBaryCoordNoPerspNV, + // mesh shaders + EbvTaskCountNV, + EbvPrimitiveCountNV, + EbvPrimitiveIndicesNV, + EbvClipDistancePerViewNV, + EbvCullDistancePerViewNV, + EbvLayerPerViewNV, + EbvMeshViewCountNV, + EbvMeshViewIndicesNV, + + // sm builtins + EbvWarpsPerSM, + EbvSMCount, + EbvWarpID, + EbvSMID, + + // HLSL built-ins that live only temporarily, until they get remapped + // to one of the above. + EbvFragDepthGreater, + EbvFragDepthLesser, + EbvGsOutputStream, + EbvOutputPatch, + EbvInputPatch, + + // structbuffer types + EbvAppendConsume, // no need to differentiate append and consume + EbvRWStructuredBuffer, + EbvStructuredBuffer, + EbvByteAddressBuffer, + EbvRWByteAddressBuffer, + + EbvLast +}; + +// In this enum, order matters; users can assume higher precision is a bigger value +// and EpqNone is 0. +enum TPrecisionQualifier { + EpqNone = 0, + EpqLow, + EpqMedium, + EpqHigh +}; + +#ifdef GLSLANG_WEB +__inline const char* GetStorageQualifierString(TStorageQualifier q) { return ""; } +__inline const char* GetPrecisionQualifierString(TPrecisionQualifier p) { return ""; } +#else +// These will show up in error messages +__inline const char* GetStorageQualifierString(TStorageQualifier q) +{ + switch (q) { + case EvqTemporary: return "temp"; break; + case EvqGlobal: return "global"; break; + case EvqConst: return "const"; break; + case EvqConstReadOnly: return "const (read only)"; break; + case EvqVaryingIn: return "in"; break; + case EvqVaryingOut: return "out"; break; + case EvqUniform: return "uniform"; break; + case EvqBuffer: return "buffer"; break; + case EvqShared: return "shared"; break; + case EvqIn: return "in"; break; + case EvqOut: return "out"; break; + case EvqInOut: return "inout"; break; + case EvqVertexId: return "gl_VertexId"; break; + case EvqInstanceId: return "gl_InstanceId"; break; + case EvqPosition: return "gl_Position"; break; + case EvqPointSize: return "gl_PointSize"; break; + case EvqClipVertex: return "gl_ClipVertex"; break; + case EvqFace: return "gl_FrontFacing"; break; + case EvqFragCoord: return "gl_FragCoord"; break; + case EvqPointCoord: return "gl_PointCoord"; break; + case EvqFragColor: return "fragColor"; break; + case EvqFragDepth: return "gl_FragDepth"; break; + case EvqPayload: return "rayPayloadNV"; break; + case EvqPayloadIn: return "rayPayloadInNV"; break; + case EvqHitAttr: return "hitAttributeNV"; break; + case EvqCallableData: return "callableDataNV"; break; + case EvqCallableDataIn: return "callableDataInNV"; break; + default: return "unknown qualifier"; + } +} + +__inline const char* GetBuiltInVariableString(TBuiltInVariable v) +{ + switch (v) { + case EbvNone: return ""; + case EbvNumWorkGroups: return "NumWorkGroups"; + case EbvWorkGroupSize: return "WorkGroupSize"; + case EbvWorkGroupId: return "WorkGroupID"; + case EbvLocalInvocationId: return "LocalInvocationID"; + case EbvGlobalInvocationId: return "GlobalInvocationID"; + case EbvLocalInvocationIndex: return "LocalInvocationIndex"; + case EbvNumSubgroups: return "NumSubgroups"; + case EbvSubgroupID: return "SubgroupID"; + case EbvSubGroupSize: return "SubGroupSize"; + case EbvSubGroupInvocation: return "SubGroupInvocation"; + case EbvSubGroupEqMask: return "SubGroupEqMask"; + case EbvSubGroupGeMask: return "SubGroupGeMask"; + case EbvSubGroupGtMask: return "SubGroupGtMask"; + case EbvSubGroupLeMask: return "SubGroupLeMask"; + case EbvSubGroupLtMask: return "SubGroupLtMask"; + case EbvSubgroupSize2: return "SubgroupSize"; + case EbvSubgroupInvocation2: return "SubgroupInvocationID"; + case EbvSubgroupEqMask2: return "SubgroupEqMask"; + case EbvSubgroupGeMask2: return "SubgroupGeMask"; + case EbvSubgroupGtMask2: return "SubgroupGtMask"; + case EbvSubgroupLeMask2: return "SubgroupLeMask"; + case EbvSubgroupLtMask2: return "SubgroupLtMask"; + case EbvVertexId: return "VertexId"; + case EbvInstanceId: return "InstanceId"; + case EbvVertexIndex: return "VertexIndex"; + case EbvInstanceIndex: return "InstanceIndex"; + case EbvBaseVertex: return "BaseVertex"; + case EbvBaseInstance: return "BaseInstance"; + case EbvDrawId: return "DrawId"; + case EbvPosition: return "Position"; + case EbvPointSize: return "PointSize"; + case EbvClipVertex: return "ClipVertex"; + case EbvClipDistance: return "ClipDistance"; + case EbvCullDistance: return "CullDistance"; + case EbvNormal: return "Normal"; + case EbvVertex: return "Vertex"; + case EbvMultiTexCoord0: return "MultiTexCoord0"; + case EbvMultiTexCoord1: return "MultiTexCoord1"; + case EbvMultiTexCoord2: return "MultiTexCoord2"; + case EbvMultiTexCoord3: return "MultiTexCoord3"; + case EbvMultiTexCoord4: return "MultiTexCoord4"; + case EbvMultiTexCoord5: return "MultiTexCoord5"; + case EbvMultiTexCoord6: return "MultiTexCoord6"; + case EbvMultiTexCoord7: return "MultiTexCoord7"; + case EbvFrontColor: return "FrontColor"; + case EbvBackColor: return "BackColor"; + case EbvFrontSecondaryColor: return "FrontSecondaryColor"; + case EbvBackSecondaryColor: return "BackSecondaryColor"; + case EbvTexCoord: return "TexCoord"; + case EbvFogFragCoord: return "FogFragCoord"; + case EbvInvocationId: return "InvocationID"; + case EbvPrimitiveId: return "PrimitiveID"; + case EbvLayer: return "Layer"; + case EbvViewportIndex: return "ViewportIndex"; + case EbvPatchVertices: return "PatchVertices"; + case EbvTessLevelOuter: return "TessLevelOuter"; + case EbvTessLevelInner: return "TessLevelInner"; + case EbvBoundingBox: return "BoundingBox"; + case EbvTessCoord: return "TessCoord"; + case EbvColor: return "Color"; + case EbvSecondaryColor: return "SecondaryColor"; + case EbvFace: return "Face"; + case EbvFragCoord: return "FragCoord"; + case EbvPointCoord: return "PointCoord"; + case EbvFragColor: return "FragColor"; + case EbvFragData: return "FragData"; + case EbvFragDepth: return "FragDepth"; + case EbvFragStencilRef: return "FragStencilRef"; + case EbvSampleId: return "SampleId"; + case EbvSamplePosition: return "SamplePosition"; + case EbvSampleMask: return "SampleMaskIn"; + case EbvHelperInvocation: return "HelperInvocation"; + + case EbvBaryCoordNoPersp: return "BaryCoordNoPersp"; + case EbvBaryCoordNoPerspCentroid: return "BaryCoordNoPerspCentroid"; + case EbvBaryCoordNoPerspSample: return "BaryCoordNoPerspSample"; + case EbvBaryCoordSmooth: return "BaryCoordSmooth"; + case EbvBaryCoordSmoothCentroid: return "BaryCoordSmoothCentroid"; + case EbvBaryCoordSmoothSample: return "BaryCoordSmoothSample"; + case EbvBaryCoordPullModel: return "BaryCoordPullModel"; + + case EbvViewIndex: return "ViewIndex"; + case EbvDeviceIndex: return "DeviceIndex"; + + case EbvFragSizeEXT: return "FragSizeEXT"; + case EbvFragInvocationCountEXT: return "FragInvocationCountEXT"; + + case EbvViewportMaskNV: return "ViewportMaskNV"; + case EbvSecondaryPositionNV: return "SecondaryPositionNV"; + case EbvSecondaryViewportMaskNV: return "SecondaryViewportMaskNV"; + case EbvPositionPerViewNV: return "PositionPerViewNV"; + case EbvViewportMaskPerViewNV: return "ViewportMaskPerViewNV"; + case EbvFragFullyCoveredNV: return "FragFullyCoveredNV"; + case EbvFragmentSizeNV: return "FragmentSizeNV"; + case EbvInvocationsPerPixelNV: return "InvocationsPerPixelNV"; + case EbvLaunchId: return "LaunchIdNV"; + case EbvLaunchSize: return "LaunchSizeNV"; + case EbvInstanceCustomIndex: return "InstanceCustomIndexNV"; + case EbvGeometryIndex: return "GeometryIndexEXT"; + case EbvWorldRayOrigin: return "WorldRayOriginNV"; + case EbvWorldRayDirection: return "WorldRayDirectionNV"; + case EbvObjectRayOrigin: return "ObjectRayOriginNV"; + case EbvObjectRayDirection: return "ObjectRayDirectionNV"; + case EbvRayTmin: return "ObjectRayTminNV"; + case EbvRayTmax: return "ObjectRayTmaxNV"; + case EbvHitT: return "HitTNV"; + case EbvHitKind: return "HitKindNV"; + case EbvIncomingRayFlags: return "IncomingRayFlagsNV"; + case EbvObjectToWorld: return "ObjectToWorldNV"; + case EbvWorldToObject: return "WorldToObjectNV"; + + case EbvBaryCoordNV: return "BaryCoordNV"; + case EbvBaryCoordNoPerspNV: return "BaryCoordNoPerspNV"; + + case EbvTaskCountNV: return "TaskCountNV"; + case EbvPrimitiveCountNV: return "PrimitiveCountNV"; + case EbvPrimitiveIndicesNV: return "PrimitiveIndicesNV"; + case EbvClipDistancePerViewNV: return "ClipDistancePerViewNV"; + case EbvCullDistancePerViewNV: return "CullDistancePerViewNV"; + case EbvLayerPerViewNV: return "LayerPerViewNV"; + case EbvMeshViewCountNV: return "MeshViewCountNV"; + case EbvMeshViewIndicesNV: return "MeshViewIndicesNV"; + + case EbvWarpsPerSM: return "WarpsPerSMNV"; + case EbvSMCount: return "SMCountNV"; + case EbvWarpID: return "WarpIDNV"; + case EbvSMID: return "SMIDNV"; + + default: return "unknown built-in variable"; + } +} + +__inline const char* GetPrecisionQualifierString(TPrecisionQualifier p) +{ + switch (p) { + case EpqNone: return ""; break; + case EpqLow: return "lowp"; break; + case EpqMedium: return "mediump"; break; + case EpqHigh: return "highp"; break; + default: return "unknown precision qualifier"; + } +} +#endif + +__inline bool isTypeSignedInt(TBasicType type) +{ + switch (type) { + case EbtInt8: + case EbtInt16: + case EbtInt: + case EbtInt64: + return true; + default: + return false; + } +} + +__inline bool isTypeUnsignedInt(TBasicType type) +{ + switch (type) { + case EbtUint8: + case EbtUint16: + case EbtUint: + case EbtUint64: + return true; + default: + return false; + } +} + +__inline bool isTypeInt(TBasicType type) +{ + return isTypeSignedInt(type) || isTypeUnsignedInt(type); +} + +__inline bool isTypeFloat(TBasicType type) +{ + switch (type) { + case EbtFloat: + case EbtDouble: + case EbtFloat16: + return true; + default: + return false; + } +} + +__inline int getTypeRank(TBasicType type) +{ + int res = -1; + switch(type) { + case EbtInt8: + case EbtUint8: + res = 0; + break; + case EbtInt16: + case EbtUint16: + res = 1; + break; + case EbtInt: + case EbtUint: + res = 2; + break; + case EbtInt64: + case EbtUint64: + res = 3; + break; + default: + assert(false); + break; + } + return res; +} + +} // end namespace glslang + +#endif // _BASICTYPES_INCLUDED_ diff --git a/android/arm64-v8a/include/glslang/glslang/Include/Common.h b/android/arm64-v8a/include/glslang/glslang/Include/Common.h new file mode 100644 index 00000000..733a790c --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/Include/Common.h @@ -0,0 +1,292 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _COMMON_INCLUDED_ +#define _COMMON_INCLUDED_ + + +#if defined(__ANDROID__) || (defined(_MSC_VER) && _MSC_VER < 1700) +#include +namespace std { +template +std::string to_string(const T& val) { + std::ostringstream os; + os << val; + return os.str(); +} +} +#endif + +#if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/) || defined MINGW_HAS_SECURE_API + #include + #ifndef snprintf + #define snprintf sprintf_s + #endif + #define safe_vsprintf(buf,max,format,args) vsnprintf_s((buf), (max), (max), (format), (args)) +#elif defined (solaris) + #define safe_vsprintf(buf,max,format,args) vsnprintf((buf), (max), (format), (args)) + #include + #define UINT_PTR uintptr_t +#else + #define safe_vsprintf(buf,max,format,args) vsnprintf((buf), (max), (format), (args)) + #include + #define UINT_PTR uintptr_t +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1800 + #include + inline long long int strtoll (const char* str, char** endptr, int base) + { + return _strtoi64(str, endptr, base); + } + inline unsigned long long int strtoull (const char* str, char** endptr, int base) + { + return _strtoui64(str, endptr, base); + } + inline long long int atoll (const char* str) + { + return strtoll(str, NULL, 10); + } +#endif + +#if defined(_MSC_VER) +#define strdup _strdup +#endif + +/* windows only pragma */ +#ifdef _MSC_VER + #pragma warning(disable : 4786) // Don't warn about too long identifiers + #pragma warning(disable : 4514) // unused inline method + #pragma warning(disable : 4201) // nameless union +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "PoolAlloc.h" + +// +// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme. +// +#define POOL_ALLOCATOR_NEW_DELETE(A) \ + void* operator new(size_t s) { return (A).allocate(s); } \ + void* operator new(size_t, void *_Where) { return (_Where); } \ + void operator delete(void*) { } \ + void operator delete(void *, void *) { } \ + void* operator new[](size_t s) { return (A).allocate(s); } \ + void* operator new[](size_t, void *_Where) { return (_Where); } \ + void operator delete[](void*) { } \ + void operator delete[](void *, void *) { } + +namespace glslang { + + // + // Pool version of string. + // + typedef pool_allocator TStringAllocator; + typedef std::basic_string , TStringAllocator> TString; + +} // end namespace glslang + +// Repackage the std::hash for use by unordered map/set with a TString key. +namespace std { + + template<> struct hash { + std::size_t operator()(const glslang::TString& s) const + { + const unsigned _FNV_offset_basis = 2166136261U; + const unsigned _FNV_prime = 16777619U; + unsigned _Val = _FNV_offset_basis; + size_t _Count = s.size(); + const char* _First = s.c_str(); + for (size_t _Next = 0; _Next < _Count; ++_Next) + { + _Val ^= (unsigned)_First[_Next]; + _Val *= _FNV_prime; + } + + return _Val; + } + }; +} + +namespace glslang { + +inline TString* NewPoolTString(const char* s) +{ + void* memory = GetThreadPoolAllocator().allocate(sizeof(TString)); + return new(memory) TString(s); +} + +template inline T* NewPoolObject(T*) +{ + return new(GetThreadPoolAllocator().allocate(sizeof(T))) T; +} + +template inline T* NewPoolObject(T, int instances) +{ + return new(GetThreadPoolAllocator().allocate(instances * sizeof(T))) T[instances]; +} + +// +// Pool allocator versions of vectors, lists, and maps +// +template class TVector : public std::vector > { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + typedef typename std::vector >::size_type size_type; + TVector() : std::vector >() {} + TVector(const pool_allocator& a) : std::vector >(a) {} + TVector(size_type i) : std::vector >(i) {} + TVector(size_type i, const T& val) : std::vector >(i, val) {} +}; + +template class TList : public std::list > { +}; + +template > +class TMap : public std::map > > { +}; + +template , class PRED = std::equal_to > +class TUnorderedMap : public std::unordered_map > > { +}; + +// +// Persistent string memory. Should only be used for strings that survive +// across compiles/links. +// +typedef std::basic_string TPersistString; + +// +// templatized min and max functions. +// +template T Min(const T a, const T b) { return a < b ? a : b; } +template T Max(const T a, const T b) { return a > b ? a : b; } + +// +// Create a TString object from an integer. +// +#if defined _MSC_VER || defined MINGW_HAS_SECURE_API +inline const TString String(const int i, const int base = 10) +{ + char text[16]; // 32 bit ints are at most 10 digits in base 10 + _itoa_s(i, text, sizeof(text), base); + return text; +} +#else +inline const TString String(const int i, const int /*base*/ = 10) +{ + char text[16]; // 32 bit ints are at most 10 digits in base 10 + + // we assume base 10 for all cases + snprintf(text, sizeof(text), "%d", i); + + return text; +} +#endif + +struct TSourceLoc { + void init() + { + name = nullptr; string = 0; line = 0; column = 0; + } + void init(int stringNum) { init(); string = stringNum; } + // Returns the name if it exists. Otherwise, returns the string number. + std::string getStringNameOrNum(bool quoteStringName = true) const + { + if (name != nullptr) { + TString qstr = quoteStringName ? ("\"" + *name + "\"") : *name; + std::string ret_str(qstr.c_str()); + return ret_str; + } + return std::to_string((long long)string); + } + const char* getFilename() const + { + if (name == nullptr) + return nullptr; + return name->c_str(); + } + const char* getFilenameStr() const { return name == nullptr ? "" : name->c_str(); } + TString* name; // descriptive name for this string, when a textual name is available, otherwise nullptr + int string; + int line; + int column; +}; + +class TPragmaTable : public TMap { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) +}; + +const int MaxTokenLength = 1024; + +template bool IsPow2(T powerOf2) +{ + if (powerOf2 <= 0) + return false; + + return (powerOf2 & (powerOf2 - 1)) == 0; +} + +// Round number up to a multiple of the given powerOf2, which is not +// a power, just a number that must be a power of 2. +template void RoundToPow2(T& number, int powerOf2) +{ + assert(IsPow2(powerOf2)); + number = (number + powerOf2 - 1) & ~(powerOf2 - 1); +} + +template bool IsMultipleOfPow2(T number, int powerOf2) +{ + assert(IsPow2(powerOf2)); + return ! (number & (powerOf2 - 1)); +} + +} // end namespace glslang + +#endif // _COMMON_INCLUDED_ diff --git a/android/arm64-v8a/include/glslang/glslang/Include/ConstantUnion.h b/android/arm64-v8a/include/glslang/glslang/Include/ConstantUnion.h new file mode 100644 index 00000000..c4ffb857 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/Include/ConstantUnion.h @@ -0,0 +1,974 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013 LunarG, Inc. +// Copyright (C) 2017 ARM Limited. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _CONSTANT_UNION_INCLUDED_ +#define _CONSTANT_UNION_INCLUDED_ + +#include "../Include/Common.h" +#include "../Include/BaseTypes.h" + +namespace glslang { + +class TConstUnion { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + TConstUnion() : iConst(0), type(EbtInt) { } + + void setI8Const(signed char i) + { + i8Const = i; + type = EbtInt8; + } + + void setU8Const(unsigned char u) + { + u8Const = u; + type = EbtUint8; + } + + void setI16Const(signed short i) + { + i16Const = i; + type = EbtInt16; + } + + void setU16Const(unsigned short u) + { + u16Const = u; + type = EbtUint16; + } + + void setIConst(int i) + { + iConst = i; + type = EbtInt; + } + + void setUConst(unsigned int u) + { + uConst = u; + type = EbtUint; + } + + void setI64Const(long long i64) + { + i64Const = i64; + type = EbtInt64; + } + + void setU64Const(unsigned long long u64) + { + u64Const = u64; + type = EbtUint64; + } + + void setDConst(double d) + { + dConst = d; + type = EbtDouble; + } + + void setBConst(bool b) + { + bConst = b; + type = EbtBool; + } + + void setSConst(const TString* s) + { + sConst = s; + type = EbtString; + } + + signed char getI8Const() const { return i8Const; } + unsigned char getU8Const() const { return u8Const; } + signed short getI16Const() const { return i16Const; } + unsigned short getU16Const() const { return u16Const; } + int getIConst() const { return iConst; } + unsigned int getUConst() const { return uConst; } + long long getI64Const() const { return i64Const; } + unsigned long long getU64Const() const { return u64Const; } + double getDConst() const { return dConst; } + bool getBConst() const { return bConst; } + const TString* getSConst() const { return sConst; } + + bool operator==(const signed char i) const + { + if (i == i8Const) + return true; + + return false; + } + + bool operator==(const unsigned char u) const + { + if (u == u8Const) + return true; + + return false; + } + + bool operator==(const signed short i) const + { + if (i == i16Const) + return true; + + return false; + } + + bool operator==(const unsigned short u) const + { + if (u == u16Const) + return true; + + return false; + } + + bool operator==(const int i) const + { + if (i == iConst) + return true; + + return false; + } + + bool operator==(const unsigned int u) const + { + if (u == uConst) + return true; + + return false; + } + + bool operator==(const long long i64) const + { + if (i64 == i64Const) + return true; + + return false; + } + + bool operator==(const unsigned long long u64) const + { + if (u64 == u64Const) + return true; + + return false; + } + + bool operator==(const double d) const + { + if (d == dConst) + return true; + + return false; + } + + bool operator==(const bool b) const + { + if (b == bConst) + return true; + + return false; + } + + bool operator==(const TConstUnion& constant) const + { + if (constant.type != type) + return false; + + switch (type) { + case EbtInt: + if (constant.iConst == iConst) + return true; + + break; + case EbtUint: + if (constant.uConst == uConst) + return true; + + break; + case EbtBool: + if (constant.bConst == bConst) + return true; + + break; + case EbtDouble: + if (constant.dConst == dConst) + return true; + + break; + +#ifndef GLSLANG_WEB + case EbtInt16: + if (constant.i16Const == i16Const) + return true; + + break; + case EbtUint16: + if (constant.u16Const == u16Const) + return true; + + break; + case EbtInt8: + if (constant.i8Const == i8Const) + return true; + + break; + case EbtUint8: + if (constant.u8Const == u8Const) + return true; + + break; + case EbtInt64: + if (constant.i64Const == i64Const) + return true; + + break; + case EbtUint64: + if (constant.u64Const == u64Const) + return true; + + break; +#endif + default: + assert(false && "Default missing"); + } + + return false; + } + + bool operator!=(const signed char i) const + { + return !operator==(i); + } + + bool operator!=(const unsigned char u) const + { + return !operator==(u); + } + + bool operator!=(const signed short i) const + { + return !operator==(i); + } + + bool operator!=(const unsigned short u) const + { + return !operator==(u); + } + + bool operator!=(const int i) const + { + return !operator==(i); + } + + bool operator!=(const unsigned int u) const + { + return !operator==(u); + } + + bool operator!=(const long long i) const + { + return !operator==(i); + } + + bool operator!=(const unsigned long long u) const + { + return !operator==(u); + } + + bool operator!=(const float f) const + { + return !operator==(f); + } + + bool operator!=(const bool b) const + { + return !operator==(b); + } + + bool operator!=(const TConstUnion& constant) const + { + return !operator==(constant); + } + + bool operator>(const TConstUnion& constant) const + { + assert(type == constant.type); + switch (type) { + case EbtInt: + if (iConst > constant.iConst) + return true; + + return false; + case EbtUint: + if (uConst > constant.uConst) + return true; + + return false; + case EbtDouble: + if (dConst > constant.dConst) + return true; + + return false; +#ifndef GLSLANG_WEB + case EbtInt8: + if (i8Const > constant.i8Const) + return true; + + return false; + case EbtUint8: + if (u8Const > constant.u8Const) + return true; + + return false; + case EbtInt16: + if (i16Const > constant.i16Const) + return true; + + return false; + case EbtUint16: + if (u16Const > constant.u16Const) + return true; + + return false; + case EbtInt64: + if (i64Const > constant.i64Const) + return true; + + return false; + case EbtUint64: + if (u64Const > constant.u64Const) + return true; + + return false; +#endif + default: + assert(false && "Default missing"); + return false; + } + } + + bool operator<(const TConstUnion& constant) const + { + assert(type == constant.type); + switch (type) { +#ifndef GLSLANG_WEB + case EbtInt8: + if (i8Const < constant.i8Const) + return true; + + return false; + case EbtUint8: + if (u8Const < constant.u8Const) + return true; + + return false; + case EbtInt16: + if (i16Const < constant.i16Const) + return true; + + return false; + case EbtUint16: + if (u16Const < constant.u16Const) + return true; + return false; + case EbtInt64: + if (i64Const < constant.i64Const) + return true; + + return false; + case EbtUint64: + if (u64Const < constant.u64Const) + return true; + + return false; +#endif + case EbtDouble: + if (dConst < constant.dConst) + return true; + + return false; + case EbtInt: + if (iConst < constant.iConst) + return true; + + return false; + case EbtUint: + if (uConst < constant.uConst) + return true; + + return false; + default: + assert(false && "Default missing"); + return false; + } + } + + TConstUnion operator+(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst + constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst + constant.uConst); break; + case EbtDouble: returnValue.setDConst(dConst + constant.dConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const + constant.i8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const + constant.i16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const + constant.i64Const); break; + case EbtUint8: returnValue.setU8Const(u8Const + constant.u8Const); break; + case EbtUint16: returnValue.setU16Const(u16Const + constant.u16Const); break; + case EbtUint64: returnValue.setU64Const(u64Const + constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator-(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst - constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst - constant.uConst); break; + case EbtDouble: returnValue.setDConst(dConst - constant.dConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const - constant.i8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const - constant.i16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const - constant.i64Const); break; + case EbtUint8: returnValue.setU8Const(u8Const - constant.u8Const); break; + case EbtUint16: returnValue.setU16Const(u16Const - constant.u16Const); break; + case EbtUint64: returnValue.setU64Const(u64Const - constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator*(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst * constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst * constant.uConst); break; + case EbtDouble: returnValue.setDConst(dConst * constant.dConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const * constant.i8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const * constant.i16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const * constant.i64Const); break; + case EbtUint8: returnValue.setU8Const(u8Const * constant.u8Const); break; + case EbtUint16: returnValue.setU16Const(u16Const * constant.u16Const); break; + case EbtUint64: returnValue.setU64Const(u64Const * constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator%(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst % constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst % constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const % constant.i8Const); break; + case EbtInt16: returnValue.setI8Const(i8Const % constant.i16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const % constant.i64Const); break; + case EbtUint8: returnValue.setU8Const(u8Const % constant.u8Const); break; + case EbtUint16: returnValue.setU16Const(u16Const % constant.u16Const); break; + case EbtUint64: returnValue.setU64Const(u64Const % constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator>>(const TConstUnion& constant) const + { + TConstUnion returnValue; + switch (type) { +#ifndef GLSLANG_WEB + case EbtInt8: + switch (constant.type) { + case EbtInt8: returnValue.setI8Const(i8Const >> constant.i8Const); break; + case EbtUint8: returnValue.setI8Const(i8Const >> constant.u8Const); break; + case EbtInt16: returnValue.setI8Const(i8Const >> constant.i16Const); break; + case EbtUint16: returnValue.setI8Const(i8Const >> constant.u16Const); break; + case EbtInt: returnValue.setI8Const(i8Const >> constant.iConst); break; + case EbtUint: returnValue.setI8Const(i8Const >> constant.uConst); break; + case EbtInt64: returnValue.setI8Const(i8Const >> constant.i64Const); break; + case EbtUint64: returnValue.setI8Const(i8Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint8: + switch (constant.type) { + case EbtInt8: returnValue.setU8Const(u8Const >> constant.i8Const); break; + case EbtUint8: returnValue.setU8Const(u8Const >> constant.u8Const); break; + case EbtInt16: returnValue.setU8Const(u8Const >> constant.i16Const); break; + case EbtUint16: returnValue.setU8Const(u8Const >> constant.u16Const); break; + case EbtInt: returnValue.setU8Const(u8Const >> constant.iConst); break; + case EbtUint: returnValue.setU8Const(u8Const >> constant.uConst); break; + case EbtInt64: returnValue.setU8Const(u8Const >> constant.i64Const); break; + case EbtUint64: returnValue.setU8Const(u8Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtInt16: + switch (constant.type) { + case EbtInt8: returnValue.setI16Const(i16Const >> constant.i8Const); break; + case EbtUint8: returnValue.setI16Const(i16Const >> constant.u8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const >> constant.i16Const); break; + case EbtUint16: returnValue.setI16Const(i16Const >> constant.u16Const); break; + case EbtInt: returnValue.setI16Const(i16Const >> constant.iConst); break; + case EbtUint: returnValue.setI16Const(i16Const >> constant.uConst); break; + case EbtInt64: returnValue.setI16Const(i16Const >> constant.i64Const); break; + case EbtUint64: returnValue.setI16Const(i16Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint16: + switch (constant.type) { + case EbtInt8: returnValue.setU16Const(u16Const >> constant.i8Const); break; + case EbtUint8: returnValue.setU16Const(u16Const >> constant.u8Const); break; + case EbtInt16: returnValue.setU16Const(u16Const >> constant.i16Const); break; + case EbtUint16: returnValue.setU16Const(u16Const >> constant.u16Const); break; + case EbtInt: returnValue.setU16Const(u16Const >> constant.iConst); break; + case EbtUint: returnValue.setU16Const(u16Const >> constant.uConst); break; + case EbtInt64: returnValue.setU16Const(u16Const >> constant.i64Const); break; + case EbtUint64: returnValue.setU16Const(u16Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; +#endif + case EbtInt: + switch (constant.type) { + case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break; + case EbtUint: returnValue.setIConst(iConst >> constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setIConst(iConst >> constant.i8Const); break; + case EbtUint8: returnValue.setIConst(iConst >> constant.u8Const); break; + case EbtInt16: returnValue.setIConst(iConst >> constant.i16Const); break; + case EbtUint16: returnValue.setIConst(iConst >> constant.u16Const); break; + case EbtInt64: returnValue.setIConst(iConst >> constant.i64Const); break; + case EbtUint64: returnValue.setIConst(iConst >> constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + break; + case EbtUint: + switch (constant.type) { + case EbtInt: returnValue.setUConst(uConst >> constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst >> constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setUConst(uConst >> constant.i8Const); break; + case EbtUint8: returnValue.setUConst(uConst >> constant.u8Const); break; + case EbtInt16: returnValue.setUConst(uConst >> constant.i16Const); break; + case EbtUint16: returnValue.setUConst(uConst >> constant.u16Const); break; + case EbtInt64: returnValue.setUConst(uConst >> constant.i64Const); break; + case EbtUint64: returnValue.setUConst(uConst >> constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + break; +#ifndef GLSLANG_WEB + case EbtInt64: + switch (constant.type) { + case EbtInt8: returnValue.setI64Const(i64Const >> constant.i8Const); break; + case EbtUint8: returnValue.setI64Const(i64Const >> constant.u8Const); break; + case EbtInt16: returnValue.setI64Const(i64Const >> constant.i16Const); break; + case EbtUint16: returnValue.setI64Const(i64Const >> constant.u16Const); break; + case EbtInt: returnValue.setI64Const(i64Const >> constant.iConst); break; + case EbtUint: returnValue.setI64Const(i64Const >> constant.uConst); break; + case EbtInt64: returnValue.setI64Const(i64Const >> constant.i64Const); break; + case EbtUint64: returnValue.setI64Const(i64Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint64: + switch (constant.type) { + case EbtInt8: returnValue.setU64Const(u64Const >> constant.i8Const); break; + case EbtUint8: returnValue.setU64Const(u64Const >> constant.u8Const); break; + case EbtInt16: returnValue.setU64Const(u64Const >> constant.i16Const); break; + case EbtUint16: returnValue.setU64Const(u64Const >> constant.u16Const); break; + case EbtInt: returnValue.setU64Const(u64Const >> constant.iConst); break; + case EbtUint: returnValue.setU64Const(u64Const >> constant.uConst); break; + case EbtInt64: returnValue.setU64Const(u64Const >> constant.i64Const); break; + case EbtUint64: returnValue.setU64Const(u64Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator<<(const TConstUnion& constant) const + { + TConstUnion returnValue; + switch (type) { +#ifndef GLSLANG_WEB + case EbtInt8: + switch (constant.type) { + case EbtInt8: returnValue.setI8Const(i8Const << constant.i8Const); break; + case EbtUint8: returnValue.setI8Const(i8Const << constant.u8Const); break; + case EbtInt16: returnValue.setI8Const(i8Const << constant.i16Const); break; + case EbtUint16: returnValue.setI8Const(i8Const << constant.u16Const); break; + case EbtInt: returnValue.setI8Const(i8Const << constant.iConst); break; + case EbtUint: returnValue.setI8Const(i8Const << constant.uConst); break; + case EbtInt64: returnValue.setI8Const(i8Const << constant.i64Const); break; + case EbtUint64: returnValue.setI8Const(i8Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint8: + switch (constant.type) { + case EbtInt8: returnValue.setU8Const(u8Const << constant.i8Const); break; + case EbtUint8: returnValue.setU8Const(u8Const << constant.u8Const); break; + case EbtInt16: returnValue.setU8Const(u8Const << constant.i16Const); break; + case EbtUint16: returnValue.setU8Const(u8Const << constant.u16Const); break; + case EbtInt: returnValue.setU8Const(u8Const << constant.iConst); break; + case EbtUint: returnValue.setU8Const(u8Const << constant.uConst); break; + case EbtInt64: returnValue.setU8Const(u8Const << constant.i64Const); break; + case EbtUint64: returnValue.setU8Const(u8Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtInt16: + switch (constant.type) { + case EbtInt8: returnValue.setI16Const(i16Const << constant.i8Const); break; + case EbtUint8: returnValue.setI16Const(i16Const << constant.u8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const << constant.i16Const); break; + case EbtUint16: returnValue.setI16Const(i16Const << constant.u16Const); break; + case EbtInt: returnValue.setI16Const(i16Const << constant.iConst); break; + case EbtUint: returnValue.setI16Const(i16Const << constant.uConst); break; + case EbtInt64: returnValue.setI16Const(i16Const << constant.i64Const); break; + case EbtUint64: returnValue.setI16Const(i16Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint16: + switch (constant.type) { + case EbtInt8: returnValue.setU16Const(u16Const << constant.i8Const); break; + case EbtUint8: returnValue.setU16Const(u16Const << constant.u8Const); break; + case EbtInt16: returnValue.setU16Const(u16Const << constant.i16Const); break; + case EbtUint16: returnValue.setU16Const(u16Const << constant.u16Const); break; + case EbtInt: returnValue.setU16Const(u16Const << constant.iConst); break; + case EbtUint: returnValue.setU16Const(u16Const << constant.uConst); break; + case EbtInt64: returnValue.setU16Const(u16Const << constant.i64Const); break; + case EbtUint64: returnValue.setU16Const(u16Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtInt64: + switch (constant.type) { + case EbtInt8: returnValue.setI64Const(i64Const << constant.i8Const); break; + case EbtUint8: returnValue.setI64Const(i64Const << constant.u8Const); break; + case EbtInt16: returnValue.setI64Const(i64Const << constant.i16Const); break; + case EbtUint16: returnValue.setI64Const(i64Const << constant.u16Const); break; + case EbtInt: returnValue.setI64Const(i64Const << constant.iConst); break; + case EbtUint: returnValue.setI64Const(i64Const << constant.uConst); break; + case EbtInt64: returnValue.setI64Const(i64Const << constant.i64Const); break; + case EbtUint64: returnValue.setI64Const(i64Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint64: + switch (constant.type) { + case EbtInt8: returnValue.setU64Const(u64Const << constant.i8Const); break; + case EbtUint8: returnValue.setU64Const(u64Const << constant.u8Const); break; + case EbtInt16: returnValue.setU64Const(u64Const << constant.i16Const); break; + case EbtUint16: returnValue.setU64Const(u64Const << constant.u16Const); break; + case EbtInt: returnValue.setU64Const(u64Const << constant.iConst); break; + case EbtUint: returnValue.setU64Const(u64Const << constant.uConst); break; + case EbtInt64: returnValue.setU64Const(u64Const << constant.i64Const); break; + case EbtUint64: returnValue.setU64Const(u64Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; +#endif + case EbtInt: + switch (constant.type) { + case EbtInt: returnValue.setIConst(iConst << constant.iConst); break; + case EbtUint: returnValue.setIConst(iConst << constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setIConst(iConst << constant.i8Const); break; + case EbtUint8: returnValue.setIConst(iConst << constant.u8Const); break; + case EbtInt16: returnValue.setIConst(iConst << constant.i16Const); break; + case EbtUint16: returnValue.setIConst(iConst << constant.u16Const); break; + case EbtInt64: returnValue.setIConst(iConst << constant.i64Const); break; + case EbtUint64: returnValue.setIConst(iConst << constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + break; + case EbtUint: + switch (constant.type) { + case EbtInt: returnValue.setUConst(uConst << constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst << constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setUConst(uConst << constant.i8Const); break; + case EbtUint8: returnValue.setUConst(uConst << constant.u8Const); break; + case EbtInt16: returnValue.setUConst(uConst << constant.i16Const); break; + case EbtUint16: returnValue.setUConst(uConst << constant.u16Const); break; + case EbtInt64: returnValue.setUConst(uConst << constant.i64Const); break; + case EbtUint64: returnValue.setUConst(uConst << constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator&(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst & constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst & constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const & constant.i8Const); break; + case EbtUint8: returnValue.setU8Const(u8Const & constant.u8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const & constant.i16Const); break; + case EbtUint16: returnValue.setU16Const(u16Const & constant.u16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const & constant.i64Const); break; + case EbtUint64: returnValue.setU64Const(u64Const & constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator|(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst | constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst | constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const | constant.i8Const); break; + case EbtUint8: returnValue.setU8Const(u8Const | constant.u8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const | constant.i16Const); break; + case EbtUint16: returnValue.setU16Const(u16Const | constant.u16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const | constant.i64Const); break; + case EbtUint64: returnValue.setU64Const(u64Const | constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator^(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst ^ constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst ^ constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const ^ constant.i8Const); break; + case EbtUint8: returnValue.setU8Const(u8Const ^ constant.u8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const ^ constant.i16Const); break; + case EbtUint16: returnValue.setU16Const(u16Const ^ constant.u16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const ^ constant.i64Const); break; + case EbtUint64: returnValue.setU64Const(u64Const ^ constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator~() const + { + TConstUnion returnValue; + switch (type) { + case EbtInt: returnValue.setIConst(~iConst); break; + case EbtUint: returnValue.setUConst(~uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(~i8Const); break; + case EbtUint8: returnValue.setU8Const(~u8Const); break; + case EbtInt16: returnValue.setI16Const(~i16Const); break; + case EbtUint16: returnValue.setU16Const(~u16Const); break; + case EbtInt64: returnValue.setI64Const(~i64Const); break; + case EbtUint64: returnValue.setU64Const(~u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator&&(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtBool: returnValue.setBConst(bConst && constant.bConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator||(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtBool: returnValue.setBConst(bConst || constant.bConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TBasicType getType() const { return type; } + +private: + union { + signed char i8Const; // used for i8vec, scalar int8s + unsigned char u8Const; // used for u8vec, scalar uint8s + signed short i16Const; // used for i16vec, scalar int16s + unsigned short u16Const; // used for u16vec, scalar uint16s + int iConst; // used for ivec, scalar ints + unsigned int uConst; // used for uvec, scalar uints + long long i64Const; // used for i64vec, scalar int64s + unsigned long long u64Const; // used for u64vec, scalar uint64s + bool bConst; // used for bvec, scalar bools + double dConst; // used for vec, dvec, mat, dmat, scalar floats and doubles + const TString* sConst; // string constant + }; + + TBasicType type; +}; + +// Encapsulate having a pointer to an array of TConstUnion, +// which only needs to be allocated if its size is going to be +// bigger than 0. +// +// One convenience is being able to use [] to go inside the array, instead +// of C++ assuming it as an array of pointers to vectors. +// +// General usage is that the size is known up front, and it is +// created once with the proper size. +// +class TConstUnionArray { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + TConstUnionArray() : unionArray(nullptr) { } + virtual ~TConstUnionArray() { } + + explicit TConstUnionArray(int size) + { + if (size == 0) + unionArray = nullptr; + else + unionArray = new TConstUnionVector(size); + } + TConstUnionArray(const TConstUnionArray& a) = default; + TConstUnionArray(const TConstUnionArray& a, int start, int size) + { + unionArray = new TConstUnionVector(size); + for (int i = 0; i < size; ++i) + (*unionArray)[i] = a[start + i]; + } + + // Use this constructor for a smear operation + TConstUnionArray(int size, const TConstUnion& val) + { + unionArray = new TConstUnionVector(size, val); + } + + int size() const { return unionArray ? (int)unionArray->size() : 0; } + TConstUnion& operator[](size_t index) { return (*unionArray)[index]; } + const TConstUnion& operator[](size_t index) const { return (*unionArray)[index]; } + bool operator==(const TConstUnionArray& rhs) const + { + // this includes the case that both are unallocated + if (unionArray == rhs.unionArray) + return true; + + if (! unionArray || ! rhs.unionArray) + return false; + + return *unionArray == *rhs.unionArray; + } + bool operator!=(const TConstUnionArray& rhs) const { return ! operator==(rhs); } + + double dot(const TConstUnionArray& rhs) + { + assert(rhs.unionArray->size() == unionArray->size()); + double sum = 0.0; + + for (size_t comp = 0; comp < unionArray->size(); ++comp) + sum += (*this)[comp].getDConst() * rhs[comp].getDConst(); + + return sum; + } + + bool empty() const { return unionArray == nullptr; } + +protected: + typedef TVector TConstUnionVector; + TConstUnionVector* unionArray; +}; + +} // end namespace glslang + +#endif // _CONSTANT_UNION_INCLUDED_ diff --git a/android/arm64-v8a/include/glslang/glslang/Include/InfoSink.h b/android/arm64-v8a/include/glslang/glslang/Include/InfoSink.h new file mode 100644 index 00000000..dceb603c --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/Include/InfoSink.h @@ -0,0 +1,144 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _INFOSINK_INCLUDED_ +#define _INFOSINK_INCLUDED_ + +#include "../Include/Common.h" +#include + +namespace glslang { + +// +// TPrefixType is used to centralize how info log messages start. +// See below. +// +enum TPrefixType { + EPrefixNone, + EPrefixWarning, + EPrefixError, + EPrefixInternalError, + EPrefixUnimplemented, + EPrefixNote +}; + +enum TOutputStream { + ENull = 0, + EDebugger = 0x01, + EStdOut = 0x02, + EString = 0x04, +}; +// +// Encapsulate info logs for all objects that have them. +// +// The methods are a general set of tools for getting a variety of +// messages and types inserted into the log. +// +class TInfoSinkBase { +public: + TInfoSinkBase() : outputStream(4) {} + void erase() { sink.erase(); } + TInfoSinkBase& operator<<(const TPersistString& t) { append(t); return *this; } + TInfoSinkBase& operator<<(char c) { append(1, c); return *this; } + TInfoSinkBase& operator<<(const char* s) { append(s); return *this; } + TInfoSinkBase& operator<<(int n) { append(String(n)); return *this; } + TInfoSinkBase& operator<<(unsigned int n) { append(String(n)); return *this; } + TInfoSinkBase& operator<<(float n) { const int size = 40; char buf[size]; + snprintf(buf, size, (fabs(n) > 1e-8 && fabs(n) < 1e8) || n == 0.0f ? "%f" : "%g", n); + append(buf); + return *this; } + TInfoSinkBase& operator+(const TPersistString& t) { append(t); return *this; } + TInfoSinkBase& operator+(const TString& t) { append(t); return *this; } + TInfoSinkBase& operator<<(const TString& t) { append(t); return *this; } + TInfoSinkBase& operator+(const char* s) { append(s); return *this; } + const char* c_str() const { return sink.c_str(); } + void prefix(TPrefixType message) { + switch(message) { + case EPrefixNone: break; + case EPrefixWarning: append("WARNING: "); break; + case EPrefixError: append("ERROR: "); break; + case EPrefixInternalError: append("INTERNAL ERROR: "); break; + case EPrefixUnimplemented: append("UNIMPLEMENTED: "); break; + case EPrefixNote: append("NOTE: "); break; + default: append("UNKNOWN ERROR: "); break; + } + } + void location(const TSourceLoc& loc) { + const int maxSize = 24; + char locText[maxSize]; + snprintf(locText, maxSize, ":%d", loc.line); + append(loc.getStringNameOrNum(false).c_str()); + append(locText); + append(": "); + } + void message(TPrefixType message, const char* s) { + prefix(message); + append(s); + append("\n"); + } + void message(TPrefixType message, const char* s, const TSourceLoc& loc) { + prefix(message); + location(loc); + append(s); + append("\n"); + } + + void setOutputStream(int output = 4) + { + outputStream = output; + } + +protected: + void append(const char* s); + + void append(int count, char c); + void append(const TPersistString& t); + void append(const TString& t); + + void checkMem(size_t growth) { if (sink.capacity() < sink.size() + growth + 2) + sink.reserve(sink.capacity() + sink.capacity() / 2); } + void appendToStream(const char* s); + TPersistString sink; + int outputStream; +}; + +} // end namespace glslang + +class TInfoSink { +public: + glslang::TInfoSinkBase info; + glslang::TInfoSinkBase debug; +}; + +#endif // _INFOSINK_INCLUDED_ diff --git a/android/arm64-v8a/include/glslang/glslang/Include/InitializeGlobals.h b/android/arm64-v8a/include/glslang/glslang/Include/InitializeGlobals.h new file mode 100644 index 00000000..95d0a40e --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/Include/InitializeGlobals.h @@ -0,0 +1,44 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef __INITIALIZE_GLOBALS_INCLUDED_ +#define __INITIALIZE_GLOBALS_INCLUDED_ + +namespace glslang { + +bool InitializePoolIndex(); + +} // end namespace glslang + +#endif // __INITIALIZE_GLOBALS_INCLUDED_ diff --git a/android/arm64-v8a/include/glslang/glslang/Include/PoolAlloc.h b/android/arm64-v8a/include/glslang/glslang/Include/PoolAlloc.h new file mode 100644 index 00000000..b8eccb88 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/Include/PoolAlloc.h @@ -0,0 +1,316 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _POOLALLOC_INCLUDED_ +#define _POOLALLOC_INCLUDED_ + +#ifdef _DEBUG +# define GUARD_BLOCKS // define to enable guard block sanity checking +#endif + +// +// This header defines an allocator that can be used to efficiently +// allocate a large number of small requests for heap memory, with the +// intention that they are not individually deallocated, but rather +// collectively deallocated at one time. +// +// This simultaneously +// +// * Makes each individual allocation much more efficient; the +// typical allocation is trivial. +// * Completely avoids the cost of doing individual deallocation. +// * Saves the trouble of tracking down and plugging a large class of leaks. +// +// Individual classes can use this allocator by supplying their own +// new and delete methods. +// +// STL containers can use this allocator by using the pool_allocator +// class as the allocator (second) template argument. +// + +#include +#include +#include + +namespace glslang { + +// If we are using guard blocks, we must track each individual +// allocation. If we aren't using guard blocks, these +// never get instantiated, so won't have any impact. +// + +class TAllocation { +public: + TAllocation(size_t size, unsigned char* mem, TAllocation* prev = 0) : + size(size), mem(mem), prevAlloc(prev) { + // Allocations are bracketed: + // [allocationHeader][initialGuardBlock][userData][finalGuardBlock] + // This would be cleaner with if (guardBlockSize)..., but that + // makes the compiler print warnings about 0 length memsets, + // even with the if() protecting them. +# ifdef GUARD_BLOCKS + memset(preGuard(), guardBlockBeginVal, guardBlockSize); + memset(data(), userDataFill, size); + memset(postGuard(), guardBlockEndVal, guardBlockSize); +# endif + } + + void check() const { + checkGuardBlock(preGuard(), guardBlockBeginVal, "before"); + checkGuardBlock(postGuard(), guardBlockEndVal, "after"); + } + + void checkAllocList() const; + + // Return total size needed to accommodate user buffer of 'size', + // plus our tracking data. + inline static size_t allocationSize(size_t size) { + return size + 2 * guardBlockSize + headerSize(); + } + + // Offset from surrounding buffer to get to user data buffer. + inline static unsigned char* offsetAllocation(unsigned char* m) { + return m + guardBlockSize + headerSize(); + } + +private: + void checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const; + + // Find offsets to pre and post guard blocks, and user data buffer + unsigned char* preGuard() const { return mem + headerSize(); } + unsigned char* data() const { return preGuard() + guardBlockSize; } + unsigned char* postGuard() const { return data() + size; } + + size_t size; // size of the user data area + unsigned char* mem; // beginning of our allocation (pts to header) + TAllocation* prevAlloc; // prior allocation in the chain + + const static unsigned char guardBlockBeginVal; + const static unsigned char guardBlockEndVal; + const static unsigned char userDataFill; + + const static size_t guardBlockSize; +# ifdef GUARD_BLOCKS + inline static size_t headerSize() { return sizeof(TAllocation); } +# else + inline static size_t headerSize() { return 0; } +# endif +}; + +// +// There are several stacks. One is to track the pushing and popping +// of the user, and not yet implemented. The others are simply a +// repositories of free pages or used pages. +// +// Page stacks are linked together with a simple header at the beginning +// of each allocation obtained from the underlying OS. Multi-page allocations +// are returned to the OS. Individual page allocations are kept for future +// re-use. +// +// The "page size" used is not, nor must it match, the underlying OS +// page size. But, having it be about that size or equal to a set of +// pages is likely most optimal. +// +class TPoolAllocator { +public: + TPoolAllocator(int growthIncrement = 8*1024, int allocationAlignment = 16); + + // + // Don't call the destructor just to free up the memory, call pop() + // + ~TPoolAllocator(); + + // + // Call push() to establish a new place to pop memory too. Does not + // have to be called to get things started. + // + void push(); + + // + // Call pop() to free all memory allocated since the last call to push(), + // or if no last call to push, frees all memory since first allocation. + // + void pop(); + + // + // Call popAll() to free all memory allocated. + // + void popAll(); + + // + // Call allocate() to actually acquire memory. Returns 0 if no memory + // available, otherwise a properly aligned pointer to 'numBytes' of memory. + // + void* allocate(size_t numBytes); + + // + // There is no deallocate. The point of this class is that + // deallocation can be skipped by the user of it, as the model + // of use is to simultaneously deallocate everything at once + // by calling pop(), and to not have to solve memory leak problems. + // + +protected: + friend struct tHeader; + + struct tHeader { + tHeader(tHeader* nextPage, size_t pageCount) : +#ifdef GUARD_BLOCKS + lastAllocation(0), +#endif + nextPage(nextPage), pageCount(pageCount) { } + + ~tHeader() { +#ifdef GUARD_BLOCKS + if (lastAllocation) + lastAllocation->checkAllocList(); +#endif + } + +#ifdef GUARD_BLOCKS + TAllocation* lastAllocation; +#endif + tHeader* nextPage; + size_t pageCount; + }; + + struct tAllocState { + size_t offset; + tHeader* page; + }; + typedef std::vector tAllocStack; + + // Track allocations if and only if we're using guard blocks +#ifndef GUARD_BLOCKS + void* initializeAllocation(tHeader*, unsigned char* memory, size_t) { +#else + void* initializeAllocation(tHeader* block, unsigned char* memory, size_t numBytes) { + new(memory) TAllocation(numBytes, memory, block->lastAllocation); + block->lastAllocation = reinterpret_cast(memory); +#endif + + // This is optimized entirely away if GUARD_BLOCKS is not defined. + return TAllocation::offsetAllocation(memory); + } + + size_t pageSize; // granularity of allocation from the OS + size_t alignment; // all returned allocations will be aligned at + // this granularity, which will be a power of 2 + size_t alignmentMask; + size_t headerSkip; // amount of memory to skip to make room for the + // header (basically, size of header, rounded + // up to make it aligned + size_t currentPageOffset; // next offset in top of inUseList to allocate from + tHeader* freeList; // list of popped memory + tHeader* inUseList; // list of all memory currently being used + tAllocStack stack; // stack of where to allocate from, to partition pool + + int numCalls; // just an interesting statistic + size_t totalBytes; // just an interesting statistic +private: + TPoolAllocator& operator=(const TPoolAllocator&); // don't allow assignment operator + TPoolAllocator(const TPoolAllocator&); // don't allow default copy constructor +}; + +// +// There could potentially be many pools with pops happening at +// different times. But a simple use is to have a global pop +// with everyone using the same global allocator. +// +extern TPoolAllocator& GetThreadPoolAllocator(); +void SetThreadPoolAllocator(TPoolAllocator* poolAllocator); + +// +// This STL compatible allocator is intended to be used as the allocator +// parameter to templatized STL containers, like vector and map. +// +// It will use the pools for allocation, and not +// do any deallocation, but will still do destruction. +// +template +class pool_allocator { +public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T *pointer; + typedef const T *const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T value_type; + template + struct rebind { + typedef pool_allocator other; + }; + pointer address(reference x) const { return &x; } + const_pointer address(const_reference x) const { return &x; } + + pool_allocator() : allocator(GetThreadPoolAllocator()) { } + pool_allocator(TPoolAllocator& a) : allocator(a) { } + pool_allocator(const pool_allocator& p) : allocator(p.allocator) { } + + template + pool_allocator(const pool_allocator& p) : allocator(p.getAllocator()) { } + + pointer allocate(size_type n) { + return reinterpret_cast(getAllocator().allocate(n * sizeof(T))); } + pointer allocate(size_type n, const void*) { + return reinterpret_cast(getAllocator().allocate(n * sizeof(T))); } + + void deallocate(void*, size_type) { } + void deallocate(pointer, size_type) { } + + pointer _Charalloc(size_t n) { + return reinterpret_cast(getAllocator().allocate(n)); } + + void construct(pointer p, const T& val) { new ((void *)p) T(val); } + void destroy(pointer p) { p->T::~T(); } + + bool operator==(const pool_allocator& rhs) const { return &getAllocator() == &rhs.getAllocator(); } + bool operator!=(const pool_allocator& rhs) const { return &getAllocator() != &rhs.getAllocator(); } + + size_type max_size() const { return static_cast(-1) / sizeof(T); } + size_type max_size(int size) const { return static_cast(-1) / size; } + + TPoolAllocator& getAllocator() const { return allocator; } + +protected: + pool_allocator& operator=(const pool_allocator&) { return *this; } + TPoolAllocator& allocator; +}; + +} // end namespace glslang + +#endif // _POOLALLOC_INCLUDED_ diff --git a/android/arm64-v8a/include/glslang/glslang/Include/ResourceLimits.h b/android/arm64-v8a/include/glslang/glslang/Include/ResourceLimits.h new file mode 100644 index 00000000..106b21d9 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/Include/ResourceLimits.h @@ -0,0 +1,149 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _RESOURCE_LIMITS_INCLUDED_ +#define _RESOURCE_LIMITS_INCLUDED_ + +struct TLimits { + bool nonInductiveForLoops; + bool whileLoops; + bool doWhileLoops; + bool generalUniformIndexing; + bool generalAttributeMatrixVectorIndexing; + bool generalVaryingIndexing; + bool generalSamplerIndexing; + bool generalVariableIndexing; + bool generalConstantMatrixVectorIndexing; +}; + +struct TBuiltInResource { + int maxLights; + int maxClipPlanes; + int maxTextureUnits; + int maxTextureCoords; + int maxVertexAttribs; + int maxVertexUniformComponents; + int maxVaryingFloats; + int maxVertexTextureImageUnits; + int maxCombinedTextureImageUnits; + int maxTextureImageUnits; + int maxFragmentUniformComponents; + int maxDrawBuffers; + int maxVertexUniformVectors; + int maxVaryingVectors; + int maxFragmentUniformVectors; + int maxVertexOutputVectors; + int maxFragmentInputVectors; + int minProgramTexelOffset; + int maxProgramTexelOffset; + int maxClipDistances; + int maxComputeWorkGroupCountX; + int maxComputeWorkGroupCountY; + int maxComputeWorkGroupCountZ; + int maxComputeWorkGroupSizeX; + int maxComputeWorkGroupSizeY; + int maxComputeWorkGroupSizeZ; + int maxComputeUniformComponents; + int maxComputeTextureImageUnits; + int maxComputeImageUniforms; + int maxComputeAtomicCounters; + int maxComputeAtomicCounterBuffers; + int maxVaryingComponents; + int maxVertexOutputComponents; + int maxGeometryInputComponents; + int maxGeometryOutputComponents; + int maxFragmentInputComponents; + int maxImageUnits; + int maxCombinedImageUnitsAndFragmentOutputs; + int maxCombinedShaderOutputResources; + int maxImageSamples; + int maxVertexImageUniforms; + int maxTessControlImageUniforms; + int maxTessEvaluationImageUniforms; + int maxGeometryImageUniforms; + int maxFragmentImageUniforms; + int maxCombinedImageUniforms; + int maxGeometryTextureImageUnits; + int maxGeometryOutputVertices; + int maxGeometryTotalOutputComponents; + int maxGeometryUniformComponents; + int maxGeometryVaryingComponents; + int maxTessControlInputComponents; + int maxTessControlOutputComponents; + int maxTessControlTextureImageUnits; + int maxTessControlUniformComponents; + int maxTessControlTotalOutputComponents; + int maxTessEvaluationInputComponents; + int maxTessEvaluationOutputComponents; + int maxTessEvaluationTextureImageUnits; + int maxTessEvaluationUniformComponents; + int maxTessPatchComponents; + int maxPatchVertices; + int maxTessGenLevel; + int maxViewports; + int maxVertexAtomicCounters; + int maxTessControlAtomicCounters; + int maxTessEvaluationAtomicCounters; + int maxGeometryAtomicCounters; + int maxFragmentAtomicCounters; + int maxCombinedAtomicCounters; + int maxAtomicCounterBindings; + int maxVertexAtomicCounterBuffers; + int maxTessControlAtomicCounterBuffers; + int maxTessEvaluationAtomicCounterBuffers; + int maxGeometryAtomicCounterBuffers; + int maxFragmentAtomicCounterBuffers; + int maxCombinedAtomicCounterBuffers; + int maxAtomicCounterBufferSize; + int maxTransformFeedbackBuffers; + int maxTransformFeedbackInterleavedComponents; + int maxCullDistances; + int maxCombinedClipAndCullDistances; + int maxSamples; + int maxMeshOutputVerticesNV; + int maxMeshOutputPrimitivesNV; + int maxMeshWorkGroupSizeX_NV; + int maxMeshWorkGroupSizeY_NV; + int maxMeshWorkGroupSizeZ_NV; + int maxTaskWorkGroupSizeX_NV; + int maxTaskWorkGroupSizeY_NV; + int maxTaskWorkGroupSizeZ_NV; + int maxMeshViewCountNV; + + TLimits limits; +}; + +#endif // _RESOURCE_LIMITS_INCLUDED_ diff --git a/android/arm64-v8a/include/glslang/glslang/Include/ShHandle.h b/android/arm64-v8a/include/glslang/glslang/Include/ShHandle.h new file mode 100644 index 00000000..df07bd8e --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/Include/ShHandle.h @@ -0,0 +1,176 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _SHHANDLE_INCLUDED_ +#define _SHHANDLE_INCLUDED_ + +// +// Machine independent part of the compiler private objects +// sent as ShHandle to the driver. +// +// This should not be included by driver code. +// + +#define SH_EXPORTING +#include "../Public/ShaderLang.h" +#include "../MachineIndependent/Versions.h" +#include "InfoSink.h" + +class TCompiler; +class TLinker; +class TUniformMap; + +// +// The base class used to back handles returned to the driver. +// +class TShHandleBase { +public: + TShHandleBase() { pool = new glslang::TPoolAllocator; } + virtual ~TShHandleBase() { delete pool; } + virtual TCompiler* getAsCompiler() { return 0; } + virtual TLinker* getAsLinker() { return 0; } + virtual TUniformMap* getAsUniformMap() { return 0; } + virtual glslang::TPoolAllocator* getPool() const { return pool; } +private: + glslang::TPoolAllocator* pool; +}; + +// +// The base class for the machine dependent linker to derive from +// for managing where uniforms live. +// +class TUniformMap : public TShHandleBase { +public: + TUniformMap() { } + virtual ~TUniformMap() { } + virtual TUniformMap* getAsUniformMap() { return this; } + virtual int getLocation(const char* name) = 0; + virtual TInfoSink& getInfoSink() { return infoSink; } + TInfoSink infoSink; +}; + +class TIntermNode; + +// +// The base class for the machine dependent compiler to derive from +// for managing object code from the compile. +// +class TCompiler : public TShHandleBase { +public: + TCompiler(EShLanguage l, TInfoSink& sink) : infoSink(sink) , language(l), haveValidObjectCode(false) { } + virtual ~TCompiler() { } + EShLanguage getLanguage() { return language; } + virtual TInfoSink& getInfoSink() { return infoSink; } + + virtual bool compile(TIntermNode* root, int version = 0, EProfile profile = ENoProfile) = 0; + + virtual TCompiler* getAsCompiler() { return this; } + virtual bool linkable() { return haveValidObjectCode; } + + TInfoSink& infoSink; +protected: + TCompiler& operator=(TCompiler&); + + EShLanguage language; + bool haveValidObjectCode; +}; + +// +// Link operations are based on a list of compile results... +// +typedef glslang::TVector TCompilerList; +typedef glslang::TVector THandleList; + +// +// The base class for the machine dependent linker to derive from +// to manage the resulting executable. +// + +class TLinker : public TShHandleBase { +public: + TLinker(EShExecutable e, TInfoSink& iSink) : + infoSink(iSink), + executable(e), + haveReturnableObjectCode(false), + appAttributeBindings(0), + fixedAttributeBindings(0), + excludedAttributes(0), + excludedCount(0), + uniformBindings(0) { } + virtual TLinker* getAsLinker() { return this; } + virtual ~TLinker() { } + virtual bool link(TCompilerList&, TUniformMap*) = 0; + virtual bool link(THandleList&) { return false; } + virtual void setAppAttributeBindings(const ShBindingTable* t) { appAttributeBindings = t; } + virtual void setFixedAttributeBindings(const ShBindingTable* t) { fixedAttributeBindings = t; } + virtual void getAttributeBindings(ShBindingTable const **t) const = 0; + virtual void setExcludedAttributes(const int* attributes, int count) { excludedAttributes = attributes; excludedCount = count; } + virtual ShBindingTable* getUniformBindings() const { return uniformBindings; } + virtual const void* getObjectCode() const { return 0; } // a real compiler would be returning object code here + virtual TInfoSink& getInfoSink() { return infoSink; } + TInfoSink& infoSink; +protected: + TLinker& operator=(TLinker&); + EShExecutable executable; + bool haveReturnableObjectCode; // true when objectCode is acceptable to send to driver + + const ShBindingTable* appAttributeBindings; + const ShBindingTable* fixedAttributeBindings; + const int* excludedAttributes; + int excludedCount; + ShBindingTable* uniformBindings; // created by the linker +}; + +// +// This is the interface between the machine independent code +// and the machine dependent code. +// +// The machine dependent code should derive from the classes +// above. Then Construct*() and Delete*() will create and +// destroy the machine dependent objects, which contain the +// above machine independent information. +// +TCompiler* ConstructCompiler(EShLanguage, int); + +TShHandleBase* ConstructLinker(EShExecutable, int); +TShHandleBase* ConstructBindings(); +void DeleteLinker(TShHandleBase*); +void DeleteBindingList(TShHandleBase* bindingList); + +TUniformMap* ConstructUniformMap(); +void DeleteCompiler(TCompiler*); + +void DeleteUniformMap(TUniformMap*); + +#endif // _SHHANDLE_INCLUDED_ diff --git a/android/arm64-v8a/include/glslang/glslang/Include/Types.h b/android/arm64-v8a/include/glslang/glslang/Include/Types.h new file mode 100644 index 00000000..b2c416d1 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/Include/Types.h @@ -0,0 +1,2483 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2016 LunarG, Inc. +// Copyright (C) 2015-2016 Google, Inc. +// Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _TYPES_INCLUDED +#define _TYPES_INCLUDED + +#include "../Include/Common.h" +#include "../Include/BaseTypes.h" +#include "../Public/ShaderLang.h" +#include "arrays.h" + +#include + +namespace glslang { + +const int GlslangMaxTypeLength = 200; // TODO: need to print block/struct one member per line, so this can stay bounded + +const char* const AnonymousPrefix = "anon@"; // for something like a block whose members can be directly accessed +inline bool IsAnonymous(const TString& name) +{ + return name.compare(0, 5, AnonymousPrefix) == 0; +} + +// +// Details within a sampler type +// +enum TSamplerDim { + EsdNone, + Esd1D, + Esd2D, + Esd3D, + EsdCube, + EsdRect, + EsdBuffer, + EsdSubpass, // goes only with non-sampled image (image is true) + EsdNumDims +}; + +struct TSampler { // misnomer now; includes images, textures without sampler, and textures with sampler + TBasicType type : 8; // type returned by sampler + TSamplerDim dim : 8; + bool arrayed : 1; + bool shadow : 1; + bool ms : 1; + bool image : 1; // image, combined should be false + bool combined : 1; // true means texture is combined with a sampler, false means texture with no sampler + bool sampler : 1; // true means a pure sampler, other fields should be clear() + +#ifdef GLSLANG_WEB + bool is1D() const { return false; } + bool isBuffer() const { return false; } + bool isRect() const { return false; } + bool isSubpass() const { return false; } + bool isCombined() const { return true; } + bool isImage() const { return false; } + bool isImageClass() const { return false; } + bool isMultiSample() const { return false; } + bool isExternal() const { return false; } + void setExternal(bool e) { } + bool isYuv() const { return false; } +#else + unsigned int vectorSize : 3; // vector return type size. + // Some languages support structures as sample results. Storing the whole structure in the + // TSampler is too large, so there is an index to a separate table. + static const unsigned structReturnIndexBits = 4; // number of index bits to use. + static const unsigned structReturnSlots = (1< TTypeList; + +typedef TVector TIdentifierList; + +// +// Following are a series of helper enums for managing layouts and qualifiers, +// used for TPublicType, TType, others. +// + +enum TLayoutPacking { + ElpNone, + ElpShared, // default, but different than saying nothing + ElpStd140, + ElpStd430, + ElpPacked, + ElpScalar, + ElpCount // If expanding, see bitfield width below +}; + +enum TLayoutMatrix { + ElmNone, + ElmRowMajor, + ElmColumnMajor, // default, but different than saying nothing + ElmCount // If expanding, see bitfield width below +}; + +// Union of geometry shader and tessellation shader geometry types. +// They don't go into TType, but rather have current state per shader or +// active parser type (TPublicType). +enum TLayoutGeometry { + ElgNone, + ElgPoints, + ElgLines, + ElgLinesAdjacency, + ElgLineStrip, + ElgTriangles, + ElgTrianglesAdjacency, + ElgTriangleStrip, + ElgQuads, + ElgIsolines, +}; + +enum TVertexSpacing { + EvsNone, + EvsEqual, + EvsFractionalEven, + EvsFractionalOdd +}; + +enum TVertexOrder { + EvoNone, + EvoCw, + EvoCcw +}; + +// Note: order matters, as type of format is done by comparison. +enum TLayoutFormat { + ElfNone, + + // Float image + ElfRgba32f, + ElfRgba16f, + ElfR32f, + ElfRgba8, + ElfRgba8Snorm, + + ElfEsFloatGuard, // to help with comparisons + + ElfRg32f, + ElfRg16f, + ElfR11fG11fB10f, + ElfR16f, + ElfRgba16, + ElfRgb10A2, + ElfRg16, + ElfRg8, + ElfR16, + ElfR8, + ElfRgba16Snorm, + ElfRg16Snorm, + ElfRg8Snorm, + ElfR16Snorm, + ElfR8Snorm, + + ElfFloatGuard, // to help with comparisons + + // Int image + ElfRgba32i, + ElfRgba16i, + ElfRgba8i, + ElfR32i, + + ElfEsIntGuard, // to help with comparisons + + ElfRg32i, + ElfRg16i, + ElfRg8i, + ElfR16i, + ElfR8i, + + ElfIntGuard, // to help with comparisons + + // Uint image + ElfRgba32ui, + ElfRgba16ui, + ElfRgba8ui, + ElfR32ui, + + ElfEsUintGuard, // to help with comparisons + + ElfRg32ui, + ElfRg16ui, + ElfRgb10a2ui, + ElfRg8ui, + ElfR16ui, + ElfR8ui, + + ElfCount +}; + +enum TLayoutDepth { + EldNone, + EldAny, + EldGreater, + EldLess, + EldUnchanged, + + EldCount +}; + +enum TBlendEquationShift { + // No 'EBlendNone': + // These are used as bit-shift amounts. A mask of such shifts will have type 'int', + // and in that space, 0 means no bits set, or none. In this enum, 0 means (1 << 0), a bit is set. + EBlendMultiply, + EBlendScreen, + EBlendOverlay, + EBlendDarken, + EBlendLighten, + EBlendColordodge, + EBlendColorburn, + EBlendHardlight, + EBlendSoftlight, + EBlendDifference, + EBlendExclusion, + EBlendHslHue, + EBlendHslSaturation, + EBlendHslColor, + EBlendHslLuminosity, + EBlendAllEquations, + + EBlendCount +}; + +enum TInterlockOrdering { + EioNone, + EioPixelInterlockOrdered, + EioPixelInterlockUnordered, + EioSampleInterlockOrdered, + EioSampleInterlockUnordered, + EioShadingRateInterlockOrdered, + EioShadingRateInterlockUnordered, + + EioCount, +}; + +enum TShaderInterface +{ + // Includes both uniform blocks and buffer blocks + EsiUniform = 0, + EsiInput, + EsiOutput, + EsiNone, + + EsiCount +}; + + +class TQualifier { +public: + static const int layoutNotSet = -1; + + void clear() + { + precision = EpqNone; + invariant = false; + makeTemporary(); + declaredBuiltIn = EbvNone; +#ifndef GLSLANG_WEB + noContraction = false; +#endif + } + + // drop qualifiers that don't belong in a temporary variable + void makeTemporary() + { + semanticName = nullptr; + storage = EvqTemporary; + builtIn = EbvNone; + clearInterstage(); + clearMemory(); + specConstant = false; + nonUniform = false; + clearLayout(); + } + + void clearInterstage() + { + clearInterpolation(); +#ifndef GLSLANG_WEB + patch = false; + sample = false; +#endif + } + + void clearInterpolation() + { + centroid = false; + smooth = false; + flat = false; +#ifndef GLSLANG_WEB + nopersp = false; + explicitInterp = false; + pervertexNV = false; + perPrimitiveNV = false; + perViewNV = false; + perTaskNV = false; +#endif + } + + void clearMemory() + { +#ifndef GLSLANG_WEB + coherent = false; + devicecoherent = false; + queuefamilycoherent = false; + workgroupcoherent = false; + subgroupcoherent = false; + shadercallcoherent = false; + nonprivate = false; + volatil = false; + restrict = false; + readonly = false; + writeonly = false; +#endif + } + + const char* semanticName; + TStorageQualifier storage : 6; + TBuiltInVariable builtIn : 9; + TBuiltInVariable declaredBuiltIn : 9; + static_assert(EbvLast < 256, "need to increase size of TBuiltInVariable bitfields!"); + TPrecisionQualifier precision : 3; + bool invariant : 1; // require canonical treatment for cross-shader invariance + bool centroid : 1; + bool smooth : 1; + bool flat : 1; + // having a constant_id is not sufficient: expressions have no id, but are still specConstant + bool specConstant : 1; + bool nonUniform : 1; + bool explicitOffset : 1; + +#ifdef GLSLANG_WEB + bool isWriteOnly() const { return false; } + bool isReadOnly() const { return false; } + bool isRestrict() const { return false; } + bool isCoherent() const { return false; } + bool isVolatile() const { return false; } + bool isSample() const { return false; } + bool isMemory() const { return false; } + bool isMemoryQualifierImageAndSSBOOnly() const { return false; } + bool bufferReferenceNeedsVulkanMemoryModel() const { return false; } + bool isInterpolation() const { return flat || smooth; } + bool isExplicitInterpolation() const { return false; } + bool isAuxiliary() const { return centroid; } + bool isPatch() const { return false; } + bool isNoContraction() const { return false; } + void setNoContraction() { } + bool isPervertexNV() const { return false; } +#else + bool noContraction: 1; // prevent contraction and reassociation, e.g., for 'precise' keyword, and expressions it affects + bool nopersp : 1; + bool explicitInterp : 1; + bool pervertexNV : 1; + bool perPrimitiveNV : 1; + bool perViewNV : 1; + bool perTaskNV : 1; + bool patch : 1; + bool sample : 1; + bool restrict : 1; + bool readonly : 1; + bool writeonly : 1; + bool coherent : 1; + bool volatil : 1; + bool devicecoherent : 1; + bool queuefamilycoherent : 1; + bool workgroupcoherent : 1; + bool subgroupcoherent : 1; + bool shadercallcoherent : 1; + bool nonprivate : 1; + bool isWriteOnly() const { return writeonly; } + bool isReadOnly() const { return readonly; } + bool isRestrict() const { return restrict; } + bool isCoherent() const { return coherent; } + bool isVolatile() const { return volatil; } + bool isSample() const { return sample; } + bool isMemory() const + { + return shadercallcoherent || subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly || nonprivate; + } + bool isMemoryQualifierImageAndSSBOOnly() const + { + return shadercallcoherent || subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly; + } + bool bufferReferenceNeedsVulkanMemoryModel() const + { + // include qualifiers that map to load/store availability/visibility/nonprivate memory access operands + return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || nonprivate; + } + bool isInterpolation() const + { + return flat || smooth || nopersp || explicitInterp; + } + bool isExplicitInterpolation() const + { + return explicitInterp; + } + bool isAuxiliary() const + { + return centroid || patch || sample || pervertexNV; + } + bool isPatch() const { return patch; } + bool isNoContraction() const { return noContraction; } + void setNoContraction() { noContraction = true; } + bool isPervertexNV() const { return pervertexNV; } +#endif + + bool isPipeInput() const + { + switch (storage) { + case EvqVaryingIn: + case EvqFragCoord: + case EvqPointCoord: + case EvqFace: + case EvqVertexId: + case EvqInstanceId: + return true; + default: + return false; + } + } + + bool isPipeOutput() const + { + switch (storage) { + case EvqPosition: + case EvqPointSize: + case EvqClipVertex: + case EvqVaryingOut: + case EvqFragColor: + case EvqFragDepth: + return true; + default: + return false; + } + } + + bool isParamInput() const + { + switch (storage) { + case EvqIn: + case EvqInOut: + case EvqConstReadOnly: + return true; + default: + return false; + } + } + + bool isParamOutput() const + { + switch (storage) { + case EvqOut: + case EvqInOut: + return true; + default: + return false; + } + } + + bool isUniformOrBuffer() const + { + switch (storage) { + case EvqUniform: + case EvqBuffer: + return true; + default: + return false; + } + } + + bool isIo() const + { + switch (storage) { + case EvqUniform: + case EvqBuffer: + case EvqVaryingIn: + case EvqFragCoord: + case EvqPointCoord: + case EvqFace: + case EvqVertexId: + case EvqInstanceId: + case EvqPosition: + case EvqPointSize: + case EvqClipVertex: + case EvqVaryingOut: + case EvqFragColor: + case EvqFragDepth: + return true; + default: + return false; + } + } + + // non-built-in symbols that might link between compilation units + bool isLinkable() const + { + switch (storage) { + case EvqGlobal: + case EvqVaryingIn: + case EvqVaryingOut: + case EvqUniform: + case EvqBuffer: + case EvqShared: + return true; + default: + return false; + } + } + +#ifdef GLSLANG_WEB + bool isPerView() const { return false; } + bool isTaskMemory() const { return false; } + bool isArrayedIo(EShLanguage language) const { return false; } +#else + bool isPerPrimitive() const { return perPrimitiveNV; } + bool isPerView() const { return perViewNV; } + bool isTaskMemory() const { return perTaskNV; } + + // True if this type of IO is supposed to be arrayed with extra level for per-vertex data + bool isArrayedIo(EShLanguage language) const + { + switch (language) { + case EShLangGeometry: + return isPipeInput(); + case EShLangTessControl: + return ! patch && (isPipeInput() || isPipeOutput()); + case EShLangTessEvaluation: + return ! patch && isPipeInput(); + case EShLangFragment: + return pervertexNV && isPipeInput(); + case EShLangMeshNV: + return ! perTaskNV && isPipeOutput(); + + default: + return false; + } + } +#endif + + // Implementing an embedded layout-qualifier class here, since C++ can't have a real class bitfield + void clearLayout() // all layout + { + clearUniformLayout(); + +#ifndef GLSLANG_WEB + layoutPushConstant = false; + layoutBufferReference = false; + layoutPassthrough = false; + layoutViewportRelative = false; + // -2048 as the default value indicating layoutSecondaryViewportRelative is not set + layoutSecondaryViewportRelativeOffset = -2048; + layoutShaderRecord = false; + layoutBufferReferenceAlign = layoutBufferReferenceAlignEnd; + layoutFormat = ElfNone; +#endif + + clearInterstageLayout(); + + layoutSpecConstantId = layoutSpecConstantIdEnd; + } + void clearInterstageLayout() + { + layoutLocation = layoutLocationEnd; + layoutComponent = layoutComponentEnd; +#ifndef GLSLANG_WEB + layoutIndex = layoutIndexEnd; + clearStreamLayout(); + clearXfbLayout(); +#endif + } + +#ifndef GLSLANG_WEB + void clearStreamLayout() + { + layoutStream = layoutStreamEnd; + } + void clearXfbLayout() + { + layoutXfbBuffer = layoutXfbBufferEnd; + layoutXfbStride = layoutXfbStrideEnd; + layoutXfbOffset = layoutXfbOffsetEnd; + } +#endif + + bool hasNonXfbLayout() const + { + return hasUniformLayout() || + hasAnyLocation() || + hasStream() || + hasFormat() || + isShaderRecord() || + isPushConstant() || + hasBufferReference(); + } + bool hasLayout() const + { + return hasNonXfbLayout() || + hasXfb(); + } + TLayoutMatrix layoutMatrix : 3; + TLayoutPacking layoutPacking : 4; + int layoutOffset; + int layoutAlign; + + unsigned int layoutLocation : 12; + static const unsigned int layoutLocationEnd = 0xFFF; + + unsigned int layoutComponent : 3; + static const unsigned int layoutComponentEnd = 4; + + unsigned int layoutSet : 7; + static const unsigned int layoutSetEnd = 0x3F; + + unsigned int layoutBinding : 16; + static const unsigned int layoutBindingEnd = 0xFFFF; + + unsigned int layoutIndex : 8; + static const unsigned int layoutIndexEnd = 0xFF; + + unsigned int layoutStream : 8; + static const unsigned int layoutStreamEnd = 0xFF; + + unsigned int layoutXfbBuffer : 4; + static const unsigned int layoutXfbBufferEnd = 0xF; + + unsigned int layoutXfbStride : 14; + static const unsigned int layoutXfbStrideEnd = 0x3FFF; + + unsigned int layoutXfbOffset : 13; + static const unsigned int layoutXfbOffsetEnd = 0x1FFF; + + unsigned int layoutAttachment : 8; // for input_attachment_index + static const unsigned int layoutAttachmentEnd = 0XFF; + + unsigned int layoutSpecConstantId : 11; + static const unsigned int layoutSpecConstantIdEnd = 0x7FF; + +#ifndef GLSLANG_WEB + // stored as log2 of the actual alignment value + unsigned int layoutBufferReferenceAlign : 6; + static const unsigned int layoutBufferReferenceAlignEnd = 0x3F; + + TLayoutFormat layoutFormat : 8; + + bool layoutPushConstant; + bool layoutBufferReference; + bool layoutPassthrough; + bool layoutViewportRelative; + int layoutSecondaryViewportRelativeOffset; + bool layoutShaderRecord; +#endif + + bool hasUniformLayout() const + { + return hasMatrix() || + hasPacking() || + hasOffset() || + hasBinding() || + hasSet() || + hasAlign(); + } + void clearUniformLayout() // only uniform specific + { + layoutMatrix = ElmNone; + layoutPacking = ElpNone; + layoutOffset = layoutNotSet; + layoutAlign = layoutNotSet; + + layoutSet = layoutSetEnd; + layoutBinding = layoutBindingEnd; +#ifndef GLSLANG_WEB + layoutAttachment = layoutAttachmentEnd; +#endif + } + + bool hasMatrix() const + { + return layoutMatrix != ElmNone; + } + bool hasPacking() const + { + return layoutPacking != ElpNone; + } + bool hasAlign() const + { + return layoutAlign != layoutNotSet; + } + bool hasAnyLocation() const + { + return hasLocation() || + hasComponent() || + hasIndex(); + } + bool hasLocation() const + { + return layoutLocation != layoutLocationEnd; + } + bool hasSet() const + { + return layoutSet != layoutSetEnd; + } + bool hasBinding() const + { + return layoutBinding != layoutBindingEnd; + } +#ifdef GLSLANG_WEB + bool hasOffset() const { return false; } + bool isNonPerspective() const { return false; } + bool hasIndex() const { return false; } + unsigned getIndex() const { return 0; } + bool hasComponent() const { return false; } + bool hasStream() const { return false; } + bool hasFormat() const { return false; } + bool hasXfb() const { return false; } + bool hasXfbBuffer() const { return false; } + bool hasXfbStride() const { return false; } + bool hasXfbOffset() const { return false; } + bool hasAttachment() const { return false; } + TLayoutFormat getFormat() const { return ElfNone; } + bool isPushConstant() const { return false; } + bool isShaderRecord() const { return false; } + bool hasBufferReference() const { return false; } + bool hasBufferReferenceAlign() const { return false; } + bool isNonUniform() const { return false; } +#else + bool hasOffset() const + { + return layoutOffset != layoutNotSet; + } + bool isNonPerspective() const { return nopersp; } + bool hasIndex() const + { + return layoutIndex != layoutIndexEnd; + } + unsigned getIndex() const { return layoutIndex; } + bool hasComponent() const + { + return layoutComponent != layoutComponentEnd; + } + bool hasStream() const + { + return layoutStream != layoutStreamEnd; + } + bool hasFormat() const + { + return layoutFormat != ElfNone; + } + bool hasXfb() const + { + return hasXfbBuffer() || + hasXfbStride() || + hasXfbOffset(); + } + bool hasXfbBuffer() const + { + return layoutXfbBuffer != layoutXfbBufferEnd; + } + bool hasXfbStride() const + { + return layoutXfbStride != layoutXfbStrideEnd; + } + bool hasXfbOffset() const + { + return layoutXfbOffset != layoutXfbOffsetEnd; + } + bool hasAttachment() const + { + return layoutAttachment != layoutAttachmentEnd; + } + TLayoutFormat getFormat() const { return layoutFormat; } + bool isPushConstant() const { return layoutPushConstant; } + bool isShaderRecord() const { return layoutShaderRecord; } + bool hasBufferReference() const { return layoutBufferReference; } + bool hasBufferReferenceAlign() const + { + return layoutBufferReferenceAlign != layoutBufferReferenceAlignEnd; + } + bool isNonUniform() const + { + return nonUniform; + } +#endif + bool hasSpecConstantId() const + { + // Not the same thing as being a specialization constant, this + // is just whether or not it was declared with an ID. + return layoutSpecConstantId != layoutSpecConstantIdEnd; + } + bool isSpecConstant() const + { + // True if type is a specialization constant, whether or not it + // had a specialization-constant ID, and false if it is not a + // true front-end constant. + return specConstant; + } + bool isFrontEndConstant() const + { + // True if the front-end knows the final constant value. + // This allows front-end constant folding. + return storage == EvqConst && ! specConstant; + } + bool isConstant() const + { + // True if is either kind of constant; specialization or regular. + return isFrontEndConstant() || isSpecConstant(); + } + void makeSpecConstant() + { + storage = EvqConst; + specConstant = true; + } + static const char* getLayoutPackingString(TLayoutPacking packing) + { + switch (packing) { + case ElpStd140: return "std140"; +#ifndef GLSLANG_WEB + case ElpPacked: return "packed"; + case ElpShared: return "shared"; + case ElpStd430: return "std430"; + case ElpScalar: return "scalar"; +#endif + default: return "none"; + } + } + static const char* getLayoutMatrixString(TLayoutMatrix m) + { + switch (m) { + case ElmColumnMajor: return "column_major"; + case ElmRowMajor: return "row_major"; + default: return "none"; + } + } +#ifdef GLSLANG_WEB + static const char* getLayoutFormatString(TLayoutFormat f) { return "none"; } +#else + static const char* getLayoutFormatString(TLayoutFormat f) + { + switch (f) { + case ElfRgba32f: return "rgba32f"; + case ElfRgba16f: return "rgba16f"; + case ElfRg32f: return "rg32f"; + case ElfRg16f: return "rg16f"; + case ElfR11fG11fB10f: return "r11f_g11f_b10f"; + case ElfR32f: return "r32f"; + case ElfR16f: return "r16f"; + case ElfRgba16: return "rgba16"; + case ElfRgb10A2: return "rgb10_a2"; + case ElfRgba8: return "rgba8"; + case ElfRg16: return "rg16"; + case ElfRg8: return "rg8"; + case ElfR16: return "r16"; + case ElfR8: return "r8"; + case ElfRgba16Snorm: return "rgba16_snorm"; + case ElfRgba8Snorm: return "rgba8_snorm"; + case ElfRg16Snorm: return "rg16_snorm"; + case ElfRg8Snorm: return "rg8_snorm"; + case ElfR16Snorm: return "r16_snorm"; + case ElfR8Snorm: return "r8_snorm"; + + case ElfRgba32i: return "rgba32i"; + case ElfRgba16i: return "rgba16i"; + case ElfRgba8i: return "rgba8i"; + case ElfRg32i: return "rg32i"; + case ElfRg16i: return "rg16i"; + case ElfRg8i: return "rg8i"; + case ElfR32i: return "r32i"; + case ElfR16i: return "r16i"; + case ElfR8i: return "r8i"; + + case ElfRgba32ui: return "rgba32ui"; + case ElfRgba16ui: return "rgba16ui"; + case ElfRgba8ui: return "rgba8ui"; + case ElfRg32ui: return "rg32ui"; + case ElfRg16ui: return "rg16ui"; + case ElfRgb10a2ui: return "rgb10_a2ui"; + case ElfRg8ui: return "rg8ui"; + case ElfR32ui: return "r32ui"; + case ElfR16ui: return "r16ui"; + case ElfR8ui: return "r8ui"; + default: return "none"; + } + } + static const char* getLayoutDepthString(TLayoutDepth d) + { + switch (d) { + case EldAny: return "depth_any"; + case EldGreater: return "depth_greater"; + case EldLess: return "depth_less"; + case EldUnchanged: return "depth_unchanged"; + default: return "none"; + } + } + static const char* getBlendEquationString(TBlendEquationShift e) + { + switch (e) { + case EBlendMultiply: return "blend_support_multiply"; + case EBlendScreen: return "blend_support_screen"; + case EBlendOverlay: return "blend_support_overlay"; + case EBlendDarken: return "blend_support_darken"; + case EBlendLighten: return "blend_support_lighten"; + case EBlendColordodge: return "blend_support_colordodge"; + case EBlendColorburn: return "blend_support_colorburn"; + case EBlendHardlight: return "blend_support_hardlight"; + case EBlendSoftlight: return "blend_support_softlight"; + case EBlendDifference: return "blend_support_difference"; + case EBlendExclusion: return "blend_support_exclusion"; + case EBlendHslHue: return "blend_support_hsl_hue"; + case EBlendHslSaturation: return "blend_support_hsl_saturation"; + case EBlendHslColor: return "blend_support_hsl_color"; + case EBlendHslLuminosity: return "blend_support_hsl_luminosity"; + case EBlendAllEquations: return "blend_support_all_equations"; + default: return "unknown"; + } + } + static const char* getGeometryString(TLayoutGeometry geometry) + { + switch (geometry) { + case ElgPoints: return "points"; + case ElgLines: return "lines"; + case ElgLinesAdjacency: return "lines_adjacency"; + case ElgLineStrip: return "line_strip"; + case ElgTriangles: return "triangles"; + case ElgTrianglesAdjacency: return "triangles_adjacency"; + case ElgTriangleStrip: return "triangle_strip"; + case ElgQuads: return "quads"; + case ElgIsolines: return "isolines"; + default: return "none"; + } + } + static const char* getVertexSpacingString(TVertexSpacing spacing) + { + switch (spacing) { + case EvsEqual: return "equal_spacing"; + case EvsFractionalEven: return "fractional_even_spacing"; + case EvsFractionalOdd: return "fractional_odd_spacing"; + default: return "none"; + } + } + static const char* getVertexOrderString(TVertexOrder order) + { + switch (order) { + case EvoCw: return "cw"; + case EvoCcw: return "ccw"; + default: return "none"; + } + } + static int mapGeometryToSize(TLayoutGeometry geometry) + { + switch (geometry) { + case ElgPoints: return 1; + case ElgLines: return 2; + case ElgLinesAdjacency: return 4; + case ElgTriangles: return 3; + case ElgTrianglesAdjacency: return 6; + default: return 0; + } + } + static const char* getInterlockOrderingString(TInterlockOrdering order) + { + switch (order) { + case EioPixelInterlockOrdered: return "pixel_interlock_ordered"; + case EioPixelInterlockUnordered: return "pixel_interlock_unordered"; + case EioSampleInterlockOrdered: return "sample_interlock_ordered"; + case EioSampleInterlockUnordered: return "sample_interlock_unordered"; + case EioShadingRateInterlockOrdered: return "shading_rate_interlock_ordered"; + case EioShadingRateInterlockUnordered: return "shading_rate_interlock_unordered"; + default: return "none"; + } + } +#endif +}; + +// Qualifiers that don't need to be keep per object. They have shader scope, not object scope. +// So, they will not be part of TType, TQualifier, etc. +struct TShaderQualifiers { + TLayoutGeometry geometry; // geometry/tessellation shader in/out primitives + bool pixelCenterInteger; // fragment shader + bool originUpperLeft; // fragment shader + int invocations; + int vertices; // for tessellation "vertices", geometry & mesh "max_vertices" + TVertexSpacing spacing; + TVertexOrder order; + bool pointMode; + int localSize[3]; // compute shader + bool localSizeNotDefault[3]; // compute shader + int localSizeSpecId[3]; // compute shader specialization id for gl_WorkGroupSize +#ifndef GLSLANG_WEB + bool earlyFragmentTests; // fragment input + bool postDepthCoverage; // fragment input + TLayoutDepth layoutDepth; + bool blendEquation; // true if any blend equation was specified + int numViews; // multiview extenstions + TInterlockOrdering interlockOrdering; + bool layoutOverrideCoverage; // true if layout override_coverage set + bool layoutDerivativeGroupQuads; // true if layout derivative_group_quadsNV set + bool layoutDerivativeGroupLinear; // true if layout derivative_group_linearNV set + int primitives; // mesh shader "max_primitives"DerivativeGroupLinear; // true if layout derivative_group_linearNV set + TLayoutDepth getDepth() const { return layoutDepth; } +#else + TLayoutDepth getDepth() const { return EldNone; } +#endif + + void init() + { + geometry = ElgNone; + originUpperLeft = false; + pixelCenterInteger = false; + invocations = TQualifier::layoutNotSet; + vertices = TQualifier::layoutNotSet; + spacing = EvsNone; + order = EvoNone; + pointMode = false; + localSize[0] = 1; + localSize[1] = 1; + localSize[2] = 1; + localSizeNotDefault[0] = false; + localSizeNotDefault[1] = false; + localSizeNotDefault[2] = false; + localSizeSpecId[0] = TQualifier::layoutNotSet; + localSizeSpecId[1] = TQualifier::layoutNotSet; + localSizeSpecId[2] = TQualifier::layoutNotSet; +#ifndef GLSLANG_WEB + earlyFragmentTests = false; + postDepthCoverage = false; + layoutDepth = EldNone; + blendEquation = false; + numViews = TQualifier::layoutNotSet; + layoutOverrideCoverage = false; + layoutDerivativeGroupQuads = false; + layoutDerivativeGroupLinear = false; + primitives = TQualifier::layoutNotSet; + interlockOrdering = EioNone; +#endif + } + +#ifdef GLSLANG_WEB + bool hasBlendEquation() const { return false; } +#else + bool hasBlendEquation() const { return blendEquation; } +#endif + + // Merge in characteristics from the 'src' qualifier. They can override when + // set, but never erase when not set. + void merge(const TShaderQualifiers& src) + { + if (src.geometry != ElgNone) + geometry = src.geometry; + if (src.pixelCenterInteger) + pixelCenterInteger = src.pixelCenterInteger; + if (src.originUpperLeft) + originUpperLeft = src.originUpperLeft; + if (src.invocations != TQualifier::layoutNotSet) + invocations = src.invocations; + if (src.vertices != TQualifier::layoutNotSet) + vertices = src.vertices; + if (src.spacing != EvsNone) + spacing = src.spacing; + if (src.order != EvoNone) + order = src.order; + if (src.pointMode) + pointMode = true; + for (int i = 0; i < 3; ++i) { + if (src.localSize[i] > 1) + localSize[i] = src.localSize[i]; + } + for (int i = 0; i < 3; ++i) { + localSizeNotDefault[i] = src.localSizeNotDefault[i] || localSizeNotDefault[i]; + } + for (int i = 0; i < 3; ++i) { + if (src.localSizeSpecId[i] != TQualifier::layoutNotSet) + localSizeSpecId[i] = src.localSizeSpecId[i]; + } +#ifndef GLSLANG_WEB + if (src.earlyFragmentTests) + earlyFragmentTests = true; + if (src.postDepthCoverage) + postDepthCoverage = true; + if (src.layoutDepth) + layoutDepth = src.layoutDepth; + if (src.blendEquation) + blendEquation = src.blendEquation; + if (src.numViews != TQualifier::layoutNotSet) + numViews = src.numViews; + if (src.layoutOverrideCoverage) + layoutOverrideCoverage = src.layoutOverrideCoverage; + if (src.layoutDerivativeGroupQuads) + layoutDerivativeGroupQuads = src.layoutDerivativeGroupQuads; + if (src.layoutDerivativeGroupLinear) + layoutDerivativeGroupLinear = src.layoutDerivativeGroupLinear; + if (src.primitives != TQualifier::layoutNotSet) + primitives = src.primitives; + if (src.interlockOrdering != EioNone) + interlockOrdering = src.interlockOrdering; +#endif + } +}; + +// +// TPublicType is just temporarily used while parsing and not quite the same +// information kept per node in TType. Due to the bison stack, it can't have +// types that it thinks have non-trivial constructors. It should +// just be used while recognizing the grammar, not anything else. +// Once enough is known about the situation, the proper information +// moved into a TType, or the parse context, etc. +// +class TPublicType { +public: + TBasicType basicType; + TSampler sampler; + TQualifier qualifier; + TShaderQualifiers shaderQualifiers; + int vectorSize : 4; + int matrixCols : 4; + int matrixRows : 4; + bool coopmat : 1; + TArraySizes* arraySizes; + const TType* userDef; + TSourceLoc loc; + TArraySizes* typeParameters; + +#ifdef GLSLANG_WEB + bool isCoopmat() const { return false; } +#else + bool isCoopmat() const { return coopmat; } +#endif + + void initType(const TSourceLoc& l) + { + basicType = EbtVoid; + vectorSize = 1; + matrixRows = 0; + matrixCols = 0; + arraySizes = nullptr; + userDef = nullptr; + loc = l; + typeParameters = nullptr; + coopmat = false; + } + + void initQualifiers(bool global = false) + { + qualifier.clear(); + if (global) + qualifier.storage = EvqGlobal; + } + + void init(const TSourceLoc& l, bool global = false) + { + initType(l); + sampler.clear(); + initQualifiers(global); + shaderQualifiers.init(); + } + + void setVector(int s) + { + matrixRows = 0; + matrixCols = 0; + vectorSize = s; + } + + void setMatrix(int c, int r) + { + matrixRows = r; + matrixCols = c; + vectorSize = 0; + } + + bool isScalar() const + { + return matrixCols == 0 && vectorSize == 1 && arraySizes == nullptr && userDef == nullptr; + } + + // "Image" is a superset of "Subpass" + bool isImage() const { return basicType == EbtSampler && sampler.isImage(); } + bool isSubpass() const { return basicType == EbtSampler && sampler.isSubpass(); } +}; + +// +// Base class for things that have a type. +// +class TType { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + // for "empty" type (no args) or simple scalar/vector/matrix + explicit TType(TBasicType t = EbtVoid, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0, + bool isVector = false) : + basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1), coopmat(false), + arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr) + { + sampler.clear(); + qualifier.clear(); + qualifier.storage = q; + assert(!(isMatrix() && vectorSize != 0)); // prevent vectorSize != 0 on matrices + } + // for explicit precision qualifier + TType(TBasicType t, TStorageQualifier q, TPrecisionQualifier p, int vs = 1, int mc = 0, int mr = 0, + bool isVector = false) : + basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1), coopmat(false), + arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr) + { + sampler.clear(); + qualifier.clear(); + qualifier.storage = q; + qualifier.precision = p; + assert(p >= EpqNone && p <= EpqHigh); + assert(!(isMatrix() && vectorSize != 0)); // prevent vectorSize != 0 on matrices + } + // for turning a TPublicType into a TType, using a shallow copy + explicit TType(const TPublicType& p) : + basicType(p.basicType), + vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), vector1(false), coopmat(p.coopmat), + arraySizes(p.arraySizes), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(p.typeParameters) + { + if (basicType == EbtSampler) + sampler = p.sampler; + else + sampler.clear(); + qualifier = p.qualifier; + if (p.userDef) { + if (p.userDef->basicType == EbtReference) { + basicType = EbtReference; + referentType = p.userDef->referentType; + } else { + structure = p.userDef->getWritableStruct(); // public type is short-lived; there are no sharing issues + } + typeName = NewPoolTString(p.userDef->getTypeName().c_str()); + } + if (p.isCoopmat() && p.typeParameters && p.typeParameters->getNumDims() > 0) { + int numBits = p.typeParameters->getDimSize(0); + if (p.basicType == EbtFloat && numBits == 16) { + basicType = EbtFloat16; + qualifier.precision = EpqNone; + } else if (p.basicType == EbtUint && numBits == 8) { + basicType = EbtUint8; + qualifier.precision = EpqNone; + } else if (p.basicType == EbtInt && numBits == 8) { + basicType = EbtInt8; + qualifier.precision = EpqNone; + } + } + } + // for construction of sampler types + TType(const TSampler& sampler, TStorageQualifier q = EvqUniform, TArraySizes* as = nullptr) : + basicType(EbtSampler), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false), + arraySizes(as), structure(nullptr), fieldName(nullptr), typeName(nullptr), + sampler(sampler), typeParameters(nullptr) + { + qualifier.clear(); + qualifier.storage = q; + } + // to efficiently make a dereferenced type + // without ever duplicating the outer structure that will be thrown away + // and using only shallow copy + TType(const TType& type, int derefIndex, bool rowMajor = false) + { + if (type.isArray()) { + shallowCopy(type); + if (type.getArraySizes()->getNumDims() == 1) { + arraySizes = nullptr; + } else { + // want our own copy of the array, so we can edit it + arraySizes = new TArraySizes; + arraySizes->copyDereferenced(*type.arraySizes); + } + } else if (type.basicType == EbtStruct || type.basicType == EbtBlock) { + // do a structure dereference + const TTypeList& memberList = *type.getStruct(); + shallowCopy(*memberList[derefIndex].type); + return; + } else { + // do a vector/matrix dereference + shallowCopy(type); + if (matrixCols > 0) { + // dereference from matrix to vector + if (rowMajor) + vectorSize = matrixCols; + else + vectorSize = matrixRows; + matrixCols = 0; + matrixRows = 0; + if (vectorSize == 1) + vector1 = true; + } else if (isVector()) { + // dereference from vector to scalar + vectorSize = 1; + vector1 = false; + } else if (isCoopMat()) { + coopmat = false; + typeParameters = nullptr; + } + } + } + // for making structures, ... + TType(TTypeList* userDef, const TString& n) : + basicType(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false), + arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr) + { + sampler.clear(); + qualifier.clear(); + typeName = NewPoolTString(n.c_str()); + } + // For interface blocks + TType(TTypeList* userDef, const TString& n, const TQualifier& q) : + basicType(EbtBlock), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false), + qualifier(q), arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr) + { + sampler.clear(); + typeName = NewPoolTString(n.c_str()); + } + // for block reference (first parameter must be EbtReference) + explicit TType(TBasicType t, const TType &p, const TString& n) : + basicType(t), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), + arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr) + { + assert(t == EbtReference); + typeName = NewPoolTString(n.c_str()); + qualifier.clear(); + qualifier.storage = p.qualifier.storage; + referentType = p.clone(); + } + virtual ~TType() {} + + // Not for use across pool pops; it will cause multiple instances of TType to point to the same information. + // This only works if that information (like a structure's list of types) does not change and + // the instances are sharing the same pool. + void shallowCopy(const TType& copyOf) + { + basicType = copyOf.basicType; + sampler = copyOf.sampler; + qualifier = copyOf.qualifier; + vectorSize = copyOf.vectorSize; + matrixCols = copyOf.matrixCols; + matrixRows = copyOf.matrixRows; + vector1 = copyOf.vector1; + arraySizes = copyOf.arraySizes; // copying the pointer only, not the contents + fieldName = copyOf.fieldName; + typeName = copyOf.typeName; + if (isStruct()) { + structure = copyOf.structure; + } else { + referentType = copyOf.referentType; + } + typeParameters = copyOf.typeParameters; + coopmat = copyOf.isCoopMat(); + } + + // Make complete copy of the whole type graph rooted at 'copyOf'. + void deepCopy(const TType& copyOf) + { + TMap copied; // to enable copying a type graph as a graph, not a tree + deepCopy(copyOf, copied); + } + + // Recursively make temporary + void makeTemporary() + { + getQualifier().makeTemporary(); + + if (isStruct()) + for (unsigned int i = 0; i < structure->size(); ++i) + (*structure)[i].type->makeTemporary(); + } + + TType* clone() const + { + TType *newType = new TType(); + newType->deepCopy(*this); + + return newType; + } + + void makeVector() { vector1 = true; } + + virtual void hideMember() { basicType = EbtVoid; vectorSize = 1; } + virtual bool hiddenMember() const { return basicType == EbtVoid; } + + virtual void setFieldName(const TString& n) { fieldName = NewPoolTString(n.c_str()); } + virtual const TString& getTypeName() const + { + assert(typeName); + return *typeName; + } + + virtual const TString& getFieldName() const + { + assert(fieldName); + return *fieldName; + } + TShaderInterface getShaderInterface() const + { + if (basicType != EbtBlock) + return EsiNone; + + switch (qualifier.storage) { + default: + return EsiNone; + case EvqVaryingIn: + return EsiInput; + case EvqVaryingOut: + return EsiOutput; + case EvqUniform: + case EvqBuffer: + return EsiUniform; + } + } + + virtual TBasicType getBasicType() const { return basicType; } + virtual const TSampler& getSampler() const { return sampler; } + virtual TSampler& getSampler() { return sampler; } + + virtual TQualifier& getQualifier() { return qualifier; } + virtual const TQualifier& getQualifier() const { return qualifier; } + + virtual int getVectorSize() const { return vectorSize; } // returns 1 for either scalar or vector of size 1, valid for both + virtual int getMatrixCols() const { return matrixCols; } + virtual int getMatrixRows() const { return matrixRows; } + virtual int getOuterArraySize() const { return arraySizes->getOuterSize(); } + virtual TIntermTyped* getOuterArrayNode() const { return arraySizes->getOuterNode(); } + virtual int getCumulativeArraySize() const { return arraySizes->getCumulativeSize(); } +#ifdef GLSLANG_WEB + bool isArrayOfArrays() const { return false; } +#else + bool isArrayOfArrays() const { return arraySizes != nullptr && arraySizes->getNumDims() > 1; } +#endif + virtual int getImplicitArraySize() const { return arraySizes->getImplicitSize(); } + virtual const TArraySizes* getArraySizes() const { return arraySizes; } + virtual TArraySizes* getArraySizes() { return arraySizes; } + virtual TType* getReferentType() const { return referentType; } + virtual const TArraySizes* getTypeParameters() const { return typeParameters; } + virtual TArraySizes* getTypeParameters() { return typeParameters; } + + virtual bool isScalar() const { return ! isVector() && ! isMatrix() && ! isStruct() && ! isArray(); } + virtual bool isScalarOrVec1() const { return isScalar() || vector1; } + virtual bool isVector() const { return vectorSize > 1 || vector1; } + virtual bool isMatrix() const { return matrixCols ? true : false; } + virtual bool isArray() const { return arraySizes != nullptr; } + virtual bool isSizedArray() const { return isArray() && arraySizes->isSized(); } + virtual bool isUnsizedArray() const { return isArray() && !arraySizes->isSized(); } + virtual bool isArrayVariablyIndexed() const { assert(isArray()); return arraySizes->isVariablyIndexed(); } + virtual void setArrayVariablyIndexed() { assert(isArray()); arraySizes->setVariablyIndexed(); } + virtual void updateImplicitArraySize(int size) { assert(isArray()); arraySizes->updateImplicitSize(size); } + virtual bool isStruct() const { return basicType == EbtStruct || basicType == EbtBlock; } + virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble || basicType == EbtFloat16; } + virtual bool isIntegerDomain() const + { + switch (basicType) { + case EbtInt8: + case EbtUint8: + case EbtInt16: + case EbtUint16: + case EbtInt: + case EbtUint: + case EbtInt64: + case EbtUint64: + case EbtAtomicUint: + return true; + default: + break; + } + return false; + } + virtual bool isOpaque() const { return basicType == EbtSampler +#ifndef GLSLANG_WEB + || basicType == EbtAtomicUint || basicType == EbtAccStruct || basicType == EbtRayQuery +#endif + ; } + virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; } + + // "Image" is a superset of "Subpass" + virtual bool isImage() const { return basicType == EbtSampler && getSampler().isImage(); } + virtual bool isSubpass() const { return basicType == EbtSampler && getSampler().isSubpass(); } + virtual bool isTexture() const { return basicType == EbtSampler && getSampler().isTexture(); } + // Check the block-name convention of creating a block without populating it's members: + virtual bool isUnusableName() const { return isStruct() && structure == nullptr; } + virtual bool isParameterized() const { return typeParameters != nullptr; } +#ifdef GLSLANG_WEB + bool isAtomic() const { return false; } + bool isCoopMat() const { return false; } + bool isReference() const { return false; } +#else + bool isAtomic() const { return basicType == EbtAtomicUint; } + bool isCoopMat() const { return coopmat; } + bool isReference() const { return getBasicType() == EbtReference; } +#endif + + // return true if this type contains any subtype which satisfies the given predicate. + template + bool contains(P predicate) const + { + if (predicate(this)) + return true; + + const auto hasa = [predicate](const TTypeLoc& tl) { return tl.type->contains(predicate); }; + + return isStruct() && std::any_of(structure->begin(), structure->end(), hasa); + } + + // Recursively checks if the type contains the given basic type + virtual bool containsBasicType(TBasicType checkType) const + { + return contains([checkType](const TType* t) { return t->basicType == checkType; } ); + } + + // Recursively check the structure for any arrays, needed for some error checks + virtual bool containsArray() const + { + return contains([](const TType* t) { return t->isArray(); } ); + } + + // Check the structure for any structures, needed for some error checks + virtual bool containsStructure() const + { + return contains([this](const TType* t) { return t != this && t->isStruct(); } ); + } + + // Recursively check the structure for any unsized arrays, needed for triggering a copyUp(). + virtual bool containsUnsizedArray() const + { + return contains([](const TType* t) { return t->isUnsizedArray(); } ); + } + + virtual bool containsOpaque() const + { + return contains([](const TType* t) { return t->isOpaque(); } ); + } + + // Recursively checks if the type contains a built-in variable + virtual bool containsBuiltIn() const + { + return contains([](const TType* t) { return t->isBuiltIn(); } ); + } + + virtual bool containsNonOpaque() const + { + const auto nonOpaque = [](const TType* t) { + switch (t->basicType) { + case EbtVoid: + case EbtFloat: + case EbtDouble: + case EbtFloat16: + case EbtInt8: + case EbtUint8: + case EbtInt16: + case EbtUint16: + case EbtInt: + case EbtUint: + case EbtInt64: + case EbtUint64: + case EbtBool: + case EbtReference: + return true; + default: + return false; + } + }; + + return contains(nonOpaque); + } + + virtual bool containsSpecializationSize() const + { + return contains([](const TType* t) { return t->isArray() && t->arraySizes->isOuterSpecialization(); } ); + } + +#ifdef GLSLANG_WEB + bool containsDouble() const { return false; } + bool contains16BitFloat() const { return false; } + bool contains64BitInt() const { return false; } + bool contains16BitInt() const { return false; } + bool contains8BitInt() const { return false; } + bool containsCoopMat() const { return false; } + bool containsReference() const { return false; } +#else + bool containsDouble() const + { + return containsBasicType(EbtDouble); + } + bool contains16BitFloat() const + { + return containsBasicType(EbtFloat16); + } + bool contains64BitInt() const + { + return containsBasicType(EbtInt64) || containsBasicType(EbtUint64); + } + bool contains16BitInt() const + { + return containsBasicType(EbtInt16) || containsBasicType(EbtUint16); + } + bool contains8BitInt() const + { + return containsBasicType(EbtInt8) || containsBasicType(EbtUint8); + } + bool containsCoopMat() const + { + return contains([](const TType* t) { return t->coopmat; } ); + } + bool containsReference() const + { + return containsBasicType(EbtReference); + } +#endif + + // Array editing methods. Array descriptors can be shared across + // type instances. This allows all uses of the same array + // to be updated at once. E.g., all nodes can be explicitly sized + // by tracking and correcting one implicit size. Or, all nodes + // can get the explicit size on a redeclaration that gives size. + // + // N.B.: Don't share with the shared symbol tables (symbols are + // marked as isReadOnly(). Such symbols with arrays that will be + // edited need to copyUp() on first use, so that + // A) the edits don't effect the shared symbol table, and + // B) the edits are shared across all users. + void updateArraySizes(const TType& type) + { + // For when we may already be sharing existing array descriptors, + // keeping the pointers the same, just updating the contents. + assert(arraySizes != nullptr); + assert(type.arraySizes != nullptr); + *arraySizes = *type.arraySizes; + } + void copyArraySizes(const TArraySizes& s) + { + // For setting a fresh new set of array sizes, not yet worrying about sharing. + arraySizes = new TArraySizes; + *arraySizes = s; + } + void transferArraySizes(TArraySizes* s) + { + // For setting an already allocated set of sizes that this type can use + // (no copy made). + arraySizes = s; + } + void clearArraySizes() + { + arraySizes = nullptr; + } + + // Add inner array sizes, to any existing sizes, via copy; the + // sizes passed in can still be reused for other purposes. + void copyArrayInnerSizes(const TArraySizes* s) + { + if (s != nullptr) { + if (arraySizes == nullptr) + copyArraySizes(*s); + else + arraySizes->addInnerSizes(*s); + } + } + void changeOuterArraySize(int s) { arraySizes->changeOuterSize(s); } + + // Recursively make the implicit array size the explicit array size. + // Expicit arrays are compile-time or link-time sized, never run-time sized. + // Sometimes, policy calls for an array to be run-time sized even if it was + // never variably indexed: Don't turn a 'skipNonvariablyIndexed' array into + // an explicit array. + void adoptImplicitArraySizes(bool skipNonvariablyIndexed) + { + if (isUnsizedArray() && !(skipNonvariablyIndexed || isArrayVariablyIndexed())) + changeOuterArraySize(getImplicitArraySize()); + // For multi-dim per-view arrays, set unsized inner dimension size to 1 + if (qualifier.isPerView() && arraySizes && arraySizes->isInnerUnsized()) + arraySizes->clearInnerUnsized(); + if (isStruct() && structure->size() > 0) { + int lastMember = (int)structure->size() - 1; + for (int i = 0; i < lastMember; ++i) + (*structure)[i].type->adoptImplicitArraySizes(false); + // implement the "last member of an SSBO" policy + (*structure)[lastMember].type->adoptImplicitArraySizes(getQualifier().storage == EvqBuffer); + } + } + + + void updateTypeParameters(const TType& type) + { + // For when we may already be sharing existing array descriptors, + // keeping the pointers the same, just updating the contents. + assert(typeParameters != nullptr); + assert(type.typeParameters != nullptr); + *typeParameters = *type.typeParameters; + } + void copyTypeParameters(const TArraySizes& s) + { + // For setting a fresh new set of type parameters, not yet worrying about sharing. + typeParameters = new TArraySizes; + *typeParameters = s; + } + void transferTypeParameters(TArraySizes* s) + { + // For setting an already allocated set of sizes that this type can use + // (no copy made). + typeParameters = s; + } + void clearTypeParameters() + { + typeParameters = nullptr; + } + + // Add inner array sizes, to any existing sizes, via copy; the + // sizes passed in can still be reused for other purposes. + void copyTypeParametersInnerSizes(const TArraySizes* s) + { + if (s != nullptr) { + if (typeParameters == nullptr) + copyTypeParameters(*s); + else + typeParameters->addInnerSizes(*s); + } + } + + + + const char* getBasicString() const + { + return TType::getBasicString(basicType); + } + + static const char* getBasicString(TBasicType t) + { + switch (t) { + case EbtFloat: return "float"; + case EbtInt: return "int"; + case EbtUint: return "uint"; + case EbtSampler: return "sampler/image"; +#ifndef GLSLANG_WEB + case EbtVoid: return "void"; + case EbtDouble: return "double"; + case EbtFloat16: return "float16_t"; + case EbtInt8: return "int8_t"; + case EbtUint8: return "uint8_t"; + case EbtInt16: return "int16_t"; + case EbtUint16: return "uint16_t"; + case EbtInt64: return "int64_t"; + case EbtUint64: return "uint64_t"; + case EbtBool: return "bool"; + case EbtAtomicUint: return "atomic_uint"; + case EbtStruct: return "structure"; + case EbtBlock: return "block"; + case EbtAccStruct: return "accelerationStructureNV"; + case EbtRayQuery: return "rayQueryEXT"; + case EbtReference: return "reference"; +#endif + default: return "unknown type"; + } + } + +#ifdef GLSLANG_WEB + TString getCompleteString() const { return ""; } + const char* getStorageQualifierString() const { return ""; } + const char* getBuiltInVariableString() const { return ""; } + const char* getPrecisionQualifierString() const { return ""; } + TString getBasicTypeString() const { return ""; } +#else + TString getCompleteString() const + { + TString typeString; + + const auto appendStr = [&](const char* s) { typeString.append(s); }; + const auto appendUint = [&](unsigned int u) { typeString.append(std::to_string(u).c_str()); }; + const auto appendInt = [&](int i) { typeString.append(std::to_string(i).c_str()); }; + + if (qualifier.hasLayout()) { + // To reduce noise, skip this if the only layout is an xfb_buffer + // with no triggering xfb_offset. + TQualifier noXfbBuffer = qualifier; + noXfbBuffer.layoutXfbBuffer = TQualifier::layoutXfbBufferEnd; + if (noXfbBuffer.hasLayout()) { + appendStr("layout("); + if (qualifier.hasAnyLocation()) { + appendStr(" location="); + appendUint(qualifier.layoutLocation); + if (qualifier.hasComponent()) { + appendStr(" component="); + appendUint(qualifier.layoutComponent); + } + if (qualifier.hasIndex()) { + appendStr(" index="); + appendUint(qualifier.layoutIndex); + } + } + if (qualifier.hasSet()) { + appendStr(" set="); + appendUint(qualifier.layoutSet); + } + if (qualifier.hasBinding()) { + appendStr(" binding="); + appendUint(qualifier.layoutBinding); + } + if (qualifier.hasStream()) { + appendStr(" stream="); + appendUint(qualifier.layoutStream); + } + if (qualifier.hasMatrix()) { + appendStr(" "); + appendStr(TQualifier::getLayoutMatrixString(qualifier.layoutMatrix)); + } + if (qualifier.hasPacking()) { + appendStr(" "); + appendStr(TQualifier::getLayoutPackingString(qualifier.layoutPacking)); + } + if (qualifier.hasOffset()) { + appendStr(" offset="); + appendInt(qualifier.layoutOffset); + } + if (qualifier.hasAlign()) { + appendStr(" align="); + appendInt(qualifier.layoutAlign); + } + if (qualifier.hasFormat()) { + appendStr(" "); + appendStr(TQualifier::getLayoutFormatString(qualifier.layoutFormat)); + } + if (qualifier.hasXfbBuffer() && qualifier.hasXfbOffset()) { + appendStr(" xfb_buffer="); + appendUint(qualifier.layoutXfbBuffer); + } + if (qualifier.hasXfbOffset()) { + appendStr(" xfb_offset="); + appendUint(qualifier.layoutXfbOffset); + } + if (qualifier.hasXfbStride()) { + appendStr(" xfb_stride="); + appendUint(qualifier.layoutXfbStride); + } + if (qualifier.hasAttachment()) { + appendStr(" input_attachment_index="); + appendUint(qualifier.layoutAttachment); + } + if (qualifier.hasSpecConstantId()) { + appendStr(" constant_id="); + appendUint(qualifier.layoutSpecConstantId); + } + if (qualifier.layoutPushConstant) + appendStr(" push_constant"); + if (qualifier.layoutBufferReference) + appendStr(" buffer_reference"); + if (qualifier.hasBufferReferenceAlign()) { + appendStr(" buffer_reference_align="); + appendUint(1u << qualifier.layoutBufferReferenceAlign); + } + + if (qualifier.layoutPassthrough) + appendStr(" passthrough"); + if (qualifier.layoutViewportRelative) + appendStr(" layoutViewportRelative"); + if (qualifier.layoutSecondaryViewportRelativeOffset != -2048) { + appendStr(" layoutSecondaryViewportRelativeOffset="); + appendInt(qualifier.layoutSecondaryViewportRelativeOffset); + } + if (qualifier.layoutShaderRecord) + appendStr(" shaderRecordNV"); + + appendStr(")"); + } + } + + if (qualifier.invariant) + appendStr(" invariant"); + if (qualifier.noContraction) + appendStr(" noContraction"); + if (qualifier.centroid) + appendStr(" centroid"); + if (qualifier.smooth) + appendStr(" smooth"); + if (qualifier.flat) + appendStr(" flat"); + if (qualifier.nopersp) + appendStr(" noperspective"); + if (qualifier.explicitInterp) + appendStr(" __explicitInterpAMD"); + if (qualifier.pervertexNV) + appendStr(" pervertexNV"); + if (qualifier.perPrimitiveNV) + appendStr(" perprimitiveNV"); + if (qualifier.perViewNV) + appendStr(" perviewNV"); + if (qualifier.perTaskNV) + appendStr(" taskNV"); + if (qualifier.patch) + appendStr(" patch"); + if (qualifier.sample) + appendStr(" sample"); + if (qualifier.coherent) + appendStr(" coherent"); + if (qualifier.devicecoherent) + appendStr(" devicecoherent"); + if (qualifier.queuefamilycoherent) + appendStr(" queuefamilycoherent"); + if (qualifier.workgroupcoherent) + appendStr(" workgroupcoherent"); + if (qualifier.subgroupcoherent) + appendStr(" subgroupcoherent"); + if (qualifier.shadercallcoherent) + appendStr(" shadercallcoherent"); + if (qualifier.nonprivate) + appendStr(" nonprivate"); + if (qualifier.volatil) + appendStr(" volatile"); + if (qualifier.restrict) + appendStr(" restrict"); + if (qualifier.readonly) + appendStr(" readonly"); + if (qualifier.writeonly) + appendStr(" writeonly"); + if (qualifier.specConstant) + appendStr(" specialization-constant"); + if (qualifier.nonUniform) + appendStr(" nonuniform"); + appendStr(" "); + appendStr(getStorageQualifierString()); + if (isArray()) { + for(int i = 0; i < (int)arraySizes->getNumDims(); ++i) { + int size = arraySizes->getDimSize(i); + if (size == UnsizedArraySize && i == 0 && arraySizes->isVariablyIndexed()) + appendStr(" runtime-sized array of"); + else { + if (size == UnsizedArraySize) { + appendStr(" unsized"); + if (i == 0) { + appendStr(" "); + appendInt(arraySizes->getImplicitSize()); + } + } else { + appendStr(" "); + appendInt(arraySizes->getDimSize(i)); + } + appendStr("-element array of"); + } + } + } + if (isParameterized()) { + appendStr("<"); + for(int i = 0; i < (int)typeParameters->getNumDims(); ++i) { + appendInt(typeParameters->getDimSize(i)); + if (i != (int)typeParameters->getNumDims() - 1) + appendStr(", "); + } + appendStr(">"); + } + if (qualifier.precision != EpqNone) { + appendStr(" "); + appendStr(getPrecisionQualifierString()); + } + if (isMatrix()) { + appendStr(" "); + appendInt(matrixCols); + appendStr("X"); + appendInt(matrixRows); + appendStr(" matrix of"); + } else if (isVector()) { + appendStr(" "); + appendInt(vectorSize); + appendStr("-component vector of"); + } + + appendStr(" "); + typeString.append(getBasicTypeString()); + + if (qualifier.builtIn != EbvNone) { + appendStr(" "); + appendStr(getBuiltInVariableString()); + } + + // Add struct/block members + if (isStruct() && structure) { + appendStr("{"); + bool hasHiddenMember = true; + for (size_t i = 0; i < structure->size(); ++i) { + if (! (*structure)[i].type->hiddenMember()) { + if (!hasHiddenMember) + appendStr(", "); + typeString.append((*structure)[i].type->getCompleteString()); + typeString.append(" "); + typeString.append((*structure)[i].type->getFieldName()); + hasHiddenMember = false; + } + } + appendStr("}"); + } + + return typeString; + } + + TString getBasicTypeString() const + { + if (basicType == EbtSampler) + return sampler.getString(); + else + return getBasicString(); + } + + const char* getStorageQualifierString() const { return GetStorageQualifierString(qualifier.storage); } + const char* getBuiltInVariableString() const { return GetBuiltInVariableString(qualifier.builtIn); } + const char* getPrecisionQualifierString() const { return GetPrecisionQualifierString(qualifier.precision); } +#endif + + const TTypeList* getStruct() const { assert(isStruct()); return structure; } + void setStruct(TTypeList* s) { assert(isStruct()); structure = s; } + TTypeList* getWritableStruct() const { assert(isStruct()); return structure; } // This should only be used when known to not be sharing with other threads + void setBasicType(const TBasicType& t) { basicType = t; } + + int computeNumComponents() const + { + int components = 0; + + if (getBasicType() == EbtStruct || getBasicType() == EbtBlock) { + for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++) + components += ((*tl).type)->computeNumComponents(); + } else if (matrixCols) + components = matrixCols * matrixRows; + else + components = vectorSize; + + if (arraySizes != nullptr) { + components *= arraySizes->getCumulativeSize(); + } + + return components; + } + + // append this type's mangled name to the passed in 'name' + void appendMangledName(TString& name) const + { + buildMangledName(name); + name += ';' ; + } + + // Do two structure types match? They could be declared independently, + // in different places, but still might satisfy the definition of matching. + // From the spec: + // + // "Structures must have the same name, sequence of type names, and + // type definitions, and member names to be considered the same type. + // This rule applies recursively for nested or embedded types." + // + bool sameStructType(const TType& right) const + { + // Most commonly, they are both nullptr, or the same pointer to the same actual structure + if ((!isStruct() && !right.isStruct()) || + (isStruct() && right.isStruct() && structure == right.structure)) + return true; + + // Both being nullptr was caught above, now they both have to be structures of the same number of elements + if (!isStruct() || !right.isStruct() || + structure->size() != right.structure->size()) + return false; + + // Structure names have to match + if (*typeName != *right.typeName) + return false; + + // Compare the names and types of all the members, which have to match + for (unsigned int i = 0; i < structure->size(); ++i) { + if ((*structure)[i].type->getFieldName() != (*right.structure)[i].type->getFieldName()) + return false; + + if (*(*structure)[i].type != *(*right.structure)[i].type) + return false; + } + + return true; + } + + bool sameReferenceType(const TType& right) const + { + if (isReference() != right.isReference()) + return false; + + if (!isReference() && !right.isReference()) + return true; + + assert(referentType != nullptr); + assert(right.referentType != nullptr); + + if (referentType == right.referentType) + return true; + + return *referentType == *right.referentType; + } + + // See if two types match, in all aspects except arrayness + bool sameElementType(const TType& right) const + { + return basicType == right.basicType && sameElementShape(right); + } + + // See if two type's arrayness match + bool sameArrayness(const TType& right) const + { + return ((arraySizes == nullptr && right.arraySizes == nullptr) || + (arraySizes != nullptr && right.arraySizes != nullptr && *arraySizes == *right.arraySizes)); + } + + // See if two type's arrayness match in everything except their outer dimension + bool sameInnerArrayness(const TType& right) const + { + assert(arraySizes != nullptr && right.arraySizes != nullptr); + return arraySizes->sameInnerArrayness(*right.arraySizes); + } + + // See if two type's parameters match + bool sameTypeParameters(const TType& right) const + { + return ((typeParameters == nullptr && right.typeParameters == nullptr) || + (typeParameters != nullptr && right.typeParameters != nullptr && *typeParameters == *right.typeParameters)); + } + + // See if two type's elements match in all ways except basic type + bool sameElementShape(const TType& right) const + { + return sampler == right.sampler && + vectorSize == right.vectorSize && + matrixCols == right.matrixCols && + matrixRows == right.matrixRows && + vector1 == right.vector1 && + isCoopMat() == right.isCoopMat() && + sameStructType(right) && + sameReferenceType(right); + } + + // See if a cooperative matrix type parameter with unspecified parameters is + // an OK function parameter + bool coopMatParameterOK(const TType& right) const + { + return isCoopMat() && right.isCoopMat() && (getBasicType() == right.getBasicType()) && + typeParameters == nullptr && right.typeParameters != nullptr; + } + + bool sameCoopMatBaseType(const TType &right) const { + bool rv = coopmat && right.coopmat; + if (getBasicType() == EbtFloat || getBasicType() == EbtFloat16) + rv = right.getBasicType() == EbtFloat || right.getBasicType() == EbtFloat16; + else if (getBasicType() == EbtUint || getBasicType() == EbtUint8) + rv = right.getBasicType() == EbtUint || right.getBasicType() == EbtUint8; + else if (getBasicType() == EbtInt || getBasicType() == EbtInt8) + rv = right.getBasicType() == EbtInt || right.getBasicType() == EbtInt8; + else + rv = false; + return rv; + } + + + // See if two types match in all ways (just the actual type, not qualification) + bool operator==(const TType& right) const + { + return sameElementType(right) && sameArrayness(right) && sameTypeParameters(right); + } + + bool operator!=(const TType& right) const + { + return ! operator==(right); + } + + unsigned int getBufferReferenceAlignment() const + { +#ifndef GLSLANG_WEB + if (getBasicType() == glslang::EbtReference) { + return getReferentType()->getQualifier().hasBufferReferenceAlign() ? + (1u << getReferentType()->getQualifier().layoutBufferReferenceAlign) : 16u; + } +#endif + return 0; + } + +protected: + // Require consumer to pick between deep copy and shallow copy. + TType(const TType& type); + TType& operator=(const TType& type); + + // Recursively copy a type graph, while preserving the graph-like + // quality. That is, don't make more than one copy of a structure that + // gets reused multiple times in the type graph. + void deepCopy(const TType& copyOf, TMap& copiedMap) + { + shallowCopy(copyOf); + + if (copyOf.arraySizes) { + arraySizes = new TArraySizes; + *arraySizes = *copyOf.arraySizes; + } + + if (copyOf.typeParameters) { + typeParameters = new TArraySizes; + *typeParameters = *copyOf.typeParameters; + } + + if (copyOf.isStruct() && copyOf.structure) { + auto prevCopy = copiedMap.find(copyOf.structure); + if (prevCopy != copiedMap.end()) + structure = prevCopy->second; + else { + structure = new TTypeList; + copiedMap[copyOf.structure] = structure; + for (unsigned int i = 0; i < copyOf.structure->size(); ++i) { + TTypeLoc typeLoc; + typeLoc.loc = (*copyOf.structure)[i].loc; + typeLoc.type = new TType(); + typeLoc.type->deepCopy(*(*copyOf.structure)[i].type, copiedMap); + structure->push_back(typeLoc); + } + } + } + + if (copyOf.fieldName) + fieldName = NewPoolTString(copyOf.fieldName->c_str()); + if (copyOf.typeName) + typeName = NewPoolTString(copyOf.typeName->c_str()); + } + + + void buildMangledName(TString&) const; + + TBasicType basicType : 8; + int vectorSize : 4; // 1 means either scalar or 1-component vector; see vector1 to disambiguate. + int matrixCols : 4; + int matrixRows : 4; + bool vector1 : 1; // Backward-compatible tracking of a 1-component vector distinguished from a scalar. + // GLSL 4.5 never has a 1-component vector; so this will always be false until such + // functionality is added. + // HLSL does have a 1-component vectors, so this will be true to disambiguate + // from a scalar. + bool coopmat : 1; + TQualifier qualifier; + + TArraySizes* arraySizes; // nullptr unless an array; can be shared across types + // A type can't be both a structure (EbtStruct/EbtBlock) and a reference (EbtReference), so + // conserve space by making these a union + union { + TTypeList* structure; // invalid unless this is a struct; can be shared across types + TType *referentType; // invalid unless this is an EbtReference + }; + TString *fieldName; // for structure field names + TString *typeName; // for structure type name + TSampler sampler; + TArraySizes* typeParameters;// nullptr unless a parameterized type; can be shared across types +}; + +} // end namespace glslang + +#endif // _TYPES_INCLUDED_ diff --git a/android/arm64-v8a/include/glslang/glslang/Include/arrays.h b/android/arm64-v8a/include/glslang/glslang/Include/arrays.h new file mode 100644 index 00000000..7f047d9f --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/Include/arrays.h @@ -0,0 +1,341 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +// +// Implement types for tracking GLSL arrays, arrays of arrays, etc. +// + +#ifndef _ARRAYS_INCLUDED +#define _ARRAYS_INCLUDED + +#include + +namespace glslang { + +// This is used to mean there is no size yet (unsized), it is waiting to get a size from somewhere else. +const int UnsizedArraySize = 0; + +class TIntermTyped; +extern bool SameSpecializationConstants(TIntermTyped*, TIntermTyped*); + +// Specialization constants need both a nominal size and a node that defines +// the specialization constant being used. Array types are the same when their +// size and specialization constant nodes are the same. +struct TArraySize { + unsigned int size; + TIntermTyped* node; // nullptr means no specialization constant node + bool operator==(const TArraySize& rhs) const + { + if (size != rhs.size) + return false; + if (node == nullptr || rhs.node == nullptr) + return node == rhs.node; + + return SameSpecializationConstants(node, rhs.node); + } +}; + +// +// TSmallArrayVector is used as the container for the set of sizes in TArraySizes. +// It has generic-container semantics, while TArraySizes has array-of-array semantics. +// That is, TSmallArrayVector should be more focused on mechanism and TArraySizes on policy. +// +struct TSmallArrayVector { + // + // TODO: memory: TSmallArrayVector is intended to be smaller. + // Almost all arrays could be handled by two sizes each fitting + // in 16 bits, needing a real vector only in the cases where there + // are more than 3 sizes or a size needing more than 16 bits. + // + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + TSmallArrayVector() : sizes(nullptr) { } + virtual ~TSmallArrayVector() { dealloc(); } + + // For breaking into two non-shared copies, independently modifiable. + TSmallArrayVector& operator=(const TSmallArrayVector& from) + { + if (from.sizes == nullptr) + sizes = nullptr; + else { + alloc(); + *sizes = *from.sizes; + } + + return *this; + } + + int size() const + { + if (sizes == nullptr) + return 0; + return (int)sizes->size(); + } + + unsigned int frontSize() const + { + assert(sizes != nullptr && sizes->size() > 0); + return sizes->front().size; + } + + TIntermTyped* frontNode() const + { + assert(sizes != nullptr && sizes->size() > 0); + return sizes->front().node; + } + + void changeFront(unsigned int s) + { + assert(sizes != nullptr); + // this should only happen for implicitly sized arrays, not specialization constants + assert(sizes->front().node == nullptr); + sizes->front().size = s; + } + + void push_back(unsigned int e, TIntermTyped* n) + { + alloc(); + TArraySize pair = { e, n }; + sizes->push_back(pair); + } + + void push_back(const TSmallArrayVector& newDims) + { + alloc(); + sizes->insert(sizes->end(), newDims.sizes->begin(), newDims.sizes->end()); + } + + void pop_front() + { + assert(sizes != nullptr && sizes->size() > 0); + if (sizes->size() == 1) + dealloc(); + else + sizes->erase(sizes->begin()); + } + + // 'this' should currently not be holding anything, and copyNonFront + // will make it hold a copy of all but the first element of rhs. + // (This would be useful for making a type that is dereferenced by + // one dimension.) + void copyNonFront(const TSmallArrayVector& rhs) + { + assert(sizes == nullptr); + if (rhs.size() > 1) { + alloc(); + sizes->insert(sizes->begin(), rhs.sizes->begin() + 1, rhs.sizes->end()); + } + } + + unsigned int getDimSize(int i) const + { + assert(sizes != nullptr && (int)sizes->size() > i); + return (*sizes)[i].size; + } + + void setDimSize(int i, unsigned int size) const + { + assert(sizes != nullptr && (int)sizes->size() > i); + assert((*sizes)[i].node == nullptr); + (*sizes)[i].size = size; + } + + TIntermTyped* getDimNode(int i) const + { + assert(sizes != nullptr && (int)sizes->size() > i); + return (*sizes)[i].node; + } + + bool operator==(const TSmallArrayVector& rhs) const + { + if (sizes == nullptr && rhs.sizes == nullptr) + return true; + if (sizes == nullptr || rhs.sizes == nullptr) + return false; + return *sizes == *rhs.sizes; + } + bool operator!=(const TSmallArrayVector& rhs) const { return ! operator==(rhs); } + +protected: + TSmallArrayVector(const TSmallArrayVector&); + + void alloc() + { + if (sizes == nullptr) + sizes = new TVector; + } + void dealloc() + { + delete sizes; + sizes = nullptr; + } + + TVector* sizes; // will either hold such a pointer, or in the future, hold the two array sizes +}; + +// +// Represent an array, or array of arrays, to arbitrary depth. This is not +// done through a hierarchy of types in a type tree, rather all contiguous arrayness +// in the type hierarchy is localized into this single cumulative object. +// +// The arrayness in TTtype is a pointer, so that it can be non-allocated and zero +// for the vast majority of types that are non-array types. +// +// Order Policy: these are all identical: +// - left to right order within a contiguous set of ...[..][..][..]... in the source language +// - index order 0, 1, 2, ... within the 'sizes' member below +// - outer-most to inner-most +// +struct TArraySizes { + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + TArraySizes() : implicitArraySize(1), variablyIndexed(false) { } + + // For breaking into two non-shared copies, independently modifiable. + TArraySizes& operator=(const TArraySizes& from) + { + implicitArraySize = from.implicitArraySize; + variablyIndexed = from.variablyIndexed; + sizes = from.sizes; + + return *this; + } + + // translate from array-of-array semantics to container semantics + int getNumDims() const { return sizes.size(); } + int getDimSize(int dim) const { return sizes.getDimSize(dim); } + TIntermTyped* getDimNode(int dim) const { return sizes.getDimNode(dim); } + void setDimSize(int dim, int size) { sizes.setDimSize(dim, size); } + int getOuterSize() const { return sizes.frontSize(); } + TIntermTyped* getOuterNode() const { return sizes.frontNode(); } + int getCumulativeSize() const + { + int size = 1; + for (int d = 0; d < sizes.size(); ++d) { + // this only makes sense in paths that have a known array size + assert(sizes.getDimSize(d) != UnsizedArraySize); + size *= sizes.getDimSize(d); + } + return size; + } + void addInnerSize() { addInnerSize((unsigned)UnsizedArraySize); } + void addInnerSize(int s) { addInnerSize((unsigned)s, nullptr); } + void addInnerSize(int s, TIntermTyped* n) { sizes.push_back((unsigned)s, n); } + void addInnerSize(TArraySize pair) { + sizes.push_back(pair.size, pair.node); + } + void addInnerSizes(const TArraySizes& s) { sizes.push_back(s.sizes); } + void changeOuterSize(int s) { sizes.changeFront((unsigned)s); } + int getImplicitSize() const { return implicitArraySize; } + void updateImplicitSize(int s) { implicitArraySize = std::max(implicitArraySize, s); } + bool isInnerUnsized() const + { + for (int d = 1; d < sizes.size(); ++d) { + if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize) + return true; + } + + return false; + } + bool clearInnerUnsized() + { + for (int d = 1; d < sizes.size(); ++d) { + if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize) + setDimSize(d, 1); + } + + return false; + } + bool isInnerSpecialization() const + { + for (int d = 1; d < sizes.size(); ++d) { + if (sizes.getDimNode(d) != nullptr) + return true; + } + + return false; + } + bool isOuterSpecialization() + { + return sizes.getDimNode(0) != nullptr; + } + + bool hasUnsized() const { return getOuterSize() == UnsizedArraySize || isInnerUnsized(); } + bool isSized() const { return getOuterSize() != UnsizedArraySize; } + void dereference() { sizes.pop_front(); } + void copyDereferenced(const TArraySizes& rhs) + { + assert(sizes.size() == 0); + if (rhs.sizes.size() > 1) + sizes.copyNonFront(rhs.sizes); + } + + bool sameInnerArrayness(const TArraySizes& rhs) const + { + if (sizes.size() != rhs.sizes.size()) + return false; + + for (int d = 1; d < sizes.size(); ++d) { + if (sizes.getDimSize(d) != rhs.sizes.getDimSize(d) || + sizes.getDimNode(d) != rhs.sizes.getDimNode(d)) + return false; + } + + return true; + } + + void setVariablyIndexed() { variablyIndexed = true; } + bool isVariablyIndexed() const { return variablyIndexed; } + + bool operator==(const TArraySizes& rhs) const { return sizes == rhs.sizes; } + bool operator!=(const TArraySizes& rhs) const { return sizes != rhs.sizes; } + +protected: + TSmallArrayVector sizes; + + TArraySizes(const TArraySizes&); + + // For tracking maximum referenced compile-time constant index. + // Applies only to the outer-most dimension. Potentially becomes + // the implicit size of the array, if not variably indexed and + // otherwise legal. + int implicitArraySize; + bool variablyIndexed; // true if array is indexed with a non compile-time constant +}; + +} // end namespace glslang + +#endif // _ARRAYS_INCLUDED_ diff --git a/android/arm64-v8a/include/glslang/glslang/Include/glslang_c_interface.h b/android/arm64-v8a/include/glslang/glslang/Include/glslang_c_interface.h new file mode 100644 index 00000000..5a450e0e --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/Include/glslang_c_interface.h @@ -0,0 +1,232 @@ +/** + This code is based on the glslang_c_interface implementation by Viktor Latypov +**/ + +/** +BSD 2-Clause License + +Copyright (c) 2019, Viktor Latypov +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**/ + +#ifndef GLSLANG_C_IFACE_H_INCLUDED +#define GLSLANG_C_IFACE_H_INCLUDED + +#include +#include + +#include "glslang_c_shader_types.h" + +typedef struct glslang_shader_s glslang_shader_t; +typedef struct glslang_program_s glslang_program_t; + +/* TLimits counterpart */ +typedef struct glslang_limits_s { + bool non_inductive_for_loops; + bool while_loops; + bool do_while_loops; + bool general_uniform_indexing; + bool general_attribute_matrix_vector_indexing; + bool general_varying_indexing; + bool general_sampler_indexing; + bool general_variable_indexing; + bool general_constant_matrix_vector_indexing; +} glslang_limits_t; + +/* TBuiltInResource counterpart */ +typedef struct glslang_resource_s { + int max_lights; + int max_clip_planes; + int max_texture_units; + int max_texture_coords; + int max_vertex_attribs; + int max_vertex_uniform_components; + int max_varying_floats; + int max_vertex_texture_image_units; + int max_combined_texture_image_units; + int max_texture_image_units; + int max_fragment_uniform_components; + int max_draw_buffers; + int max_vertex_uniform_vectors; + int max_varying_vectors; + int max_fragment_uniform_vectors; + int max_vertex_output_vectors; + int max_fragment_input_vectors; + int min_program_texel_offset; + int max_program_texel_offset; + int max_clip_distances; + int max_compute_work_group_count_x; + int max_compute_work_group_count_y; + int max_compute_work_group_count_z; + int max_compute_work_group_size_x; + int max_compute_work_group_size_y; + int max_compute_work_group_size_z; + int max_compute_uniform_components; + int max_compute_texture_image_units; + int max_compute_image_uniforms; + int max_compute_atomic_counters; + int max_compute_atomic_counter_buffers; + int max_varying_components; + int max_vertex_output_components; + int max_geometry_input_components; + int max_geometry_output_components; + int max_fragment_input_components; + int max_image_units; + int max_combined_image_units_and_fragment_outputs; + int max_combined_shader_output_resources; + int max_image_samples; + int max_vertex_image_uniforms; + int max_tess_control_image_uniforms; + int max_tess_evaluation_image_uniforms; + int max_geometry_image_uniforms; + int max_fragment_image_uniforms; + int max_combined_image_uniforms; + int max_geometry_texture_image_units; + int max_geometry_output_vertices; + int max_geometry_total_output_components; + int max_geometry_uniform_components; + int max_geometry_varying_components; + int max_tess_control_input_components; + int max_tess_control_output_components; + int max_tess_control_texture_image_units; + int max_tess_control_uniform_components; + int max_tess_control_total_output_components; + int max_tess_evaluation_input_components; + int max_tess_evaluation_output_components; + int max_tess_evaluation_texture_image_units; + int max_tess_evaluation_uniform_components; + int max_tess_patch_components; + int max_patch_vertices; + int max_tess_gen_level; + int max_viewports; + int max_vertex_atomic_counters; + int max_tess_control_atomic_counters; + int max_tess_evaluation_atomic_counters; + int max_geometry_atomic_counters; + int max_fragment_atomic_counters; + int max_combined_atomic_counters; + int max_atomic_counter_bindings; + int max_vertex_atomic_counter_buffers; + int max_tess_control_atomic_counter_buffers; + int max_tess_evaluation_atomic_counter_buffers; + int max_geometry_atomic_counter_buffers; + int max_fragment_atomic_counter_buffers; + int max_combined_atomic_counter_buffers; + int max_atomic_counter_buffer_size; + int max_transform_feedback_buffers; + int max_transform_feedback_interleaved_components; + int max_cull_distances; + int max_combined_clip_and_cull_distances; + int max_samples; + int max_mesh_output_vertices_nv; + int max_mesh_output_primitives_nv; + int max_mesh_work_group_size_x_nv; + int max_mesh_work_group_size_y_nv; + int max_mesh_work_group_size_z_nv; + int max_task_work_group_size_x_nv; + int max_task_work_group_size_y_nv; + int max_task_work_group_size_z_nv; + int max_mesh_view_count_nv; + + glslang_limits_t limits; +} glslang_resource_t; + +typedef struct glslang_input_s { + glslang_source_t language; + glslang_stage_t stage; + glslang_client_t client; + glslang_target_client_version_t client_version; + glslang_target_language_t target_language; + glslang_target_language_version_t target_language_version; + /** Shader source code */ + const char* code; + int default_version; + glslang_profile_t default_profile; + int force_default_version_and_profile; + int forward_compatible; + glslang_messages_t messages; + const glslang_resource_t* resource; +} glslang_input_t; + +/* Inclusion result structure allocated by C include_local/include_system callbacks */ +typedef struct glsl_include_result_s { + /* Header file name or NULL if inclusion failed */ + const char* header_name; + + /* Header contents or NULL */ + const char* header_data; + size_t header_length; + +} glsl_include_result_t; + +/* Callback for local file inclusion */ +typedef glsl_include_result_t* (*glsl_include_local_func)(void* ctx, const char* header_name, const char* includer_name, + size_t include_depth); + +/* Callback for system file inclusion */ +typedef glsl_include_result_t* (*glsl_include_system_func)(void* ctx, const char* header_name, + const char* includer_name, size_t include_depth); + +/* Callback for include result destruction */ +typedef int (*glsl_free_include_result_func)(void* ctx, glsl_include_result_t* result); + +/* Collection of callbacks for GLSL preprocessor */ +typedef struct glsl_include_callbacks_s { + glsl_include_system_func include_system; + glsl_include_local_func include_local; + glsl_free_include_result_func free_include_result; +} glsl_include_callbacks_t; + +#ifdef __cplusplus +extern "C" { +#endif + +int glslang_initialize_process(); +void glslang_finalize_process(); + +glslang_shader_t* glslang_shader_create(const glslang_input_t* input); +void glslang_shader_delete(glslang_shader_t* shader); +int glslang_shader_preprocess(glslang_shader_t* shader, const glslang_input_t* input); +int glslang_shader_parse(glslang_shader_t* shader, const glslang_input_t* input); +const char* glslang_shader_get_preprocessed_code(glslang_shader_t* shader); +const char* glslang_shader_get_info_log(glslang_shader_t* shader); +const char* glslang_shader_get_info_debug_log(glslang_shader_t* shader); + +glslang_program_t* glslang_program_create(); +void glslang_program_delete(glslang_program_t* program); +void glslang_program_add_shader(glslang_program_t* program, glslang_shader_t* shader); +int glslang_program_link(glslang_program_t* program, int messages); // glslang_messages_t +void glslang_program_SPIRV_generate(glslang_program_t* program, glslang_stage_t stage); +size_t glslang_program_SPIRV_get_size(glslang_program_t* program); +void glslang_program_SPIRV_get(glslang_program_t* program, unsigned int*); +unsigned int* glslang_program_SPIRV_get_ptr(glslang_program_t* program); +const char* glslang_program_SPIRV_get_messages(glslang_program_t* program); +const char* glslang_program_get_info_log(glslang_program_t* program); +const char* glslang_program_get_info_debug_log(glslang_program_t* program); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifdef GLSLANG_C_IFACE_INCLUDED */ diff --git a/android/arm64-v8a/include/glslang/glslang/Include/glslang_c_shader_types.h b/android/arm64-v8a/include/glslang/glslang/Include/glslang_c_shader_types.h new file mode 100644 index 00000000..769f4c4a --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/Include/glslang_c_shader_types.h @@ -0,0 +1,182 @@ +/** + This code is based on the glslang_c_interface implementation by Viktor Latypov +**/ + +/** +BSD 2-Clause License + +Copyright (c) 2019, Viktor Latypov +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**/ + +#ifndef C_SHADER_TYPES_H_INCLUDED +#define C_SHADER_TYPES_H_INCLUDED + +#define LAST_ELEMENT_MARKER(x) x + +/* EShLanguage counterpart */ +typedef enum { + GLSLANG_STAGE_VERTEX, + GLSLANG_STAGE_TESSCONTROL, + GLSLANG_STAGE_TESSEVALUATION, + GLSLANG_STAGE_GEOMETRY, + GLSLANG_STAGE_FRAGMENT, + GLSLANG_STAGE_COMPUTE, + GLSLANG_STAGE_RAYGEN_NV, + GLSLANG_STAGE_INTERSECT_NV, + GLSLANG_STAGE_ANYHIT_NV, + GLSLANG_STAGE_CLOSESTHIT_NV, + GLSLANG_STAGE_MISS_NV, + GLSLANG_STAGE_CALLABLE_NV, + GLSLANG_STAGE_TASK_NV, + GLSLANG_STAGE_MESH_NV, + LAST_ELEMENT_MARKER(GLSLANG_STAGE_COUNT), +} glslang_stage_t; // would be better as stage, but this is ancient now + +/* EShLanguageMask counterpart */ +typedef enum { + GLSLANG_STAGE_VERTEX_MASK = (1 << GLSLANG_STAGE_VERTEX), + GLSLANG_STAGE_TESSCONTROL_MASK = (1 << GLSLANG_STAGE_TESSCONTROL), + GLSLANG_STAGE_TESSEVALUATION_MASK = (1 << GLSLANG_STAGE_TESSEVALUATION), + GLSLANG_STAGE_GEOMETRY_MASK = (1 << GLSLANG_STAGE_GEOMETRY), + GLSLANG_STAGE_FRAGMENT_MASK = (1 << GLSLANG_STAGE_FRAGMENT), + GLSLANG_STAGE_COMPUTE_MASK = (1 << GLSLANG_STAGE_COMPUTE), + GLSLANG_STAGE_RAYGEN_NV_MASK = (1 << GLSLANG_STAGE_RAYGEN_NV), + GLSLANG_STAGE_INTERSECT_NV_MASK = (1 << GLSLANG_STAGE_INTERSECT_NV), + GLSLANG_STAGE_ANYHIT_NV_MASK = (1 << GLSLANG_STAGE_ANYHIT_NV), + GLSLANG_STAGE_CLOSESTHIT_NV_MASK = (1 << GLSLANG_STAGE_CLOSESTHIT_NV), + GLSLANG_STAGE_MISS_NV_MASK = (1 << GLSLANG_STAGE_MISS_NV), + GLSLANG_STAGE_CALLABLE_NV_MASK = (1 << GLSLANG_STAGE_CALLABLE_NV), + GLSLANG_STAGE_TASK_NV_MASK = (1 << GLSLANG_STAGE_TASK_NV), + GLSLANG_STAGE_MESH_NV_MASK = (1 << GLSLANG_STAGE_MESH_NV), + LAST_ELEMENT_MARKER(GLSLANG_STAGE_MASK_COUNT), +} glslang_stage_mask_t; + +/* EShSource counterpart */ +typedef enum { + GLSLANG_SOURCE_NONE, + GLSLANG_SOURCE_GLSL, + GLSLANG_SOURCE_HLSL, + LAST_ELEMENT_MARKER(GLSLANG_SOURCE_COUNT), +} glslang_source_t; + +/* EShClient counterpart */ +typedef enum { + GLSLANG_CLIENT_NONE, + GLSLANG_CLIENT_VULKAN, + GLSLANG_CLIENT_OPENGL, + LAST_ELEMENT_MARKER(GLSLANG_CLIENT_COUNT), +} glslang_client_t; + +/* EShTargetLanguage counterpart */ +typedef enum { + GLSLANG_TARGET_NONE, + GLSLANG_TARGET_SPV, + LAST_ELEMENT_MARKER(GLSLANG_TARGET_COUNT), +} glslang_target_language_t; + +/* SH_TARGET_ClientVersion counterpart */ +typedef enum { + GLSLANG_TARGET_VULKAN_1_0 = (1 << 22), + GLSLANG_TARGET_VULKAN_1_1 = (1 << 22) | (1 << 12), + GLSLANG_TARGET_OPENGL_450 = 450, + LAST_ELEMENT_MARKER(GLSLANG_TARGET_CLIENT_VERSION_COUNT), +} glslang_target_client_version_t; + +/* SH_TARGET_LanguageVersion counterpart */ +typedef enum { + GLSLANG_TARGET_SPV_1_0 = (1 << 16), + GLSLANG_TARGET_SPV_1_1 = (1 << 16) | (1 << 8), + GLSLANG_TARGET_SPV_1_2 = (1 << 16) | (2 << 8), + GLSLANG_TARGET_SPV_1_3 = (1 << 16) | (3 << 8), + GLSLANG_TARGET_SPV_1_4 = (1 << 16) | (4 << 8), + GLSLANG_TARGET_SPV_1_5 = (1 << 16) | (5 << 8), + LAST_ELEMENT_MARKER(GLSLANG_TARGET_LANGUAGE_VERSION_COUNT), +} glslang_target_language_version_t; + +/* EShExecutable counterpart */ +typedef enum { GLSLANG_EX_VERTEX_FRAGMENT, GLSLANG_EX_FRAGMENT } glslang_executable_t; + +/* EShOptimizationLevel counterpart */ +typedef enum { + GLSLANG_OPT_NO_GENERATION, + GLSLANG_OPT_NONE, + GLSLANG_OPT_SIMPLE, + GLSLANG_OPT_FULL, + LAST_ELEMENT_MARKER(GLSLANG_OPT_LEVEL_COUNT), +} glslang_optimization_level_t; + +/* EShTextureSamplerTransformMode counterpart */ +typedef enum { + GLSLANG_TEX_SAMP_TRANS_KEEP, + GLSLANG_TEX_SAMP_TRANS_UPGRADE_TEXTURE_REMOVE_SAMPLER, + LAST_ELEMENT_MARKER(GLSLANG_TEX_SAMP_TRANS_COUNT), +} glslang_texture_sampler_transform_mode_t; + +/* EShMessages counterpart */ +typedef enum { + GLSLANG_MSG_DEFAULT_BIT = 0, + GLSLANG_MSG_RELAXED_ERRORS_BIT = (1 << 0), + GLSLANG_MSG_SUPPRESS_WARNINGS_BIT = (1 << 1), + GLSLANG_MSG_AST_BIT = (1 << 2), + GLSLANG_MSG_SPV_RULES_BIT = (1 << 3), + GLSLANG_MSG_VULKAN_RULES_BIT = (1 << 4), + GLSLANG_MSG_ONLY_PREPROCESSOR_BIT = (1 << 5), + GLSLANG_MSG_READ_HLSL_BIT = (1 << 6), + GLSLANG_MSG_CASCADING_ERRORS_BIT = (1 << 7), + GLSLANG_MSG_KEEP_UNCALLED_BIT = (1 << 8), + GLSLANG_MSG_HLSL_OFFSETS_BIT = (1 << 9), + GLSLANG_MSG_DEBUG_INFO_BIT = (1 << 10), + GLSLANG_MSG_HLSL_ENABLE_16BIT_TYPES_BIT = (1 << 11), + GLSLANG_MSG_HLSL_LEGALIZATION_BIT = (1 << 12), + GLSLANG_MSG_HLSL_DX9_COMPATIBLE_BIT = (1 << 13), + GLSLANG_MSG_BUILTIN_SYMBOL_TABLE_BIT = (1 << 14), + LAST_ELEMENT_MARKER(GLSLANG_MSG_COUNT), +} glslang_messages_t; + +/* EShReflectionOptions counterpart */ +typedef enum { + GLSLANG_REFLECTION_DEFAULT_BIT = 0, + GLSLANG_REFLECTION_STRICT_ARRAY_SUFFIX_BIT = (1 << 0), + GLSLANG_REFLECTION_BASIC_ARRAY_SUFFIX_BIT = (1 << 1), + GLSLANG_REFLECTION_INTERMEDIATE_IOO_BIT = (1 << 2), + GLSLANG_REFLECTION_SEPARATE_BUFFERS_BIT = (1 << 3), + GLSLANG_REFLECTION_ALL_BLOCK_VARIABLES_BIT = (1 << 4), + GLSLANG_REFLECTION_UNWRAP_IO_BLOCKS_BIT = (1 << 5), + LAST_ELEMENT_MARKER(GLSLANG_REFLECTION_COUNT), +} glslang_reflection_options_t; + +/* EProfile counterpart (from Versions.h) */ +typedef enum { + GLSLANG_BAD_PROFILE = 0, + GLSLANG_NO_PROFILE = (1 << 0), + GLSLANG_CORE_PROFILE = (1 << 1), + GLSLANG_COMPATIBILITY_PROFILE = (1 << 2), + GLSLANG_ES_PROFILE = (1 << 3), + LAST_ELEMENT_MARKER(GLSLANG_PROFILE_COUNT), +} glslang_profile_t; + +#undef LAST_ELEMENT_MARKER + +#endif diff --git a/android/arm64-v8a/include/glslang/glslang/Include/intermediate.h b/android/arm64-v8a/include/glslang/glslang/Include/intermediate.h new file mode 100644 index 00000000..bf12fcf8 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/Include/intermediate.h @@ -0,0 +1,1805 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2016 LunarG, Inc. +// Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +// +// Definition of the in-memory high-level intermediate representation +// of shaders. This is a tree that parser creates. +// +// Nodes in the tree are defined as a hierarchy of classes derived from +// TIntermNode. Each is a node in a tree. There is no preset branching factor; +// each node can have it's own type of list of children. +// + +#ifndef __INTERMEDIATE_H +#define __INTERMEDIATE_H + +#if defined(_MSC_VER) && _MSC_VER >= 1900 + #pragma warning(disable : 4464) // relative include path contains '..' + #pragma warning(disable : 5026) // 'glslang::TIntermUnary': move constructor was implicitly defined as deleted +#endif + +#include "../Include/Common.h" +#include "../Include/Types.h" +#include "../Include/ConstantUnion.h" + +namespace glslang { + +class TIntermediate; + +// +// Operators used by the high-level (parse tree) representation. +// +enum TOperator { + EOpNull, // if in a node, should only mean a node is still being built + EOpSequence, // denotes a list of statements, or parameters, etc. + EOpLinkerObjects, // for aggregate node of objects the linker may need, if not reference by the rest of the AST + EOpFunctionCall, + EOpFunction, // For function definition + EOpParameters, // an aggregate listing the parameters to a function + + // + // Unary operators + // + + EOpNegative, + EOpLogicalNot, + EOpVectorLogicalNot, + EOpBitwiseNot, + + EOpPostIncrement, + EOpPostDecrement, + EOpPreIncrement, + EOpPreDecrement, + + EOpCopyObject, + + // (u)int* -> bool + EOpConvInt8ToBool, + EOpConvUint8ToBool, + EOpConvInt16ToBool, + EOpConvUint16ToBool, + EOpConvIntToBool, + EOpConvUintToBool, + EOpConvInt64ToBool, + EOpConvUint64ToBool, + + // float* -> bool + EOpConvFloat16ToBool, + EOpConvFloatToBool, + EOpConvDoubleToBool, + + // bool -> (u)int* + EOpConvBoolToInt8, + EOpConvBoolToUint8, + EOpConvBoolToInt16, + EOpConvBoolToUint16, + EOpConvBoolToInt, + EOpConvBoolToUint, + EOpConvBoolToInt64, + EOpConvBoolToUint64, + + // bool -> float* + EOpConvBoolToFloat16, + EOpConvBoolToFloat, + EOpConvBoolToDouble, + + // int8_t -> (u)int* + EOpConvInt8ToInt16, + EOpConvInt8ToInt, + EOpConvInt8ToInt64, + EOpConvInt8ToUint8, + EOpConvInt8ToUint16, + EOpConvInt8ToUint, + EOpConvInt8ToUint64, + + // uint8_t -> (u)int* + EOpConvUint8ToInt8, + EOpConvUint8ToInt16, + EOpConvUint8ToInt, + EOpConvUint8ToInt64, + EOpConvUint8ToUint16, + EOpConvUint8ToUint, + EOpConvUint8ToUint64, + + // int8_t -> float* + EOpConvInt8ToFloat16, + EOpConvInt8ToFloat, + EOpConvInt8ToDouble, + + // uint8_t -> float* + EOpConvUint8ToFloat16, + EOpConvUint8ToFloat, + EOpConvUint8ToDouble, + + // int16_t -> (u)int* + EOpConvInt16ToInt8, + EOpConvInt16ToInt, + EOpConvInt16ToInt64, + EOpConvInt16ToUint8, + EOpConvInt16ToUint16, + EOpConvInt16ToUint, + EOpConvInt16ToUint64, + + // uint16_t -> (u)int* + EOpConvUint16ToInt8, + EOpConvUint16ToInt16, + EOpConvUint16ToInt, + EOpConvUint16ToInt64, + EOpConvUint16ToUint8, + EOpConvUint16ToUint, + EOpConvUint16ToUint64, + + // int16_t -> float* + EOpConvInt16ToFloat16, + EOpConvInt16ToFloat, + EOpConvInt16ToDouble, + + // uint16_t -> float* + EOpConvUint16ToFloat16, + EOpConvUint16ToFloat, + EOpConvUint16ToDouble, + + // int32_t -> (u)int* + EOpConvIntToInt8, + EOpConvIntToInt16, + EOpConvIntToInt64, + EOpConvIntToUint8, + EOpConvIntToUint16, + EOpConvIntToUint, + EOpConvIntToUint64, + + // uint32_t -> (u)int* + EOpConvUintToInt8, + EOpConvUintToInt16, + EOpConvUintToInt, + EOpConvUintToInt64, + EOpConvUintToUint8, + EOpConvUintToUint16, + EOpConvUintToUint64, + + // int32_t -> float* + EOpConvIntToFloat16, + EOpConvIntToFloat, + EOpConvIntToDouble, + + // uint32_t -> float* + EOpConvUintToFloat16, + EOpConvUintToFloat, + EOpConvUintToDouble, + + // int64_t -> (u)int* + EOpConvInt64ToInt8, + EOpConvInt64ToInt16, + EOpConvInt64ToInt, + EOpConvInt64ToUint8, + EOpConvInt64ToUint16, + EOpConvInt64ToUint, + EOpConvInt64ToUint64, + + // uint64_t -> (u)int* + EOpConvUint64ToInt8, + EOpConvUint64ToInt16, + EOpConvUint64ToInt, + EOpConvUint64ToInt64, + EOpConvUint64ToUint8, + EOpConvUint64ToUint16, + EOpConvUint64ToUint, + + // int64_t -> float* + EOpConvInt64ToFloat16, + EOpConvInt64ToFloat, + EOpConvInt64ToDouble, + + // uint64_t -> float* + EOpConvUint64ToFloat16, + EOpConvUint64ToFloat, + EOpConvUint64ToDouble, + + // float16_t -> (u)int* + EOpConvFloat16ToInt8, + EOpConvFloat16ToInt16, + EOpConvFloat16ToInt, + EOpConvFloat16ToInt64, + EOpConvFloat16ToUint8, + EOpConvFloat16ToUint16, + EOpConvFloat16ToUint, + EOpConvFloat16ToUint64, + + // float16_t -> float* + EOpConvFloat16ToFloat, + EOpConvFloat16ToDouble, + + // float -> (u)int* + EOpConvFloatToInt8, + EOpConvFloatToInt16, + EOpConvFloatToInt, + EOpConvFloatToInt64, + EOpConvFloatToUint8, + EOpConvFloatToUint16, + EOpConvFloatToUint, + EOpConvFloatToUint64, + + // float -> float* + EOpConvFloatToFloat16, + EOpConvFloatToDouble, + + // float64 _t-> (u)int* + EOpConvDoubleToInt8, + EOpConvDoubleToInt16, + EOpConvDoubleToInt, + EOpConvDoubleToInt64, + EOpConvDoubleToUint8, + EOpConvDoubleToUint16, + EOpConvDoubleToUint, + EOpConvDoubleToUint64, + + // float64_t -> float* + EOpConvDoubleToFloat16, + EOpConvDoubleToFloat, + + // uint64_t <-> pointer + EOpConvUint64ToPtr, + EOpConvPtrToUint64, + + // uvec2 <-> pointer + EOpConvUvec2ToPtr, + EOpConvPtrToUvec2, + + // + // binary operations + // + + EOpAdd, + EOpSub, + EOpMul, + EOpDiv, + EOpMod, + EOpRightShift, + EOpLeftShift, + EOpAnd, + EOpInclusiveOr, + EOpExclusiveOr, + EOpEqual, + EOpNotEqual, + EOpVectorEqual, + EOpVectorNotEqual, + EOpLessThan, + EOpGreaterThan, + EOpLessThanEqual, + EOpGreaterThanEqual, + EOpComma, + + EOpVectorTimesScalar, + EOpVectorTimesMatrix, + EOpMatrixTimesVector, + EOpMatrixTimesScalar, + + EOpLogicalOr, + EOpLogicalXor, + EOpLogicalAnd, + + EOpIndexDirect, + EOpIndexIndirect, + EOpIndexDirectStruct, + + EOpVectorSwizzle, + + EOpMethod, + EOpScoping, + + // + // Built-in functions mapped to operators + // + + EOpRadians, + EOpDegrees, + EOpSin, + EOpCos, + EOpTan, + EOpAsin, + EOpAcos, + EOpAtan, + EOpSinh, + EOpCosh, + EOpTanh, + EOpAsinh, + EOpAcosh, + EOpAtanh, + + EOpPow, + EOpExp, + EOpLog, + EOpExp2, + EOpLog2, + EOpSqrt, + EOpInverseSqrt, + + EOpAbs, + EOpSign, + EOpFloor, + EOpTrunc, + EOpRound, + EOpRoundEven, + EOpCeil, + EOpFract, + EOpModf, + EOpMin, + EOpMax, + EOpClamp, + EOpMix, + EOpStep, + EOpSmoothStep, + + EOpIsNan, + EOpIsInf, + + EOpFma, + + EOpFrexp, + EOpLdexp, + + EOpFloatBitsToInt, + EOpFloatBitsToUint, + EOpIntBitsToFloat, + EOpUintBitsToFloat, + EOpDoubleBitsToInt64, + EOpDoubleBitsToUint64, + EOpInt64BitsToDouble, + EOpUint64BitsToDouble, + EOpFloat16BitsToInt16, + EOpFloat16BitsToUint16, + EOpInt16BitsToFloat16, + EOpUint16BitsToFloat16, + EOpPackSnorm2x16, + EOpUnpackSnorm2x16, + EOpPackUnorm2x16, + EOpUnpackUnorm2x16, + EOpPackSnorm4x8, + EOpUnpackSnorm4x8, + EOpPackUnorm4x8, + EOpUnpackUnorm4x8, + EOpPackHalf2x16, + EOpUnpackHalf2x16, + EOpPackDouble2x32, + EOpUnpackDouble2x32, + EOpPackInt2x32, + EOpUnpackInt2x32, + EOpPackUint2x32, + EOpUnpackUint2x32, + EOpPackFloat2x16, + EOpUnpackFloat2x16, + EOpPackInt2x16, + EOpUnpackInt2x16, + EOpPackUint2x16, + EOpUnpackUint2x16, + EOpPackInt4x16, + EOpUnpackInt4x16, + EOpPackUint4x16, + EOpUnpackUint4x16, + EOpPack16, + EOpPack32, + EOpPack64, + EOpUnpack32, + EOpUnpack16, + EOpUnpack8, + + EOpLength, + EOpDistance, + EOpDot, + EOpCross, + EOpNormalize, + EOpFaceForward, + EOpReflect, + EOpRefract, + + EOpMin3, + EOpMax3, + EOpMid3, + + EOpDPdx, // Fragment only + EOpDPdy, // Fragment only + EOpFwidth, // Fragment only + EOpDPdxFine, // Fragment only + EOpDPdyFine, // Fragment only + EOpFwidthFine, // Fragment only + EOpDPdxCoarse, // Fragment only + EOpDPdyCoarse, // Fragment only + EOpFwidthCoarse, // Fragment only + + EOpInterpolateAtCentroid, // Fragment only + EOpInterpolateAtSample, // Fragment only + EOpInterpolateAtOffset, // Fragment only + EOpInterpolateAtVertex, + + EOpMatrixTimesMatrix, + EOpOuterProduct, + EOpDeterminant, + EOpMatrixInverse, + EOpTranspose, + + EOpFtransform, + + EOpNoise, + + EOpEmitVertex, // geometry only + EOpEndPrimitive, // geometry only + EOpEmitStreamVertex, // geometry only + EOpEndStreamPrimitive, // geometry only + + EOpBarrier, + EOpMemoryBarrier, + EOpMemoryBarrierAtomicCounter, + EOpMemoryBarrierBuffer, + EOpMemoryBarrierImage, + EOpMemoryBarrierShared, // compute only + EOpGroupMemoryBarrier, // compute only + + EOpBallot, + EOpReadInvocation, + EOpReadFirstInvocation, + + EOpAnyInvocation, + EOpAllInvocations, + EOpAllInvocationsEqual, + + EOpSubgroupGuardStart, + EOpSubgroupBarrier, + EOpSubgroupMemoryBarrier, + EOpSubgroupMemoryBarrierBuffer, + EOpSubgroupMemoryBarrierImage, + EOpSubgroupMemoryBarrierShared, // compute only + EOpSubgroupElect, + EOpSubgroupAll, + EOpSubgroupAny, + EOpSubgroupAllEqual, + EOpSubgroupBroadcast, + EOpSubgroupBroadcastFirst, + EOpSubgroupBallot, + EOpSubgroupInverseBallot, + EOpSubgroupBallotBitExtract, + EOpSubgroupBallotBitCount, + EOpSubgroupBallotInclusiveBitCount, + EOpSubgroupBallotExclusiveBitCount, + EOpSubgroupBallotFindLSB, + EOpSubgroupBallotFindMSB, + EOpSubgroupShuffle, + EOpSubgroupShuffleXor, + EOpSubgroupShuffleUp, + EOpSubgroupShuffleDown, + EOpSubgroupAdd, + EOpSubgroupMul, + EOpSubgroupMin, + EOpSubgroupMax, + EOpSubgroupAnd, + EOpSubgroupOr, + EOpSubgroupXor, + EOpSubgroupInclusiveAdd, + EOpSubgroupInclusiveMul, + EOpSubgroupInclusiveMin, + EOpSubgroupInclusiveMax, + EOpSubgroupInclusiveAnd, + EOpSubgroupInclusiveOr, + EOpSubgroupInclusiveXor, + EOpSubgroupExclusiveAdd, + EOpSubgroupExclusiveMul, + EOpSubgroupExclusiveMin, + EOpSubgroupExclusiveMax, + EOpSubgroupExclusiveAnd, + EOpSubgroupExclusiveOr, + EOpSubgroupExclusiveXor, + EOpSubgroupClusteredAdd, + EOpSubgroupClusteredMul, + EOpSubgroupClusteredMin, + EOpSubgroupClusteredMax, + EOpSubgroupClusteredAnd, + EOpSubgroupClusteredOr, + EOpSubgroupClusteredXor, + EOpSubgroupQuadBroadcast, + EOpSubgroupQuadSwapHorizontal, + EOpSubgroupQuadSwapVertical, + EOpSubgroupQuadSwapDiagonal, + + EOpSubgroupPartition, + EOpSubgroupPartitionedAdd, + EOpSubgroupPartitionedMul, + EOpSubgroupPartitionedMin, + EOpSubgroupPartitionedMax, + EOpSubgroupPartitionedAnd, + EOpSubgroupPartitionedOr, + EOpSubgroupPartitionedXor, + EOpSubgroupPartitionedInclusiveAdd, + EOpSubgroupPartitionedInclusiveMul, + EOpSubgroupPartitionedInclusiveMin, + EOpSubgroupPartitionedInclusiveMax, + EOpSubgroupPartitionedInclusiveAnd, + EOpSubgroupPartitionedInclusiveOr, + EOpSubgroupPartitionedInclusiveXor, + EOpSubgroupPartitionedExclusiveAdd, + EOpSubgroupPartitionedExclusiveMul, + EOpSubgroupPartitionedExclusiveMin, + EOpSubgroupPartitionedExclusiveMax, + EOpSubgroupPartitionedExclusiveAnd, + EOpSubgroupPartitionedExclusiveOr, + EOpSubgroupPartitionedExclusiveXor, + + EOpSubgroupGuardStop, + + EOpMinInvocations, + EOpMaxInvocations, + EOpAddInvocations, + EOpMinInvocationsNonUniform, + EOpMaxInvocationsNonUniform, + EOpAddInvocationsNonUniform, + EOpMinInvocationsInclusiveScan, + EOpMaxInvocationsInclusiveScan, + EOpAddInvocationsInclusiveScan, + EOpMinInvocationsInclusiveScanNonUniform, + EOpMaxInvocationsInclusiveScanNonUniform, + EOpAddInvocationsInclusiveScanNonUniform, + EOpMinInvocationsExclusiveScan, + EOpMaxInvocationsExclusiveScan, + EOpAddInvocationsExclusiveScan, + EOpMinInvocationsExclusiveScanNonUniform, + EOpMaxInvocationsExclusiveScanNonUniform, + EOpAddInvocationsExclusiveScanNonUniform, + EOpSwizzleInvocations, + EOpSwizzleInvocationsMasked, + EOpWriteInvocation, + EOpMbcnt, + + EOpCubeFaceIndex, + EOpCubeFaceCoord, + EOpTime, + + EOpAtomicAdd, + EOpAtomicMin, + EOpAtomicMax, + EOpAtomicAnd, + EOpAtomicOr, + EOpAtomicXor, + EOpAtomicExchange, + EOpAtomicCompSwap, + EOpAtomicLoad, + EOpAtomicStore, + + EOpAtomicCounterIncrement, // results in pre-increment value + EOpAtomicCounterDecrement, // results in post-decrement value + EOpAtomicCounter, + EOpAtomicCounterAdd, + EOpAtomicCounterSubtract, + EOpAtomicCounterMin, + EOpAtomicCounterMax, + EOpAtomicCounterAnd, + EOpAtomicCounterOr, + EOpAtomicCounterXor, + EOpAtomicCounterExchange, + EOpAtomicCounterCompSwap, + + EOpAny, + EOpAll, + + EOpCooperativeMatrixLoad, + EOpCooperativeMatrixStore, + EOpCooperativeMatrixMulAdd, + + EOpBeginInvocationInterlock, // Fragment only + EOpEndInvocationInterlock, // Fragment only + + EOpIsHelperInvocation, + + EOpDebugPrintf, + + // + // Branch + // + + EOpKill, // Fragment only + EOpReturn, + EOpBreak, + EOpContinue, + EOpCase, + EOpDefault, + EOpDemote, // Fragment only + + // + // Constructors + // + + EOpConstructGuardStart, + EOpConstructInt, // these first scalar forms also identify what implicit conversion is needed + EOpConstructUint, + EOpConstructInt8, + EOpConstructUint8, + EOpConstructInt16, + EOpConstructUint16, + EOpConstructInt64, + EOpConstructUint64, + EOpConstructBool, + EOpConstructFloat, + EOpConstructDouble, + // Keep vector and matrix constructors in a consistent relative order for + // TParseContext::constructBuiltIn, which converts between 8/16/32 bit + // vector constructors + EOpConstructVec2, + EOpConstructVec3, + EOpConstructVec4, + EOpConstructMat2x2, + EOpConstructMat2x3, + EOpConstructMat2x4, + EOpConstructMat3x2, + EOpConstructMat3x3, + EOpConstructMat3x4, + EOpConstructMat4x2, + EOpConstructMat4x3, + EOpConstructMat4x4, + EOpConstructDVec2, + EOpConstructDVec3, + EOpConstructDVec4, + EOpConstructBVec2, + EOpConstructBVec3, + EOpConstructBVec4, + EOpConstructI8Vec2, + EOpConstructI8Vec3, + EOpConstructI8Vec4, + EOpConstructU8Vec2, + EOpConstructU8Vec3, + EOpConstructU8Vec4, + EOpConstructI16Vec2, + EOpConstructI16Vec3, + EOpConstructI16Vec4, + EOpConstructU16Vec2, + EOpConstructU16Vec3, + EOpConstructU16Vec4, + EOpConstructIVec2, + EOpConstructIVec3, + EOpConstructIVec4, + EOpConstructUVec2, + EOpConstructUVec3, + EOpConstructUVec4, + EOpConstructI64Vec2, + EOpConstructI64Vec3, + EOpConstructI64Vec4, + EOpConstructU64Vec2, + EOpConstructU64Vec3, + EOpConstructU64Vec4, + EOpConstructDMat2x2, + EOpConstructDMat2x3, + EOpConstructDMat2x4, + EOpConstructDMat3x2, + EOpConstructDMat3x3, + EOpConstructDMat3x4, + EOpConstructDMat4x2, + EOpConstructDMat4x3, + EOpConstructDMat4x4, + EOpConstructIMat2x2, + EOpConstructIMat2x3, + EOpConstructIMat2x4, + EOpConstructIMat3x2, + EOpConstructIMat3x3, + EOpConstructIMat3x4, + EOpConstructIMat4x2, + EOpConstructIMat4x3, + EOpConstructIMat4x4, + EOpConstructUMat2x2, + EOpConstructUMat2x3, + EOpConstructUMat2x4, + EOpConstructUMat3x2, + EOpConstructUMat3x3, + EOpConstructUMat3x4, + EOpConstructUMat4x2, + EOpConstructUMat4x3, + EOpConstructUMat4x4, + EOpConstructBMat2x2, + EOpConstructBMat2x3, + EOpConstructBMat2x4, + EOpConstructBMat3x2, + EOpConstructBMat3x3, + EOpConstructBMat3x4, + EOpConstructBMat4x2, + EOpConstructBMat4x3, + EOpConstructBMat4x4, + EOpConstructFloat16, + EOpConstructF16Vec2, + EOpConstructF16Vec3, + EOpConstructF16Vec4, + EOpConstructF16Mat2x2, + EOpConstructF16Mat2x3, + EOpConstructF16Mat2x4, + EOpConstructF16Mat3x2, + EOpConstructF16Mat3x3, + EOpConstructF16Mat3x4, + EOpConstructF16Mat4x2, + EOpConstructF16Mat4x3, + EOpConstructF16Mat4x4, + EOpConstructStruct, + EOpConstructTextureSampler, + EOpConstructNonuniform, // expected to be transformed away, not present in final AST + EOpConstructReference, + EOpConstructCooperativeMatrix, + EOpConstructGuardEnd, + + // + // moves + // + + EOpAssign, + EOpAddAssign, + EOpSubAssign, + EOpMulAssign, + EOpVectorTimesMatrixAssign, + EOpVectorTimesScalarAssign, + EOpMatrixTimesScalarAssign, + EOpMatrixTimesMatrixAssign, + EOpDivAssign, + EOpModAssign, + EOpAndAssign, + EOpInclusiveOrAssign, + EOpExclusiveOrAssign, + EOpLeftShiftAssign, + EOpRightShiftAssign, + + // + // Array operators + // + + // Can apply to arrays, vectors, or matrices. + // Can be decomposed to a constant at compile time, but this does not always happen, + // due to link-time effects. So, consumer can expect either a link-time sized or + // run-time sized array. + EOpArrayLength, + + // + // Image operations + // + + EOpImageGuardBegin, + + EOpImageQuerySize, + EOpImageQuerySamples, + EOpImageLoad, + EOpImageStore, + EOpImageLoadLod, + EOpImageStoreLod, + EOpImageAtomicAdd, + EOpImageAtomicMin, + EOpImageAtomicMax, + EOpImageAtomicAnd, + EOpImageAtomicOr, + EOpImageAtomicXor, + EOpImageAtomicExchange, + EOpImageAtomicCompSwap, + EOpImageAtomicLoad, + EOpImageAtomicStore, + + EOpSubpassLoad, + EOpSubpassLoadMS, + EOpSparseImageLoad, + EOpSparseImageLoadLod, + + EOpImageGuardEnd, + + // + // Texture operations + // + + EOpTextureGuardBegin, + + EOpTextureQuerySize, + EOpTextureQueryLod, + EOpTextureQueryLevels, + EOpTextureQuerySamples, + + EOpSamplingGuardBegin, + + EOpTexture, + EOpTextureProj, + EOpTextureLod, + EOpTextureOffset, + EOpTextureFetch, + EOpTextureFetchOffset, + EOpTextureProjOffset, + EOpTextureLodOffset, + EOpTextureProjLod, + EOpTextureProjLodOffset, + EOpTextureGrad, + EOpTextureGradOffset, + EOpTextureProjGrad, + EOpTextureProjGradOffset, + EOpTextureGather, + EOpTextureGatherOffset, + EOpTextureGatherOffsets, + EOpTextureClamp, + EOpTextureOffsetClamp, + EOpTextureGradClamp, + EOpTextureGradOffsetClamp, + EOpTextureGatherLod, + EOpTextureGatherLodOffset, + EOpTextureGatherLodOffsets, + EOpFragmentMaskFetch, + EOpFragmentFetch, + + EOpSparseTextureGuardBegin, + + EOpSparseTexture, + EOpSparseTextureLod, + EOpSparseTextureOffset, + EOpSparseTextureFetch, + EOpSparseTextureFetchOffset, + EOpSparseTextureLodOffset, + EOpSparseTextureGrad, + EOpSparseTextureGradOffset, + EOpSparseTextureGather, + EOpSparseTextureGatherOffset, + EOpSparseTextureGatherOffsets, + EOpSparseTexelsResident, + EOpSparseTextureClamp, + EOpSparseTextureOffsetClamp, + EOpSparseTextureGradClamp, + EOpSparseTextureGradOffsetClamp, + EOpSparseTextureGatherLod, + EOpSparseTextureGatherLodOffset, + EOpSparseTextureGatherLodOffsets, + + EOpSparseTextureGuardEnd, + + EOpImageFootprintGuardBegin, + EOpImageSampleFootprintNV, + EOpImageSampleFootprintClampNV, + EOpImageSampleFootprintLodNV, + EOpImageSampleFootprintGradNV, + EOpImageSampleFootprintGradClampNV, + EOpImageFootprintGuardEnd, + EOpSamplingGuardEnd, + EOpTextureGuardEnd, + + // + // Integer operations + // + + EOpAddCarry, + EOpSubBorrow, + EOpUMulExtended, + EOpIMulExtended, + EOpBitfieldExtract, + EOpBitfieldInsert, + EOpBitFieldReverse, + EOpBitCount, + EOpFindLSB, + EOpFindMSB, + + EOpCountLeadingZeros, + EOpCountTrailingZeros, + EOpAbsDifference, + EOpAddSaturate, + EOpSubSaturate, + EOpAverage, + EOpAverageRounded, + EOpMul32x16, + + EOpTrace, + EOpReportIntersection, + EOpIgnoreIntersection, + EOpTerminateRay, + EOpExecuteCallable, + EOpWritePackedPrimitiveIndices4x8NV, + + // + // GL_EXT_ray_query operations + // + + EOpRayQueryInitialize, + EOpRayQueryTerminate, + EOpRayQueryGenerateIntersection, + EOpRayQueryConfirmIntersection, + EOpRayQueryProceed, + EOpRayQueryGetIntersectionType, + EOpRayQueryGetRayTMin, + EOpRayQueryGetRayFlags, + EOpRayQueryGetIntersectionT, + EOpRayQueryGetIntersectionInstanceCustomIndex, + EOpRayQueryGetIntersectionInstanceId, + EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset, + EOpRayQueryGetIntersectionGeometryIndex, + EOpRayQueryGetIntersectionPrimitiveIndex, + EOpRayQueryGetIntersectionBarycentrics, + EOpRayQueryGetIntersectionFrontFace, + EOpRayQueryGetIntersectionCandidateAABBOpaque, + EOpRayQueryGetIntersectionObjectRayDirection, + EOpRayQueryGetIntersectionObjectRayOrigin, + EOpRayQueryGetWorldRayDirection, + EOpRayQueryGetWorldRayOrigin, + EOpRayQueryGetIntersectionObjectToWorld, + EOpRayQueryGetIntersectionWorldToObject, + + // + // HLSL operations + // + + EOpClip, // discard if input value < 0 + EOpIsFinite, + EOpLog10, // base 10 log + EOpRcp, // 1/x + EOpSaturate, // clamp from 0 to 1 + EOpSinCos, // sin and cos in out parameters + EOpGenMul, // mul(x,y) on any of mat/vec/scalars + EOpDst, // x = 1, y=src0.y * src1.y, z=src0.z, w=src1.w + EOpInterlockedAdd, // atomic ops, but uses [optional] out arg instead of return + EOpInterlockedAnd, // ... + EOpInterlockedCompareExchange, // ... + EOpInterlockedCompareStore, // ... + EOpInterlockedExchange, // ... + EOpInterlockedMax, // ... + EOpInterlockedMin, // ... + EOpInterlockedOr, // ... + EOpInterlockedXor, // ... + EOpAllMemoryBarrierWithGroupSync, // memory barriers without non-hlsl AST equivalents + EOpDeviceMemoryBarrier, // ... + EOpDeviceMemoryBarrierWithGroupSync, // ... + EOpWorkgroupMemoryBarrier, // ... + EOpWorkgroupMemoryBarrierWithGroupSync, // ... + EOpEvaluateAttributeSnapped, // InterpolateAtOffset with int position on 16x16 grid + EOpF32tof16, // HLSL conversion: half of a PackHalf2x16 + EOpF16tof32, // HLSL conversion: half of an UnpackHalf2x16 + EOpLit, // HLSL lighting coefficient vector + EOpTextureBias, // HLSL texture bias: will be lowered to EOpTexture + EOpAsDouble, // slightly different from EOpUint64BitsToDouble + EOpD3DCOLORtoUBYTE4, // convert and swizzle 4-component color to UBYTE4 range + + EOpMethodSample, // Texture object methods. These are translated to existing + EOpMethodSampleBias, // AST methods, and exist to represent HLSL semantics until that + EOpMethodSampleCmp, // translation is performed. See HlslParseContext::decomposeSampleMethods(). + EOpMethodSampleCmpLevelZero, // ... + EOpMethodSampleGrad, // ... + EOpMethodSampleLevel, // ... + EOpMethodLoad, // ... + EOpMethodGetDimensions, // ... + EOpMethodGetSamplePosition, // ... + EOpMethodGather, // ... + EOpMethodCalculateLevelOfDetail, // ... + EOpMethodCalculateLevelOfDetailUnclamped, // ... + + // Load already defined above for textures + EOpMethodLoad2, // Structure buffer object methods. These are translated to existing + EOpMethodLoad3, // AST methods, and exist to represent HLSL semantics until that + EOpMethodLoad4, // translation is performed. See HlslParseContext::decomposeSampleMethods(). + EOpMethodStore, // ... + EOpMethodStore2, // ... + EOpMethodStore3, // ... + EOpMethodStore4, // ... + EOpMethodIncrementCounter, // ... + EOpMethodDecrementCounter, // ... + // EOpMethodAppend is defined for geo shaders below + EOpMethodConsume, + + // SM5 texture methods + EOpMethodGatherRed, // These are covered under the above EOpMethodSample comment about + EOpMethodGatherGreen, // translation to existing AST opcodes. They exist temporarily + EOpMethodGatherBlue, // because HLSL arguments are slightly different. + EOpMethodGatherAlpha, // ... + EOpMethodGatherCmp, // ... + EOpMethodGatherCmpRed, // ... + EOpMethodGatherCmpGreen, // ... + EOpMethodGatherCmpBlue, // ... + EOpMethodGatherCmpAlpha, // ... + + // geometry methods + EOpMethodAppend, // Geometry shader methods + EOpMethodRestartStrip, // ... + + // matrix + EOpMatrixSwizzle, // select multiple matrix components (non-column) + + // SM6 wave ops + EOpWaveGetLaneCount, // Will decompose to gl_SubgroupSize. + EOpWaveGetLaneIndex, // Will decompose to gl_SubgroupInvocationID. + EOpWaveActiveCountBits, // Will decompose to subgroupBallotBitCount(subgroupBallot()). + EOpWavePrefixCountBits, // Will decompose to subgroupBallotInclusiveBitCount(subgroupBallot()). + + // Shader Clock Ops + EOpReadClockSubgroupKHR, + EOpReadClockDeviceKHR, +}; + +class TIntermTraverser; +class TIntermOperator; +class TIntermAggregate; +class TIntermUnary; +class TIntermBinary; +class TIntermConstantUnion; +class TIntermSelection; +class TIntermSwitch; +class TIntermBranch; +class TIntermTyped; +class TIntermMethod; +class TIntermSymbol; +class TIntermLoop; + +} // end namespace glslang + +// +// Base class for the tree nodes +// +// (Put outside the glslang namespace, as it's used as part of the external interface.) +// +class TIntermNode { +public: + POOL_ALLOCATOR_NEW_DELETE(glslang::GetThreadPoolAllocator()) + + TIntermNode() { loc.init(); } + virtual const glslang::TSourceLoc& getLoc() const { return loc; } + virtual void setLoc(const glslang::TSourceLoc& l) { loc = l; } + virtual void traverse(glslang::TIntermTraverser*) = 0; + virtual glslang::TIntermTyped* getAsTyped() { return 0; } + virtual glslang::TIntermOperator* getAsOperator() { return 0; } + virtual glslang::TIntermConstantUnion* getAsConstantUnion() { return 0; } + virtual glslang::TIntermAggregate* getAsAggregate() { return 0; } + virtual glslang::TIntermUnary* getAsUnaryNode() { return 0; } + virtual glslang::TIntermBinary* getAsBinaryNode() { return 0; } + virtual glslang::TIntermSelection* getAsSelectionNode() { return 0; } + virtual glslang::TIntermSwitch* getAsSwitchNode() { return 0; } + virtual glslang::TIntermMethod* getAsMethodNode() { return 0; } + virtual glslang::TIntermSymbol* getAsSymbolNode() { return 0; } + virtual glslang::TIntermBranch* getAsBranchNode() { return 0; } + virtual glslang::TIntermLoop* getAsLoopNode() { return 0; } + + virtual const glslang::TIntermTyped* getAsTyped() const { return 0; } + virtual const glslang::TIntermOperator* getAsOperator() const { return 0; } + virtual const glslang::TIntermConstantUnion* getAsConstantUnion() const { return 0; } + virtual const glslang::TIntermAggregate* getAsAggregate() const { return 0; } + virtual const glslang::TIntermUnary* getAsUnaryNode() const { return 0; } + virtual const glslang::TIntermBinary* getAsBinaryNode() const { return 0; } + virtual const glslang::TIntermSelection* getAsSelectionNode() const { return 0; } + virtual const glslang::TIntermSwitch* getAsSwitchNode() const { return 0; } + virtual const glslang::TIntermMethod* getAsMethodNode() const { return 0; } + virtual const glslang::TIntermSymbol* getAsSymbolNode() const { return 0; } + virtual const glslang::TIntermBranch* getAsBranchNode() const { return 0; } + virtual const glslang::TIntermLoop* getAsLoopNode() const { return 0; } + virtual ~TIntermNode() { } + +protected: + TIntermNode(const TIntermNode&); + TIntermNode& operator=(const TIntermNode&); + glslang::TSourceLoc loc; +}; + +namespace glslang { + +// +// This is just to help yacc. +// +struct TIntermNodePair { + TIntermNode* node1; + TIntermNode* node2; +}; + +// +// Intermediate class for nodes that have a type. +// +class TIntermTyped : public TIntermNode { +public: + TIntermTyped(const TType& t) { type.shallowCopy(t); } + TIntermTyped(TBasicType basicType) { TType bt(basicType); type.shallowCopy(bt); } + virtual TIntermTyped* getAsTyped() { return this; } + virtual const TIntermTyped* getAsTyped() const { return this; } + virtual void setType(const TType& t) { type.shallowCopy(t); } + virtual const TType& getType() const { return type; } + virtual TType& getWritableType() { return type; } + + virtual TBasicType getBasicType() const { return type.getBasicType(); } + virtual TQualifier& getQualifier() { return type.getQualifier(); } + virtual const TQualifier& getQualifier() const { return type.getQualifier(); } + virtual void propagatePrecision(TPrecisionQualifier); + virtual int getVectorSize() const { return type.getVectorSize(); } + virtual int getMatrixCols() const { return type.getMatrixCols(); } + virtual int getMatrixRows() const { return type.getMatrixRows(); } + virtual bool isMatrix() const { return type.isMatrix(); } + virtual bool isArray() const { return type.isArray(); } + virtual bool isVector() const { return type.isVector(); } + virtual bool isScalar() const { return type.isScalar(); } + virtual bool isStruct() const { return type.isStruct(); } + virtual bool isFloatingDomain() const { return type.isFloatingDomain(); } + virtual bool isIntegerDomain() const { return type.isIntegerDomain(); } + bool isAtomic() const { return type.isAtomic(); } + bool isReference() const { return type.isReference(); } + TString getCompleteString() const { return type.getCompleteString(); } + +protected: + TIntermTyped& operator=(const TIntermTyped&); + TType type; +}; + +// +// Handle for, do-while, and while loops. +// +class TIntermLoop : public TIntermNode { +public: + TIntermLoop(TIntermNode* aBody, TIntermTyped* aTest, TIntermTyped* aTerminal, bool testFirst) : + body(aBody), + test(aTest), + terminal(aTerminal), + first(testFirst), + unroll(false), + dontUnroll(false), + dependency(0), + minIterations(0), + maxIterations(iterationsInfinite), + iterationMultiple(1), + peelCount(0), + partialCount(0) + { } + + virtual TIntermLoop* getAsLoopNode() { return this; } + virtual const TIntermLoop* getAsLoopNode() const { return this; } + virtual void traverse(TIntermTraverser*); + TIntermNode* getBody() const { return body; } + TIntermTyped* getTest() const { return test; } + TIntermTyped* getTerminal() const { return terminal; } + bool testFirst() const { return first; } + + void setUnroll() { unroll = true; } + void setDontUnroll() { + dontUnroll = true; + peelCount = 0; + partialCount = 0; + } + bool getUnroll() const { return unroll; } + bool getDontUnroll() const { return dontUnroll; } + + static const unsigned int dependencyInfinite = 0xFFFFFFFF; + static const unsigned int iterationsInfinite = 0xFFFFFFFF; + void setLoopDependency(int d) { dependency = d; } + int getLoopDependency() const { return dependency; } + + void setMinIterations(unsigned int v) { minIterations = v; } + unsigned int getMinIterations() const { return minIterations; } + void setMaxIterations(unsigned int v) { maxIterations = v; } + unsigned int getMaxIterations() const { return maxIterations; } + void setIterationMultiple(unsigned int v) { iterationMultiple = v; } + unsigned int getIterationMultiple() const { return iterationMultiple; } + void setPeelCount(unsigned int v) { + peelCount = v; + dontUnroll = false; + } + unsigned int getPeelCount() const { return peelCount; } + void setPartialCount(unsigned int v) { + partialCount = v; + dontUnroll = false; + } + unsigned int getPartialCount() const { return partialCount; } + +protected: + TIntermNode* body; // code to loop over + TIntermTyped* test; // exit condition associated with loop, could be 0 for 'for' loops + TIntermTyped* terminal; // exists for for-loops + bool first; // true for while and for, not for do-while + bool unroll; // true if unroll requested + bool dontUnroll; // true if request to not unroll + unsigned int dependency; // loop dependency hint; 0 means not set or unknown + unsigned int minIterations; // as per the SPIR-V specification + unsigned int maxIterations; // as per the SPIR-V specification + unsigned int iterationMultiple; // as per the SPIR-V specification + unsigned int peelCount; // as per the SPIR-V specification + unsigned int partialCount; // as per the SPIR-V specification +}; + +// +// Handle case, break, continue, return, and kill. +// +class TIntermBranch : public TIntermNode { +public: + TIntermBranch(TOperator op, TIntermTyped* e) : + flowOp(op), + expression(e) { } + virtual TIntermBranch* getAsBranchNode() { return this; } + virtual const TIntermBranch* getAsBranchNode() const { return this; } + virtual void traverse(TIntermTraverser*); + TOperator getFlowOp() const { return flowOp; } + TIntermTyped* getExpression() const { return expression; } + void setExpression(TIntermTyped* pExpression) { expression = pExpression; } +protected: + TOperator flowOp; + TIntermTyped* expression; +}; + +// +// Represent method names before seeing their calling signature +// or resolving them to operations. Just an expression as the base object +// and a textural name. +// +class TIntermMethod : public TIntermTyped { +public: + TIntermMethod(TIntermTyped* o, const TType& t, const TString& m) : TIntermTyped(t), object(o), method(m) { } + virtual TIntermMethod* getAsMethodNode() { return this; } + virtual const TIntermMethod* getAsMethodNode() const { return this; } + virtual const TString& getMethodName() const { return method; } + virtual TIntermTyped* getObject() const { return object; } + virtual void traverse(TIntermTraverser*); +protected: + TIntermTyped* object; + TString method; +}; + +// +// Nodes that correspond to symbols or constants in the source code. +// +class TIntermSymbol : public TIntermTyped { +public: + // if symbol is initialized as symbol(sym), the memory comes from the pool allocator of sym. If sym comes from + // per process threadPoolAllocator, then it causes increased memory usage per compile + // it is essential to use "symbol = sym" to assign to symbol + TIntermSymbol(int i, const TString& n, const TType& t) + : TIntermTyped(t), id(i), +#ifndef GLSLANG_WEB + flattenSubset(-1), +#endif + constSubtree(nullptr) + { name = n; } + virtual int getId() const { return id; } + virtual void changeId(int i) { id = i; } + virtual const TString& getName() const { return name; } + virtual void traverse(TIntermTraverser*); + virtual TIntermSymbol* getAsSymbolNode() { return this; } + virtual const TIntermSymbol* getAsSymbolNode() const { return this; } + void setConstArray(const TConstUnionArray& c) { constArray = c; } + const TConstUnionArray& getConstArray() const { return constArray; } + void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; } + TIntermTyped* getConstSubtree() const { return constSubtree; } +#ifndef GLSLANG_WEB + void setFlattenSubset(int subset) { flattenSubset = subset; } + int getFlattenSubset() const { return flattenSubset; } // -1 means full object +#endif + + // This is meant for cases where a node has already been constructed, and + // later on, it becomes necessary to switch to a different symbol. + virtual void switchId(int newId) { id = newId; } + +protected: + int id; // the unique id of the symbol this node represents +#ifndef GLSLANG_WEB + int flattenSubset; // how deeply the flattened object rooted at id has been dereferenced +#endif + TString name; // the name of the symbol this node represents + TConstUnionArray constArray; // if the symbol is a front-end compile-time constant, this is its value + TIntermTyped* constSubtree; +}; + +class TIntermConstantUnion : public TIntermTyped { +public: + TIntermConstantUnion(const TConstUnionArray& ua, const TType& t) : TIntermTyped(t), constArray(ua), literal(false) { } + const TConstUnionArray& getConstArray() const { return constArray; } + virtual TIntermConstantUnion* getAsConstantUnion() { return this; } + virtual const TIntermConstantUnion* getAsConstantUnion() const { return this; } + virtual void traverse(TIntermTraverser*); + virtual TIntermTyped* fold(TOperator, const TIntermTyped*) const; + virtual TIntermTyped* fold(TOperator, const TType&) const; + void setLiteral() { literal = true; } + void setExpression() { literal = false; } + bool isLiteral() const { return literal; } + +protected: + TIntermConstantUnion& operator=(const TIntermConstantUnion&); + + const TConstUnionArray constArray; + bool literal; // true if node represents a literal in the source code +}; + +// Represent the independent aspects of a texturing TOperator +struct TCrackedTextureOp { + bool query; + bool proj; + bool lod; + bool fetch; + bool offset; + bool offsets; + bool gather; + bool grad; + bool subpass; + bool lodClamp; + bool fragMask; +}; + +// +// Intermediate class for node types that hold operators. +// +class TIntermOperator : public TIntermTyped { +public: + virtual TIntermOperator* getAsOperator() { return this; } + virtual const TIntermOperator* getAsOperator() const { return this; } + TOperator getOp() const { return op; } + void setOp(TOperator newOp) { op = newOp; } + bool modifiesState() const; + bool isConstructor() const; + bool isTexture() const { return op > EOpTextureGuardBegin && op < EOpTextureGuardEnd; } + bool isSampling() const { return op > EOpSamplingGuardBegin && op < EOpSamplingGuardEnd; } +#ifdef GLSLANG_WEB + bool isImage() const { return false; } + bool isSparseTexture() const { return false; } + bool isImageFootprint() const { return false; } + bool isSparseImage() const { return false; } + bool isSubgroup() const { return false; } +#else + bool isImage() const { return op > EOpImageGuardBegin && op < EOpImageGuardEnd; } + bool isSparseTexture() const { return op > EOpSparseTextureGuardBegin && op < EOpSparseTextureGuardEnd; } + bool isImageFootprint() const { return op > EOpImageFootprintGuardBegin && op < EOpImageFootprintGuardEnd; } + bool isSparseImage() const { return op == EOpSparseImageLoad; } + bool isSubgroup() const { return op > EOpSubgroupGuardStart && op < EOpSubgroupGuardStop; } +#endif + + void setOperationPrecision(TPrecisionQualifier p) { operationPrecision = p; } + TPrecisionQualifier getOperationPrecision() const { return operationPrecision != EpqNone ? + operationPrecision : + type.getQualifier().precision; } + TString getCompleteString() const + { + TString cs = type.getCompleteString(); + if (getOperationPrecision() != type.getQualifier().precision) { + cs += ", operation at "; + cs += GetPrecisionQualifierString(getOperationPrecision()); + } + + return cs; + } + + // Crack the op into the individual dimensions of texturing operation. + void crackTexture(TSampler sampler, TCrackedTextureOp& cracked) const + { + cracked.query = false; + cracked.proj = false; + cracked.lod = false; + cracked.fetch = false; + cracked.offset = false; + cracked.offsets = false; + cracked.gather = false; + cracked.grad = false; + cracked.subpass = false; + cracked.lodClamp = false; + cracked.fragMask = false; + + switch (op) { + case EOpImageQuerySize: + case EOpImageQuerySamples: + case EOpTextureQuerySize: + case EOpTextureQueryLod: + case EOpTextureQueryLevels: + case EOpTextureQuerySamples: + case EOpSparseTexelsResident: + cracked.query = true; + break; + case EOpTexture: + case EOpSparseTexture: + break; + case EOpTextureProj: + cracked.proj = true; + break; + case EOpTextureLod: + case EOpSparseTextureLod: + cracked.lod = true; + break; + case EOpTextureOffset: + case EOpSparseTextureOffset: + cracked.offset = true; + break; + case EOpTextureFetch: + case EOpSparseTextureFetch: + cracked.fetch = true; + if (sampler.is1D() || (sampler.dim == Esd2D && ! sampler.isMultiSample()) || sampler.dim == Esd3D) + cracked.lod = true; + break; + case EOpTextureFetchOffset: + case EOpSparseTextureFetchOffset: + cracked.fetch = true; + cracked.offset = true; + if (sampler.is1D() || (sampler.dim == Esd2D && ! sampler.isMultiSample()) || sampler.dim == Esd3D) + cracked.lod = true; + break; + case EOpTextureProjOffset: + cracked.offset = true; + cracked.proj = true; + break; + case EOpTextureLodOffset: + case EOpSparseTextureLodOffset: + cracked.offset = true; + cracked.lod = true; + break; + case EOpTextureProjLod: + cracked.lod = true; + cracked.proj = true; + break; + case EOpTextureProjLodOffset: + cracked.offset = true; + cracked.lod = true; + cracked.proj = true; + break; + case EOpTextureGrad: + case EOpSparseTextureGrad: + cracked.grad = true; + break; + case EOpTextureGradOffset: + case EOpSparseTextureGradOffset: + cracked.grad = true; + cracked.offset = true; + break; + case EOpTextureProjGrad: + cracked.grad = true; + cracked.proj = true; + break; + case EOpTextureProjGradOffset: + cracked.grad = true; + cracked.offset = true; + cracked.proj = true; + break; +#ifndef GLSLANG_WEB + case EOpTextureClamp: + case EOpSparseTextureClamp: + cracked.lodClamp = true; + break; + case EOpTextureOffsetClamp: + case EOpSparseTextureOffsetClamp: + cracked.offset = true; + cracked.lodClamp = true; + break; + case EOpTextureGradClamp: + case EOpSparseTextureGradClamp: + cracked.grad = true; + cracked.lodClamp = true; + break; + case EOpTextureGradOffsetClamp: + case EOpSparseTextureGradOffsetClamp: + cracked.grad = true; + cracked.offset = true; + cracked.lodClamp = true; + break; + case EOpTextureGather: + case EOpSparseTextureGather: + cracked.gather = true; + break; + case EOpTextureGatherOffset: + case EOpSparseTextureGatherOffset: + cracked.gather = true; + cracked.offset = true; + break; + case EOpTextureGatherOffsets: + case EOpSparseTextureGatherOffsets: + cracked.gather = true; + cracked.offsets = true; + break; + case EOpTextureGatherLod: + case EOpSparseTextureGatherLod: + cracked.gather = true; + cracked.lod = true; + break; + case EOpTextureGatherLodOffset: + case EOpSparseTextureGatherLodOffset: + cracked.gather = true; + cracked.offset = true; + cracked.lod = true; + break; + case EOpTextureGatherLodOffsets: + case EOpSparseTextureGatherLodOffsets: + cracked.gather = true; + cracked.offsets = true; + cracked.lod = true; + break; + case EOpImageLoadLod: + case EOpImageStoreLod: + case EOpSparseImageLoadLod: + cracked.lod = true; + break; + case EOpFragmentMaskFetch: + cracked.subpass = sampler.dim == EsdSubpass; + cracked.fragMask = true; + break; + case EOpFragmentFetch: + cracked.subpass = sampler.dim == EsdSubpass; + cracked.fragMask = true; + break; + case EOpImageSampleFootprintNV: + break; + case EOpImageSampleFootprintClampNV: + cracked.lodClamp = true; + break; + case EOpImageSampleFootprintLodNV: + cracked.lod = true; + break; + case EOpImageSampleFootprintGradNV: + cracked.grad = true; + break; + case EOpImageSampleFootprintGradClampNV: + cracked.lodClamp = true; + cracked.grad = true; + break; + case EOpSubpassLoad: + case EOpSubpassLoadMS: + cracked.subpass = true; + break; +#endif + default: + break; + } + } + +protected: + TIntermOperator(TOperator o) : TIntermTyped(EbtFloat), op(o), operationPrecision(EpqNone) {} + TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o), operationPrecision(EpqNone) {} + TOperator op; + // The result precision is in the inherited TType, and is usually meant to be both + // the operation precision and the result precision. However, some more complex things, + // like built-in function calls, distinguish between the two, in which case non-EqpNone + // 'operationPrecision' overrides the result precision as far as operation precision + // is concerned. + TPrecisionQualifier operationPrecision; +}; + +// +// Nodes for all the basic binary math operators. +// +class TIntermBinary : public TIntermOperator { +public: + TIntermBinary(TOperator o) : TIntermOperator(o) {} + virtual void traverse(TIntermTraverser*); + virtual void setLeft(TIntermTyped* n) { left = n; } + virtual void setRight(TIntermTyped* n) { right = n; } + virtual TIntermTyped* getLeft() const { return left; } + virtual TIntermTyped* getRight() const { return right; } + virtual TIntermBinary* getAsBinaryNode() { return this; } + virtual const TIntermBinary* getAsBinaryNode() const { return this; } + virtual void updatePrecision(); +protected: + TIntermTyped* left; + TIntermTyped* right; +}; + +// +// Nodes for unary math operators. +// +class TIntermUnary : public TIntermOperator { +public: + TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {} + TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {} + virtual void traverse(TIntermTraverser*); + virtual void setOperand(TIntermTyped* o) { operand = o; } + virtual TIntermTyped* getOperand() { return operand; } + virtual const TIntermTyped* getOperand() const { return operand; } + virtual TIntermUnary* getAsUnaryNode() { return this; } + virtual const TIntermUnary* getAsUnaryNode() const { return this; } + virtual void updatePrecision(); +protected: + TIntermTyped* operand; +}; + +typedef TVector TIntermSequence; +typedef TVector TQualifierList; +// +// Nodes that operate on an arbitrary sized set of children. +// +class TIntermAggregate : public TIntermOperator { +public: + TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(nullptr) { } + TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(nullptr) { } + ~TIntermAggregate() { delete pragmaTable; } + virtual TIntermAggregate* getAsAggregate() { return this; } + virtual const TIntermAggregate* getAsAggregate() const { return this; } + virtual void setOperator(TOperator o) { op = o; } + virtual TIntermSequence& getSequence() { return sequence; } + virtual const TIntermSequence& getSequence() const { return sequence; } + virtual void setName(const TString& n) { name = n; } + virtual const TString& getName() const { return name; } + virtual void traverse(TIntermTraverser*); + virtual void setUserDefined() { userDefined = true; } + virtual bool isUserDefined() { return userDefined; } + virtual TQualifierList& getQualifierList() { return qualifier; } + virtual const TQualifierList& getQualifierList() const { return qualifier; } + void setOptimize(bool o) { optimize = o; } + void setDebug(bool d) { debug = d; } + bool getOptimize() const { return optimize; } + bool getDebug() const { return debug; } + void setPragmaTable(const TPragmaTable& pTable); + const TPragmaTable& getPragmaTable() const { return *pragmaTable; } +protected: + TIntermAggregate(const TIntermAggregate&); // disallow copy constructor + TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator + TIntermSequence sequence; + TQualifierList qualifier; + TString name; + bool userDefined; // used for user defined function names + bool optimize; + bool debug; + TPragmaTable* pragmaTable; +}; + +// +// For if tests. +// +class TIntermSelection : public TIntermTyped { +public: + TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) : + TIntermTyped(EbtVoid), condition(cond), trueBlock(trueB), falseBlock(falseB), + shortCircuit(true), + flatten(false), dontFlatten(false) {} + TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) : + TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB), + shortCircuit(true), + flatten(false), dontFlatten(false) {} + virtual void traverse(TIntermTraverser*); + virtual TIntermTyped* getCondition() const { return condition; } + virtual TIntermNode* getTrueBlock() const { return trueBlock; } + virtual TIntermNode* getFalseBlock() const { return falseBlock; } + virtual TIntermSelection* getAsSelectionNode() { return this; } + virtual const TIntermSelection* getAsSelectionNode() const { return this; } + + void setNoShortCircuit() { shortCircuit = false; } + bool getShortCircuit() const { return shortCircuit; } + + void setFlatten() { flatten = true; } + void setDontFlatten() { dontFlatten = true; } + bool getFlatten() const { return flatten; } + bool getDontFlatten() const { return dontFlatten; } + +protected: + TIntermTyped* condition; + TIntermNode* trueBlock; + TIntermNode* falseBlock; + bool shortCircuit; // normally all if-then-else and all GLSL ?: short-circuit, but HLSL ?: does not + bool flatten; // true if flatten requested + bool dontFlatten; // true if requested to not flatten +}; + +// +// For switch statements. Designed use is that a switch will have sequence of nodes +// that are either case/default nodes or a *single* node that represents all the code +// in between (if any) consecutive case/defaults. So, a traversal need only deal with +// 0 or 1 nodes per case/default statement. +// +class TIntermSwitch : public TIntermNode { +public: + TIntermSwitch(TIntermTyped* cond, TIntermAggregate* b) : condition(cond), body(b), + flatten(false), dontFlatten(false) {} + virtual void traverse(TIntermTraverser*); + virtual TIntermNode* getCondition() const { return condition; } + virtual TIntermAggregate* getBody() const { return body; } + virtual TIntermSwitch* getAsSwitchNode() { return this; } + virtual const TIntermSwitch* getAsSwitchNode() const { return this; } + + void setFlatten() { flatten = true; } + void setDontFlatten() { dontFlatten = true; } + bool getFlatten() const { return flatten; } + bool getDontFlatten() const { return dontFlatten; } + +protected: + TIntermTyped* condition; + TIntermAggregate* body; + bool flatten; // true if flatten requested + bool dontFlatten; // true if requested to not flatten +}; + +enum TVisit +{ + EvPreVisit, + EvInVisit, + EvPostVisit +}; + +// +// For traversing the tree. User should derive from this, +// put their traversal specific data in it, and then pass +// it to a Traverse method. +// +// When using this, just fill in the methods for nodes you want visited. +// Return false from a pre-visit to skip visiting that node's subtree. +// +// Explicitly set postVisit to true if you want post visiting, otherwise, +// filled in methods will only be called at pre-visit time (before processing +// the subtree). Similarly for inVisit for in-order visiting of nodes with +// multiple children. +// +// If you only want post-visits, explicitly turn off preVisit (and inVisit) +// and turn on postVisit. +// +// In general, for the visit*() methods, return true from interior nodes +// to have the traversal continue on to children. +// +// If you process children yourself, or don't want them processed, return false. +// +class TIntermTraverser { +public: + POOL_ALLOCATOR_NEW_DELETE(glslang::GetThreadPoolAllocator()) + TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) : + preVisit(preVisit), + inVisit(inVisit), + postVisit(postVisit), + rightToLeft(rightToLeft), + depth(0), + maxDepth(0) { } + virtual ~TIntermTraverser() { } + + virtual void visitSymbol(TIntermSymbol*) { } + virtual void visitConstantUnion(TIntermConstantUnion*) { } + virtual bool visitBinary(TVisit, TIntermBinary*) { return true; } + virtual bool visitUnary(TVisit, TIntermUnary*) { return true; } + virtual bool visitSelection(TVisit, TIntermSelection*) { return true; } + virtual bool visitAggregate(TVisit, TIntermAggregate*) { return true; } + virtual bool visitLoop(TVisit, TIntermLoop*) { return true; } + virtual bool visitBranch(TVisit, TIntermBranch*) { return true; } + virtual bool visitSwitch(TVisit, TIntermSwitch*) { return true; } + + int getMaxDepth() const { return maxDepth; } + + void incrementDepth(TIntermNode *current) + { + depth++; + maxDepth = (std::max)(maxDepth, depth); + path.push_back(current); + } + + void decrementDepth() + { + depth--; + path.pop_back(); + } + + TIntermNode *getParentNode() + { + return path.size() == 0 ? NULL : path.back(); + } + + const bool preVisit; + const bool inVisit; + const bool postVisit; + const bool rightToLeft; + +protected: + TIntermTraverser& operator=(TIntermTraverser&); + + int depth; + int maxDepth; + + // All the nodes from root to the current node's parent during traversing. + TVector path; +}; + +// KHR_vulkan_glsl says "Two arrays sized with specialization constants are the same type only if +// sized with the same symbol, involving no operations" +inline bool SameSpecializationConstants(TIntermTyped* node1, TIntermTyped* node2) +{ + return node1->getAsSymbolNode() && node2->getAsSymbolNode() && + node1->getAsSymbolNode()->getId() == node2->getAsSymbolNode()->getId(); +} + +} // end namespace glslang + +#endif // __INTERMEDIATE_H diff --git a/android/arm64-v8a/include/glslang/glslang/Include/revision.h b/android/arm64-v8a/include/glslang/glslang/Include/revision.h new file mode 100644 index 00000000..744c2fb4 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/Include/revision.h @@ -0,0 +1,3 @@ +// This header is generated by the make-revision script. + +#define GLSLANG_PATCH_LEVEL 3743 diff --git a/android/arm64-v8a/include/glslang/glslang/MachineIndependent/Initialize.h b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/Initialize.h new file mode 100644 index 00000000..ac8ec33e --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/Initialize.h @@ -0,0 +1,112 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013-2016 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _INITIALIZE_INCLUDED_ +#define _INITIALIZE_INCLUDED_ + +#include "../Include/ResourceLimits.h" +#include "../Include/Common.h" +#include "../Include/ShHandle.h" +#include "SymbolTable.h" +#include "Versions.h" + +namespace glslang { + +// +// This is made to hold parseable strings for almost all the built-in +// functions and variables for one specific combination of version +// and profile. (Some still need to be added programmatically.) +// This is a base class for language-specific derivations, which +// can be used for language independent builtins. +// +// The strings are organized by +// commonBuiltins: intersection of all stages' built-ins, processed just once +// stageBuiltins[]: anything a stage needs that's not in commonBuiltins +// +class TBuiltInParseables { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + TBuiltInParseables(); + virtual ~TBuiltInParseables(); + virtual void initialize(int version, EProfile, const SpvVersion& spvVersion) = 0; + virtual void initialize(const TBuiltInResource& resources, int version, EProfile, const SpvVersion& spvVersion, EShLanguage) = 0; + virtual const TString& getCommonString() const { return commonBuiltins; } + virtual const TString& getStageString(EShLanguage language) const { return stageBuiltins[language]; } + + virtual void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable) = 0; + virtual void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources) = 0; + +protected: + TString commonBuiltins; + TString stageBuiltins[EShLangCount]; +}; + +// +// This is a GLSL specific derivation of TBuiltInParseables. To present a stable +// interface and match other similar code, it is called TBuiltIns, rather +// than TBuiltInParseablesGlsl. +// +class TBuiltIns : public TBuiltInParseables { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + TBuiltIns(); + virtual ~TBuiltIns(); + void initialize(int version, EProfile, const SpvVersion& spvVersion); + void initialize(const TBuiltInResource& resources, int version, EProfile, const SpvVersion& spvVersion, EShLanguage); + + void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable); + void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources); + +protected: + void addTabledBuiltins(int version, EProfile profile, const SpvVersion& spvVersion); + void relateTabledBuiltins(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage, TSymbolTable&); + void add2ndGenerationSamplingImaging(int version, EProfile profile, const SpvVersion& spvVersion); + void addSubpassSampling(TSampler, const TString& typeName, int version, EProfile profile); + void addQueryFunctions(TSampler, const TString& typeName, int version, EProfile profile); + void addImageFunctions(TSampler, const TString& typeName, int version, EProfile profile); + void addSamplingFunctions(TSampler, const TString& typeName, int version, EProfile profile); + void addGatherFunctions(TSampler, const TString& typeName, int version, EProfile profile); + + // Helpers for making textual representations of the permutations + // of texturing/imaging functions. + const char* postfixes[5]; + const char* prefixes[EbtNumTypes]; + int dimMap[EsdNumDims]; +}; + +} // end namespace glslang + +#endif // _INITIALIZE_INCLUDED_ diff --git a/android/arm64-v8a/include/glslang/glslang/MachineIndependent/LiveTraverser.h b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/LiveTraverser.h new file mode 100644 index 00000000..7333bc96 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/LiveTraverser.h @@ -0,0 +1,138 @@ +// +// Copyright (C) 2016 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#pragma once + +#include "../Include/Common.h" +#include "reflection.h" +#include "localintermediate.h" + +#include "gl_types.h" + +#include +#include + +namespace glslang { + +// +// The traverser: mostly pass through, except +// - processing function-call nodes to push live functions onto the stack of functions to process +// - processing selection nodes to trim semantically dead code +// +// This is in the glslang namespace directly so it can be a friend of TReflection. +// This can be derived from to implement reflection database traversers or +// binding mappers: anything that wants to traverse the live subset of the tree. +// + +class TLiveTraverser : public TIntermTraverser { +public: + TLiveTraverser(const TIntermediate& i, bool traverseAll = false, + bool preVisit = true, bool inVisit = false, bool postVisit = false) : + TIntermTraverser(preVisit, inVisit, postVisit), + intermediate(i), traverseAll(traverseAll) + { } + + // + // Given a function name, find its subroot in the tree, and push it onto the stack of + // functions left to process. + // + void pushFunction(const TString& name) + { + TIntermSequence& globals = intermediate.getTreeRoot()->getAsAggregate()->getSequence(); + for (unsigned int f = 0; f < globals.size(); ++f) { + TIntermAggregate* candidate = globals[f]->getAsAggregate(); + if (candidate && candidate->getOp() == EOpFunction && candidate->getName() == name) { + functions.push_back(candidate); + break; + } + } + } + + typedef std::list TFunctionStack; + TFunctionStack functions; + +protected: + // To catch which function calls are not dead, and hence which functions must be visited. + virtual bool visitAggregate(TVisit, TIntermAggregate* node) + { + if (!traverseAll) + if (node->getOp() == EOpFunctionCall) + addFunctionCall(node); + + return true; // traverse this subtree + } + + // To prune semantically dead paths. + virtual bool visitSelection(TVisit /* visit */, TIntermSelection* node) + { + if (traverseAll) + return true; // traverse all code + + TIntermConstantUnion* constant = node->getCondition()->getAsConstantUnion(); + if (constant) { + // cull the path that is dead + if (constant->getConstArray()[0].getBConst() == true && node->getTrueBlock()) + node->getTrueBlock()->traverse(this); + if (constant->getConstArray()[0].getBConst() == false && node->getFalseBlock()) + node->getFalseBlock()->traverse(this); + + return false; // don't traverse any more, we did it all above + } else + return true; // traverse the whole subtree + } + + // Track live functions as well as uniforms, so that we don't visit dead functions + // and only visit each function once. + void addFunctionCall(TIntermAggregate* call) + { + // // just use the map to ensure we process each function at most once + if (liveFunctions.find(call->getName()) == liveFunctions.end()) { + liveFunctions.insert(call->getName()); + pushFunction(call->getName()); + } + } + + const TIntermediate& intermediate; + typedef std::unordered_set TLiveFunctions; + TLiveFunctions liveFunctions; + bool traverseAll; + +private: + // prevent copy & copy construct + TLiveTraverser(TLiveTraverser&); + TLiveTraverser& operator=(TLiveTraverser&); +}; + +} // namespace glslang diff --git a/android/arm64-v8a/include/glslang/glslang/MachineIndependent/ParseHelper.h b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/ParseHelper.h new file mode 100644 index 00000000..20df6405 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/ParseHelper.h @@ -0,0 +1,525 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +// +// This header defines a two-level parse-helper hierarchy, derived from +// TParseVersions: +// - TParseContextBase: sharable across multiple parsers +// - TParseContext: GLSL specific helper +// + +#ifndef _PARSER_HELPER_INCLUDED_ +#define _PARSER_HELPER_INCLUDED_ + +#include +#include + +#include "parseVersions.h" +#include "../Include/ShHandle.h" +#include "SymbolTable.h" +#include "localintermediate.h" +#include "Scan.h" +#include "attribute.h" + +namespace glslang { + +struct TPragma { + TPragma(bool o, bool d) : optimize(o), debug(d) { } + bool optimize; + bool debug; + TPragmaTable pragmaTable; +}; + +class TScanContext; +class TPpContext; + +typedef std::set TIdSetType; + +// +// Sharable code (as well as what's in TParseVersions) across +// parse helpers. +// +class TParseContextBase : public TParseVersions { +public: + TParseContextBase(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins, int version, + EProfile profile, const SpvVersion& spvVersion, EShLanguage language, + TInfoSink& infoSink, bool forwardCompatible, EShMessages messages, + const TString* entryPoint = nullptr) + : TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages), + scopeMangler("::"), + symbolTable(symbolTable), + statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0), + postEntryPointReturn(false), + contextPragma(true, false), + beginInvocationInterlockCount(0), endInvocationInterlockCount(0), + parsingBuiltins(parsingBuiltins), scanContext(nullptr), ppContext(nullptr), + limits(resources.limits), + globalUniformBlock(nullptr), + globalUniformBinding(TQualifier::layoutBindingEnd), + globalUniformSet(TQualifier::layoutSetEnd) + { + if (entryPoint != nullptr) + sourceEntryPointName = *entryPoint; + } + virtual ~TParseContextBase() { } + +#if !defined(GLSLANG_WEB) || defined(GLSLANG_WEB_DEVEL) + virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...); + virtual void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...); + virtual void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...); + virtual void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...); +#endif + + virtual void setLimits(const TBuiltInResource&) = 0; + + void checkIndex(const TSourceLoc&, const TType&, int& index); + + EShLanguage getLanguage() const { return language; } + void setScanContext(TScanContext* c) { scanContext = c; } + TScanContext* getScanContext() const { return scanContext; } + void setPpContext(TPpContext* c) { ppContext = c; } + TPpContext* getPpContext() const { return ppContext; } + + virtual void setLineCallback(const std::function& func) { lineCallback = func; } + virtual void setExtensionCallback(const std::function& func) { extensionCallback = func; } + virtual void setVersionCallback(const std::function& func) { versionCallback = func; } + virtual void setPragmaCallback(const std::function&)>& func) { pragmaCallback = func; } + virtual void setErrorCallback(const std::function& func) { errorCallback = func; } + + virtual void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) = 0; + virtual bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) = 0; + virtual bool lineDirectiveShouldSetNextLine() const = 0; + virtual void handlePragma(const TSourceLoc&, const TVector&) = 0; + + virtual bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) = 0; + + virtual void notifyVersion(int line, int version, const char* type_string) + { + if (versionCallback) + versionCallback(line, version, type_string); + } + virtual void notifyErrorDirective(int line, const char* error_message) + { + if (errorCallback) + errorCallback(line, error_message); + } + virtual void notifyLineDirective(int curLineNo, int newLineNo, bool hasSource, int sourceNum, const char* sourceName) + { + if (lineCallback) + lineCallback(curLineNo, newLineNo, hasSource, sourceNum, sourceName); + } + virtual void notifyExtensionDirective(int line, const char* extension, const char* behavior) + { + if (extensionCallback) + extensionCallback(line, extension, behavior); + } + +#ifdef ENABLE_HLSL + // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL) + virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr); +#endif + + // Potentially rename shader entry point function + void renameShaderFunction(TString*& name) const + { + // Replace the entry point name given in the shader with the real entry point name, + // if there is a substitution. + if (name != nullptr && *name == sourceEntryPointName && intermediate.getEntryPointName().size() > 0) + name = NewPoolTString(intermediate.getEntryPointName().c_str()); + } + + virtual bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*); + virtual void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*); + + const char* const scopeMangler; + + // Basic parsing state, easily accessible to the grammar + + TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile + int statementNestingLevel; // 0 if outside all flow control or compound statements + int loopNestingLevel; // 0 if outside all loops + int structNestingLevel; // 0 if outside blocks and structures + int controlFlowNestingLevel; // 0 if outside all flow control + const TType* currentFunctionType; // the return type of the function that's currently being parsed + bool functionReturnsValue; // true if a non-void function has a return + // if inside a function, true if the function is the entry point and this is after a return statement + bool postEntryPointReturn; + // case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting + TList switchSequenceStack; + // the statementNestingLevel the current switch statement is at, which must match the level of its case statements + TList switchLevel; + struct TPragma contextPragma; + int beginInvocationInterlockCount; + int endInvocationInterlockCount; + +protected: + TParseContextBase(TParseContextBase&); + TParseContextBase& operator=(TParseContextBase&); + + const bool parsingBuiltins; // true if parsing built-in symbols/functions + TVector linkageSymbols; // will be transferred to 'linkage', after all editing is done, order preserving + TScanContext* scanContext; + TPpContext* ppContext; + TBuiltInResource resources; + TLimits& limits; + TString sourceEntryPointName; + + // These, if set, will be called when a line, pragma ... is preprocessed. + // They will be called with any parameters to the original directive. + std::function lineCallback; + std::function&)> pragmaCallback; + std::function versionCallback; + std::function extensionCallback; + std::function errorCallback; + + // see implementation for detail + const TFunction* selectFunction(const TVector, const TFunction&, + std::function, + std::function, + /* output */ bool& tie); + + virtual void parseSwizzleSelector(const TSourceLoc&, const TString&, int size, + TSwizzleSelectors&); + + // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL) + TVariable* globalUniformBlock; // the actual block, inserted into the symbol table + unsigned int globalUniformBinding; // the block's binding number + unsigned int globalUniformSet; // the block's set number + int firstNewMember; // the index of the first member not yet inserted into the symbol table + // override this to set the language-specific name + virtual const char* getGlobalUniformBlockName() const { return ""; } + virtual void setUniformBlockDefaults(TType&) const { } + virtual void finalizeGlobalUniformBlockLayout(TVariable&) { } + virtual void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, TPrefixType prefix, + va_list args); + virtual void trackLinkage(TSymbol& symbol); + virtual void makeEditable(TSymbol*&); + virtual TVariable* getEditableVariable(const char* name); + virtual void finish(); +}; + +// +// Manage the state for when to respect precision qualifiers and when to warn about +// the defaults being different than might be expected. +// +class TPrecisionManager { +public: + TPrecisionManager() : obey(false), warn(false), explicitIntDefault(false), explicitFloatDefault(false){ } + virtual ~TPrecisionManager() {} + + void respectPrecisionQualifiers() { obey = true; } + bool respectingPrecisionQualifiers() const { return obey; } + bool shouldWarnAboutDefaults() const { return warn; } + void defaultWarningGiven() { warn = false; } + void warnAboutDefaults() { warn = true; } + void explicitIntDefaultSeen() + { + explicitIntDefault = true; + if (explicitFloatDefault) + warn = false; + } + void explicitFloatDefaultSeen() + { + explicitFloatDefault = true; + if (explicitIntDefault) + warn = false; + } + +protected: + bool obey; // respect precision qualifiers + bool warn; // need to give a warning about the defaults + bool explicitIntDefault; // user set the default for int/uint + bool explicitFloatDefault; // user set the default for float +}; + +// +// GLSL-specific parse helper. Should have GLSL in the name, but that's +// too big of a change for comparing branches at the moment, and perhaps +// impacts downstream consumers as well. +// +class TParseContext : public TParseContextBase { +public: + TParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins, int version, EProfile, const SpvVersion& spvVersion, EShLanguage, TInfoSink&, + bool forwardCompatible = false, EShMessages messages = EShMsgDefault, + const TString* entryPoint = nullptr); + virtual ~TParseContext(); + + bool obeyPrecisionQualifiers() const { return precisionManager.respectingPrecisionQualifiers(); } + void setPrecisionDefaults(); + + void setLimits(const TBuiltInResource&) override; + bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) override; + void parserError(const char* s); // for bison's yyerror + + void reservedErrorCheck(const TSourceLoc&, const TString&); + void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) override; + bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) override; + bool lineDirectiveShouldSetNextLine() const override; + bool builtInName(const TString&); + + void handlePragma(const TSourceLoc&, const TVector&) override; + TIntermTyped* handleVariable(const TSourceLoc&, TSymbol* symbol, const TString* string); + TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index); + void handleIndexLimits(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index); + +#ifndef GLSLANG_WEB + void makeEditable(TSymbol*&) override; + void ioArrayCheck(const TSourceLoc&, const TType&, const TString& identifier); +#endif + bool isIoResizeArray(const TType&) const; + void fixIoArraySize(const TSourceLoc&, TType&); + void handleIoResizeArrayAccess(const TSourceLoc&, TIntermTyped* base); + void checkIoArraysConsistency(const TSourceLoc&, bool tailOnly = false); + int getIoArrayImplicitSize(const TQualifier&, TString* featureString = nullptr) const; + void checkIoArrayConsistency(const TSourceLoc&, int requiredSize, const char* feature, TType&, const TString&); + + TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right); + TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode); + TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field); + void blockMemberExtensionCheck(const TSourceLoc&, const TIntermTyped* base, int member, const TString& memberName); + TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype); + TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&); + TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*); + TIntermTyped* handleBuiltInFunctionCall(TSourceLoc, TIntermNode* arguments, const TFunction& function); + void computeBuiltinPrecisions(TIntermTyped&, const TFunction&); + TIntermNode* handleReturnValue(const TSourceLoc&, TIntermTyped*); + void checkLocation(const TSourceLoc&, TOperator); + TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*); + void addInputArgumentConversions(const TFunction&, TIntermNode*&) const; + TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const; + void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&); + void nonOpBuiltInCheck(const TSourceLoc&, const TFunction&, TIntermAggregate&); + void userFunctionCallCheck(const TSourceLoc&, TIntermAggregate&); + void samplerConstructorLocationCheck(const TSourceLoc&, const char* token, TIntermNode*); + TFunction* handleConstructorCall(const TSourceLoc&, const TPublicType&); + void handlePrecisionQualifier(const TSourceLoc&, TQualifier&, TPrecisionQualifier); + void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier); + void memorySemanticsCheck(const TSourceLoc&, const TFunction&, const TIntermOperator& callNode); + + void assignError(const TSourceLoc&, const char* op, TString left, TString right); + void unaryOpError(const TSourceLoc&, const char* op, TString operand); + void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right); + void variableCheck(TIntermTyped*& nodePtr); + bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override; + void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override; + void constantValueCheck(TIntermTyped* node, const char* token); + void integerCheck(const TIntermTyped* node, const char* token); + void globalCheck(const TSourceLoc&, const char* token); + bool constructorError(const TSourceLoc&, TIntermNode*, TFunction&, TOperator, TType&); + bool constructorTextureSamplerError(const TSourceLoc&, const TFunction&); + void arraySizeCheck(const TSourceLoc&, TIntermTyped* expr, TArraySize&, const char *sizeType); + bool arrayQualifierError(const TSourceLoc&, const TQualifier&); + bool arrayError(const TSourceLoc&, const TType&); + void arraySizeRequiredCheck(const TSourceLoc&, const TArraySizes&); + void structArrayCheck(const TSourceLoc&, const TType& structure); + void arraySizesCheck(const TSourceLoc&, const TQualifier&, TArraySizes*, const TIntermTyped* initializer, bool lastMember); + void arrayOfArrayVersionCheck(const TSourceLoc&, const TArraySizes*); + bool voidErrorCheck(const TSourceLoc&, const TString&, TBasicType); + void boolCheck(const TSourceLoc&, const TIntermTyped*); + void boolCheck(const TSourceLoc&, const TPublicType&); + void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer); + void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier); + void accStructCheck(const TSourceLoc & loc, const TType & type, const TString & identifier); + void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier); + void memberQualifierCheck(glslang::TPublicType&); + void globalQualifierFixCheck(const TSourceLoc&, TQualifier&); + void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&); + bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType); + void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force); + void setDefaultPrecision(const TSourceLoc&, TPublicType&, TPrecisionQualifier); + int computeSamplerTypeIndex(TSampler&); + TPrecisionQualifier getDefaultPrecision(TPublicType&); + void precisionQualifierCheck(const TSourceLoc&, TBasicType, TQualifier&); + void parameterTypeCheck(const TSourceLoc&, TStorageQualifier qualifier, const TType& type); + bool containsFieldWithBasicType(const TType& type ,TBasicType basicType); + TSymbol* redeclareBuiltinVariable(const TSourceLoc&, const TString&, const TQualifier&, const TShaderQualifiers&); + void redeclareBuiltinBlock(const TSourceLoc&, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes); + void paramCheckFixStorage(const TSourceLoc&, const TStorageQualifier&, TType& type); + void paramCheckFix(const TSourceLoc&, const TQualifier&, TType& type); + void nestedBlockCheck(const TSourceLoc&); + void nestedStructCheck(const TSourceLoc&); + void arrayObjectCheck(const TSourceLoc&, const TType&, const char* op); + void opaqueCheck(const TSourceLoc&, const TType&, const char* op); + void referenceCheck(const TSourceLoc&, const TType&, const char* op); + void storage16BitAssignmentCheck(const TSourceLoc&, const TType&, const char* op); + void specializationCheck(const TSourceLoc&, const TType&, const char* op); + void structTypeCheck(const TSourceLoc&, TPublicType&); + void inductiveLoopCheck(const TSourceLoc&, TIntermNode* init, TIntermLoop* loop); + void arrayLimitCheck(const TSourceLoc&, const TString&, int size); + void limitCheck(const TSourceLoc&, int value, const char* limit, const char* feature); + + void inductiveLoopBodyCheck(TIntermNode*, int loopIndexId, TSymbolTable&); + void constantIndexExpressionCheck(TIntermNode*); + + void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&); + void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&, const TIntermTyped*); + void mergeObjectLayoutQualifiers(TQualifier& dest, const TQualifier& src, bool inheritOnly); + void layoutObjectCheck(const TSourceLoc&, const TSymbol&); + void layoutMemberLocationArrayCheck(const TSourceLoc&, bool memberWithLocation, TArraySizes* arraySizes); + void layoutTypeCheck(const TSourceLoc&, const TType&); + void layoutQualifierCheck(const TSourceLoc&, const TQualifier&); + void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&); + void fixOffset(const TSourceLoc&, TSymbol&); + + const TFunction* findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn); + const TFunction* findFunctionExact(const TSourceLoc& loc, const TFunction& call, bool& builtIn); + const TFunction* findFunction120(const TSourceLoc& loc, const TFunction& call, bool& builtIn); + const TFunction* findFunction400(const TSourceLoc& loc, const TFunction& call, bool& builtIn); + const TFunction* findFunctionExplicitTypes(const TSourceLoc& loc, const TFunction& call, bool& builtIn); + void declareTypeDefaults(const TSourceLoc&, const TPublicType&); + TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, const TPublicType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0); + TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&); + TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&); + TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset); + void inheritMemoryQualifiers(const TQualifier& from, TQualifier& to); + void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0); + void blockStageIoCheck(const TSourceLoc&, const TQualifier&); + void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName); + void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation); + void fixXfbOffsets(TQualifier&, TTypeList&); + void fixBlockUniformOffsets(TQualifier&, TTypeList&); + void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier); + void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&); + void invariantCheck(const TSourceLoc&, const TQualifier&); + void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&); + void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode); + TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body); + +#ifndef GLSLANG_WEB + TAttributeType attributeFromName(const TString& name) const; + TAttributes* makeAttributes(const TString& identifier) const; + TAttributes* makeAttributes(const TString& identifier, TIntermNode* node) const; + TAttributes* mergeAttributes(TAttributes*, TAttributes*) const; + + // Determine selection control from attributes + void handleSelectionAttributes(const TAttributes& attributes, TIntermNode*); + void handleSwitchAttributes(const TAttributes& attributes, TIntermNode*); + // Determine loop control from attributes + void handleLoopAttributes(const TAttributes& attributes, TIntermNode*); +#endif + + void checkAndResizeMeshViewDim(const TSourceLoc&, TType&, bool isBlockMember); + +protected: + void nonInitConstCheck(const TSourceLoc&, TString& identifier, TType& type); + void inheritGlobalDefaults(TQualifier& dst) const; + TVariable* makeInternalVariable(const char* name, const TType&) const; + TVariable* declareNonArray(const TSourceLoc&, const TString& identifier, const TType&); + void declareArray(const TSourceLoc&, const TString& identifier, const TType&, TSymbol*&); + void checkRuntimeSizable(const TSourceLoc&, const TIntermTyped&); + bool isRuntimeLength(const TIntermTyped&) const; + TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable); + TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer); +#ifndef GLSLANG_WEB + void finish() override; +#endif + +public: + // + // Generally, bison productions, the scanner, and the PP need read/write access to these; just give them direct access + // + + // Current state of parsing + bool inMain; // if inside a function, true if the function is main + const TString* blockName; + TQualifier currentBlockQualifier; + TPrecisionQualifier defaultPrecision[EbtNumTypes]; + TBuiltInResource resources; + TLimits& limits; + +protected: + TParseContext(TParseContext&); + TParseContext& operator=(TParseContext&); + + static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2 * 2 * 2 * 2)); // see computeSamplerTypeIndex() + TPrecisionQualifier defaultSamplerPrecision[maxSamplerIndex]; + TPrecisionManager precisionManager; + TQualifier globalBufferDefaults; + TQualifier globalUniformDefaults; + TQualifier globalInputDefaults; + TQualifier globalOutputDefaults; + TString currentCaller; // name of last function body entered (not valid when at global scope) +#ifndef GLSLANG_WEB + int* atomicUintOffsets; // to become an array of the right size to hold an offset per binding point + bool anyIndexLimits; + TIdSetType inductiveLoopIds; + TVector needsIndexLimitationChecking; + + // + // Geometry shader input arrays: + // - array sizing is based on input primitive and/or explicit size + // + // Tessellation control output arrays: + // - array sizing is based on output layout(vertices=...) and/or explicit size + // + // Both: + // - array sizing is retroactive + // - built-in block redeclarations interact with this + // + // Design: + // - use a per-context "resize-list", a list of symbols whose array sizes + // can be fixed + // + // - the resize-list starts empty at beginning of user-shader compilation, it does + // not have built-ins in it + // + // - on built-in array use: copyUp() symbol and add it to the resize-list + // + // - on user array declaration: add it to the resize-list + // + // - on block redeclaration: copyUp() symbol and add it to the resize-list + // * note, that appropriately gives an error if redeclaring a block that + // was already used and hence already copied-up + // + // - on seeing a layout declaration that sizes the array, fix everything in the + // resize-list, giving errors for mismatch + // + // - on seeing an array size declaration, give errors on mismatch between it and previous + // array-sizing declarations + // + TVector ioArraySymbolResizeList; +#endif +}; + +} // end namespace glslang + +#endif // _PARSER_HELPER_INCLUDED_ diff --git a/android/arm64-v8a/include/glslang/glslang/MachineIndependent/RemoveTree.h b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/RemoveTree.h new file mode 100644 index 00000000..1ed01562 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/RemoveTree.h @@ -0,0 +1,41 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#pragma once + +namespace glslang { + +void RemoveAllTreeNodes(TIntermNode*); + +} // end namespace glslang diff --git a/android/arm64-v8a/include/glslang/glslang/MachineIndependent/Scan.h b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/Scan.h new file mode 100644 index 00000000..24b75cf7 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/Scan.h @@ -0,0 +1,276 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +#ifndef _GLSLANG_SCAN_INCLUDED_ +#define _GLSLANG_SCAN_INCLUDED_ + +#include "Versions.h" + +namespace glslang { + +// Use a global end-of-input character, so no translation is needed across +// layers of encapsulation. Characters are all 8 bit, and positive, so there is +// no aliasing of character 255 onto -1, for example. +const int EndOfInput = -1; + +// +// A character scanner that seamlessly, on read-only strings, reads across an +// array of strings without assuming null termination. +// +class TInputScanner { +public: + TInputScanner(int n, const char* const s[], size_t L[], const char* const* names = nullptr, + int b = 0, int f = 0, bool single = false) : + numSources(n), + // up to this point, common usage is "char*", but now we need positive 8-bit characters + sources(reinterpret_cast(s)), + lengths(L), currentSource(0), currentChar(0), stringBias(b), finale(f), singleLogical(single), + endOfFileReached(false) + { + loc = new TSourceLoc[numSources]; + for (int i = 0; i < numSources; ++i) { + loc[i].init(i - stringBias); + } + if (names != nullptr) { + for (int i = 0; i < numSources; ++i) + loc[i].name = names[i] != nullptr ? NewPoolTString(names[i]) : nullptr; + } + loc[currentSource].line = 1; + logicalSourceLoc.init(1); + logicalSourceLoc.name = loc[0].name; + } + + virtual ~TInputScanner() + { + delete [] loc; + } + + // retrieve the next character and advance one character + int get() + { + int ret = peek(); + if (ret == EndOfInput) + return ret; + ++loc[currentSource].column; + ++logicalSourceLoc.column; + if (ret == '\n') { + ++loc[currentSource].line; + ++logicalSourceLoc.line; + logicalSourceLoc.column = 0; + loc[currentSource].column = 0; + } + advance(); + + return ret; + } + + // retrieve the next character, no advance + int peek() + { + if (currentSource >= numSources) { + endOfFileReached = true; + return EndOfInput; + } + // Make sure we do not read off the end of a string. + // N.B. Sources can have a length of 0. + int sourceToRead = currentSource; + size_t charToRead = currentChar; + while(charToRead >= lengths[sourceToRead]) { + charToRead = 0; + sourceToRead += 1; + if (sourceToRead >= numSources) { + return EndOfInput; + } + } + + // Here, we care about making negative valued characters positive + return sources[sourceToRead][charToRead]; + } + + // go back one character + void unget() + { + // Do not roll back once we've reached the end of the file. + if (endOfFileReached) + return; + + if (currentChar > 0) { + --currentChar; + --loc[currentSource].column; + --logicalSourceLoc.column; + if (loc[currentSource].column < 0) { + // We've moved back past a new line. Find the + // previous newline (or start of the file) to compute + // the column count on the now current line. + size_t chIndex = currentChar; + while (chIndex > 0) { + if (sources[currentSource][chIndex] == '\n') { + break; + } + --chIndex; + } + logicalSourceLoc.column = (int)(currentChar - chIndex); + loc[currentSource].column = (int)(currentChar - chIndex); + } + } else { + do { + --currentSource; + } while (currentSource > 0 && lengths[currentSource] == 0); + if (lengths[currentSource] == 0) { + // set to 0 if we've backed up to the start of an empty string + currentChar = 0; + } else + currentChar = lengths[currentSource] - 1; + } + if (peek() == '\n') { + --loc[currentSource].line; + --logicalSourceLoc.line; + } + } + + // for #line override + void setLine(int newLine) + { + logicalSourceLoc.line = newLine; + loc[getLastValidSourceIndex()].line = newLine; + } + + // for #line override in filename based parsing + void setFile(const char* filename) + { + TString* fn_tstr = NewPoolTString(filename); + logicalSourceLoc.name = fn_tstr; + loc[getLastValidSourceIndex()].name = fn_tstr; + } + + void setFile(const char* filename, int i) + { + TString* fn_tstr = NewPoolTString(filename); + if (i == getLastValidSourceIndex()) { + logicalSourceLoc.name = fn_tstr; + } + loc[i].name = fn_tstr; + } + + void setString(int newString) + { + logicalSourceLoc.string = newString; + loc[getLastValidSourceIndex()].string = newString; + logicalSourceLoc.name = nullptr; + loc[getLastValidSourceIndex()].name = nullptr; + } + + // for #include content indentation + void setColumn(int col) + { + logicalSourceLoc.column = col; + loc[getLastValidSourceIndex()].column = col; + } + + void setEndOfInput() + { + endOfFileReached = true; + currentSource = numSources; + } + + bool atEndOfInput() const { return endOfFileReached; } + + const TSourceLoc& getSourceLoc() const + { + if (singleLogical) { + return logicalSourceLoc; + } else { + return loc[std::max(0, std::min(currentSource, numSources - finale - 1))]; + } + } + // Returns the index (starting from 0) of the most recent valid source string we are reading from. + int getLastValidSourceIndex() const { return std::min(currentSource, numSources - 1); } + + void consumeWhiteSpace(bool& foundNonSpaceTab); + bool consumeComment(); + void consumeWhitespaceComment(bool& foundNonSpaceTab); + bool scanVersion(int& version, EProfile& profile, bool& notFirstToken); + +protected: + + // advance one character + void advance() + { + ++currentChar; + if (currentChar >= lengths[currentSource]) { + ++currentSource; + if (currentSource < numSources) { + loc[currentSource].string = loc[currentSource - 1].string + 1; + loc[currentSource].line = 1; + loc[currentSource].column = 0; + } + while (currentSource < numSources && lengths[currentSource] == 0) { + ++currentSource; + if (currentSource < numSources) { + loc[currentSource].string = loc[currentSource - 1].string + 1; + loc[currentSource].line = 1; + loc[currentSource].column = 0; + } + } + currentChar = 0; + } + } + + int numSources; // number of strings in source + const unsigned char* const *sources; // array of strings; must be converted to positive values on use, to avoid aliasing with -1 as EndOfInput + const size_t *lengths; // length of each string + int currentSource; + size_t currentChar; + + // This is for reporting what string/line an error occurred on, and can be overridden by #line. + // It remembers the last state of each source string as it is left for the next one, so unget() + // can restore that state. + TSourceLoc* loc; // an array + + int stringBias; // the first string that is the user's string number 0 + int finale; // number of internal strings after user's last string + + TSourceLoc logicalSourceLoc; + bool singleLogical; // treats the strings as a single logical string. + // locations will be reported from the first string. + + // Set to true once peek() returns EndOfFile, so that we won't roll back + // once we've reached EndOfFile. + bool endOfFileReached; +}; + +} // end namespace glslang + +#endif // _GLSLANG_SCAN_INCLUDED_ diff --git a/android/arm64-v8a/include/glslang/glslang/MachineIndependent/ScanContext.h b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/ScanContext.h new file mode 100644 index 00000000..74b2b3c7 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/ScanContext.h @@ -0,0 +1,93 @@ +// +// Copyright (C) 2013 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +// +// This holds context specific to the GLSL scanner, which +// sits between the preprocessor scanner and parser. +// + +#pragma once + +#include "ParseHelper.h" + +namespace glslang { + +class TPpContext; +class TPpToken; +class TParserToken; + +class TScanContext { +public: + explicit TScanContext(TParseContextBase& pc) : + parseContext(pc), + afterType(false), afterStruct(false), + field(false), afterBuffer(false) { } + virtual ~TScanContext() { } + + static void fillInKeywordMap(); + static void deleteKeywordMap(); + + int tokenize(TPpContext*, TParserToken&); + +protected: + TScanContext(TScanContext&); + TScanContext& operator=(TScanContext&); + + int tokenizeIdentifier(); + int identifierOrType(); + int reservedWord(); + int identifierOrReserved(bool reserved); + int es30ReservedFromGLSL(int version); + int nonreservedKeyword(int esVersion, int nonEsVersion); + int precisionKeyword(); + int matNxM(); + int dMat(); + int firstGenerationImage(bool inEs310); + int secondGenerationImage(); + + TParseContextBase& parseContext; + bool afterType; // true if we've recognized a type, so can only be looking for an identifier + bool afterStruct; // true if we've recognized the STRUCT keyword, so can only be looking for an identifier + bool field; // true if we're on a field, right after a '.' + bool afterBuffer; // true if we've recognized the BUFFER keyword + TSourceLoc loc; + TParserToken* parserToken; + TPpToken* ppToken; + + const char* tokenText; + int keyword; +}; + +} // end namespace glslang diff --git a/android/arm64-v8a/include/glslang/glslang/MachineIndependent/SymbolTable.h b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/SymbolTable.h new file mode 100644 index 00000000..40ca3da5 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/SymbolTable.h @@ -0,0 +1,885 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _SYMBOL_TABLE_INCLUDED_ +#define _SYMBOL_TABLE_INCLUDED_ + +// +// Symbol table for parsing. Has these design characteristics: +// +// * Same symbol table can be used to compile many shaders, to preserve +// effort of creating and loading with the large numbers of built-in +// symbols. +// +// --> This requires a copy mechanism, so initial pools used to create +// the shared information can be popped. Done through "clone" +// methods. +// +// * Name mangling will be used to give each function a unique name +// so that symbol table lookups are never ambiguous. This allows +// a simpler symbol table structure. +// +// * Pushing and popping of scope, so symbol table will really be a stack +// of symbol tables. Searched from the top, with new inserts going into +// the top. +// +// * Constants: Compile time constant symbols will keep their values +// in the symbol table. The parser can substitute constants at parse +// time, including doing constant folding and constant propagation. +// +// * No temporaries: Temporaries made from operations (+, --, .xy, etc.) +// are tracked in the intermediate representation, not the symbol table. +// + +#include "../Include/Common.h" +#include "../Include/intermediate.h" +#include "../Include/InfoSink.h" + +namespace glslang { + +// +// Symbol base class. (Can build functions or variables out of these...) +// + +class TVariable; +class TFunction; +class TAnonMember; + +typedef TVector TExtensionList; + +class TSymbol { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + explicit TSymbol(const TString *n) : name(n), extensions(0), writable(true) { } + virtual TSymbol* clone() const = 0; + virtual ~TSymbol() { } // rely on all symbol owned memory coming from the pool + + virtual const TString& getName() const { return *name; } + virtual void changeName(const TString* newName) { name = newName; } + virtual void addPrefix(const char* prefix) + { + TString newName(prefix); + newName.append(*name); + changeName(NewPoolTString(newName.c_str())); + } + virtual const TString& getMangledName() const { return getName(); } + virtual TFunction* getAsFunction() { return 0; } + virtual const TFunction* getAsFunction() const { return 0; } + virtual TVariable* getAsVariable() { return 0; } + virtual const TVariable* getAsVariable() const { return 0; } + virtual const TAnonMember* getAsAnonMember() const { return 0; } + virtual const TType& getType() const = 0; + virtual TType& getWritableType() = 0; + virtual void setUniqueId(int id) { uniqueId = id; } + virtual int getUniqueId() const { return uniqueId; } + virtual void setExtensions(int numExts, const char* const exts[]) + { + assert(extensions == 0); + assert(numExts > 0); + extensions = NewPoolObject(extensions); + for (int e = 0; e < numExts; ++e) + extensions->push_back(exts[e]); + } + virtual int getNumExtensions() const { return extensions == nullptr ? 0 : (int)extensions->size(); } + virtual const char** getExtensions() const { return extensions->data(); } + +#ifndef GLSLANG_WEB + virtual void dump(TInfoSink& infoSink, bool complete = false) const = 0; + void dumpExtensions(TInfoSink& infoSink) const; +#endif + + virtual bool isReadOnly() const { return ! writable; } + virtual void makeReadOnly() { writable = false; } + +protected: + explicit TSymbol(const TSymbol&); + TSymbol& operator=(const TSymbol&); + + const TString *name; + unsigned int uniqueId; // For cross-scope comparing during code generation + + // For tracking what extensions must be present + // (don't use if correct version/profile is present). + TExtensionList* extensions; // an array of pointers to existing constant char strings + + // + // N.B.: Non-const functions that will be generally used should assert on this, + // to avoid overwriting shared symbol-table information. + // + bool writable; +}; + +// +// Variable class, meaning a symbol that's not a function. +// +// There could be a separate class hierarchy for Constant variables; +// Only one of int, bool, or float, (or none) is correct for +// any particular use, but it's easy to do this way, and doesn't +// seem worth having separate classes, and "getConst" can't simply return +// different values for different types polymorphically, so this is +// just simple and pragmatic. +// +class TVariable : public TSymbol { +public: + TVariable(const TString *name, const TType& t, bool uT = false ) + : TSymbol(name), + userType(uT), + constSubtree(nullptr), + memberExtensions(nullptr), + anonId(-1) + { type.shallowCopy(t); } + virtual TVariable* clone() const; + virtual ~TVariable() { } + + virtual TVariable* getAsVariable() { return this; } + virtual const TVariable* getAsVariable() const { return this; } + virtual const TType& getType() const { return type; } + virtual TType& getWritableType() { assert(writable); return type; } + virtual bool isUserType() const { return userType; } + virtual const TConstUnionArray& getConstArray() const { return constArray; } + virtual TConstUnionArray& getWritableConstArray() { assert(writable); return constArray; } + virtual void setConstArray(const TConstUnionArray& array) { constArray = array; } + virtual void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; } + virtual TIntermTyped* getConstSubtree() const { return constSubtree; } + virtual void setAnonId(int i) { anonId = i; } + virtual int getAnonId() const { return anonId; } + + virtual void setMemberExtensions(int member, int numExts, const char* const exts[]) + { + assert(type.isStruct()); + assert(numExts > 0); + if (memberExtensions == nullptr) { + memberExtensions = NewPoolObject(memberExtensions); + memberExtensions->resize(type.getStruct()->size()); + } + for (int e = 0; e < numExts; ++e) + (*memberExtensions)[member].push_back(exts[e]); + } + virtual bool hasMemberExtensions() const { return memberExtensions != nullptr; } + virtual int getNumMemberExtensions(int member) const + { + return memberExtensions == nullptr ? 0 : (int)(*memberExtensions)[member].size(); + } + virtual const char** getMemberExtensions(int member) const { return (*memberExtensions)[member].data(); } + +#ifndef GLSLANG_WEB + virtual void dump(TInfoSink& infoSink, bool complete = false) const; +#endif + +protected: + explicit TVariable(const TVariable&); + TVariable& operator=(const TVariable&); + + TType type; + bool userType; + + // we are assuming that Pool Allocator will free the memory allocated to unionArray + // when this object is destroyed + + TConstUnionArray constArray; // for compile-time constant value + TIntermTyped* constSubtree; // for specialization constant computation + TVector* memberExtensions; // per-member extension list, allocated only when needed + int anonId; // the ID used for anonymous blocks: TODO: see if uniqueId could serve a dual purpose +}; + +// +// The function sub-class of symbols and the parser will need to +// share this definition of a function parameter. +// +struct TParameter { + TString *name; + TType* type; + TIntermTyped* defaultValue; + void copyParam(const TParameter& param) + { + if (param.name) + name = NewPoolTString(param.name->c_str()); + else + name = 0; + type = param.type->clone(); + defaultValue = param.defaultValue; + } + TBuiltInVariable getDeclaredBuiltIn() const { return type->getQualifier().declaredBuiltIn; } +}; + +// +// The function sub-class of a symbol. +// +class TFunction : public TSymbol { +public: + explicit TFunction(TOperator o) : + TSymbol(0), + op(o), + defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0) { } + TFunction(const TString *name, const TType& retType, TOperator tOp = EOpNull) : + TSymbol(name), + mangledName(*name + '('), + op(tOp), + defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0) + { + returnType.shallowCopy(retType); + declaredBuiltIn = retType.getQualifier().builtIn; + } + virtual TFunction* clone() const override; + virtual ~TFunction(); + + virtual TFunction* getAsFunction() override { return this; } + virtual const TFunction* getAsFunction() const override { return this; } + + // Install 'p' as the (non-'this') last parameter. + // Non-'this' parameters are reflected in both the list of parameters and the + // mangled name. + virtual void addParameter(TParameter& p) + { + assert(writable); + parameters.push_back(p); + p.type->appendMangledName(mangledName); + + if (p.defaultValue != nullptr) + defaultParamCount++; + } + + // Install 'this' as the first parameter. + // 'this' is reflected in the list of parameters, but not the mangled name. + virtual void addThisParameter(TType& type, const char* name) + { + TParameter p = { NewPoolTString(name), new TType, nullptr }; + p.type->shallowCopy(type); + parameters.insert(parameters.begin(), p); + } + + virtual void addPrefix(const char* prefix) override + { + TSymbol::addPrefix(prefix); + mangledName.insert(0, prefix); + } + + virtual void removePrefix(const TString& prefix) + { + assert(mangledName.compare(0, prefix.size(), prefix) == 0); + mangledName.erase(0, prefix.size()); + } + + virtual const TString& getMangledName() const override { return mangledName; } + virtual const TType& getType() const override { return returnType; } + virtual TBuiltInVariable getDeclaredBuiltInType() const { return declaredBuiltIn; } + virtual TType& getWritableType() override { return returnType; } + virtual void relateToOperator(TOperator o) { assert(writable); op = o; } + virtual TOperator getBuiltInOp() const { return op; } + virtual void setDefined() { assert(writable); defined = true; } + virtual bool isDefined() const { return defined; } + virtual void setPrototyped() { assert(writable); prototyped = true; } + virtual bool isPrototyped() const { return prototyped; } + virtual void setImplicitThis() { assert(writable); implicitThis = true; } + virtual bool hasImplicitThis() const { return implicitThis; } + virtual void setIllegalImplicitThis() { assert(writable); illegalImplicitThis = true; } + virtual bool hasIllegalImplicitThis() const { return illegalImplicitThis; } + + // Return total number of parameters + virtual int getParamCount() const { return static_cast(parameters.size()); } + // Return number of parameters with default values. + virtual int getDefaultParamCount() const { return defaultParamCount; } + // Return number of fixed parameters (without default values) + virtual int getFixedParamCount() const { return getParamCount() - getDefaultParamCount(); } + + virtual TParameter& operator[](int i) { assert(writable); return parameters[i]; } + virtual const TParameter& operator[](int i) const { return parameters[i]; } + +#ifndef GLSLANG_WEB + virtual void dump(TInfoSink& infoSink, bool complete = false) const override; +#endif + +protected: + explicit TFunction(const TFunction&); + TFunction& operator=(const TFunction&); + + typedef TVector TParamList; + TParamList parameters; + TType returnType; + TBuiltInVariable declaredBuiltIn; + + TString mangledName; + TOperator op; + bool defined; + bool prototyped; + bool implicitThis; // True if this function is allowed to see all members of 'this' + bool illegalImplicitThis; // True if this function is not supposed to have access to dynamic members of 'this', + // even if it finds member variables in the symbol table. + // This is important for a static member function that has member variables in scope, + // but is not allowed to use them, or see hidden symbols instead. + int defaultParamCount; +}; + +// +// Members of anonymous blocks are a kind of TSymbol. They are not hidden in +// the symbol table behind a container; rather they are visible and point to +// their anonymous container. (The anonymous container is found through the +// member, not the other way around.) +// +class TAnonMember : public TSymbol { +public: + TAnonMember(const TString* n, unsigned int m, TVariable& a, int an) : TSymbol(n), anonContainer(a), memberNumber(m), anonId(an) { } + virtual TAnonMember* clone() const override; + virtual ~TAnonMember() { } + + virtual const TAnonMember* getAsAnonMember() const override { return this; } + virtual const TVariable& getAnonContainer() const { return anonContainer; } + virtual unsigned int getMemberNumber() const { return memberNumber; } + + virtual const TType& getType() const override + { + const TTypeList& types = *anonContainer.getType().getStruct(); + return *types[memberNumber].type; + } + + virtual TType& getWritableType() override + { + assert(writable); + const TTypeList& types = *anonContainer.getType().getStruct(); + return *types[memberNumber].type; + } + + virtual void setExtensions(int numExts, const char* const exts[]) override + { + anonContainer.setMemberExtensions(memberNumber, numExts, exts); + } + virtual int getNumExtensions() const override { return anonContainer.getNumMemberExtensions(memberNumber); } + virtual const char** getExtensions() const override { return anonContainer.getMemberExtensions(memberNumber); } + + virtual int getAnonId() const { return anonId; } +#ifndef GLSLANG_WEB + virtual void dump(TInfoSink& infoSink, bool complete = false) const override; +#endif + +protected: + explicit TAnonMember(const TAnonMember&); + TAnonMember& operator=(const TAnonMember&); + + TVariable& anonContainer; + unsigned int memberNumber; + int anonId; +}; + +class TSymbolTableLevel { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + TSymbolTableLevel() : defaultPrecision(0), anonId(0), thisLevel(false) { } + ~TSymbolTableLevel(); + + bool insert(TSymbol& symbol, bool separateNameSpaces) + { + // + // returning true means symbol was added to the table with no semantic errors + // + const TString& name = symbol.getName(); + if (name == "") { + symbol.getAsVariable()->setAnonId(anonId++); + // An empty name means an anonymous container, exposing its members to the external scope. + // Give it a name and insert its members in the symbol table, pointing to the container. + char buf[20]; + snprintf(buf, 20, "%s%d", AnonymousPrefix, symbol.getAsVariable()->getAnonId()); + symbol.changeName(NewPoolTString(buf)); + + return insertAnonymousMembers(symbol, 0); + } else { + // Check for redefinition errors: + // - STL itself will tell us if there is a direct name collision, with name mangling, at this level + // - additionally, check for function-redefining-variable name collisions + const TString& insertName = symbol.getMangledName(); + if (symbol.getAsFunction()) { + // make sure there isn't a variable of this name + if (! separateNameSpaces && level.find(name) != level.end()) + return false; + + // insert, and whatever happens is okay + level.insert(tLevelPair(insertName, &symbol)); + + return true; + } else + return level.insert(tLevelPair(insertName, &symbol)).second; + } + } + + // Add more members to an already inserted aggregate object + bool amend(TSymbol& symbol, int firstNewMember) + { + // See insert() for comments on basic explanation of insert. + // This operates similarly, but more simply. + // Only supporting amend of anonymous blocks so far. + if (IsAnonymous(symbol.getName())) + return insertAnonymousMembers(symbol, firstNewMember); + else + return false; + } + + bool insertAnonymousMembers(TSymbol& symbol, int firstMember) + { + const TTypeList& types = *symbol.getAsVariable()->getType().getStruct(); + for (unsigned int m = firstMember; m < types.size(); ++m) { + TAnonMember* member = new TAnonMember(&types[m].type->getFieldName(), m, *symbol.getAsVariable(), symbol.getAsVariable()->getAnonId()); + if (! level.insert(tLevelPair(member->getMangledName(), member)).second) + return false; + } + + return true; + } + + TSymbol* find(const TString& name) const + { + tLevel::const_iterator it = level.find(name); + if (it == level.end()) + return 0; + else + return (*it).second; + } + + void findFunctionNameList(const TString& name, TVector& list) + { + size_t parenAt = name.find_first_of('('); + TString base(name, 0, parenAt + 1); + + tLevel::const_iterator begin = level.lower_bound(base); + base[parenAt] = ')'; // assume ')' is lexically after '(' + tLevel::const_iterator end = level.upper_bound(base); + for (tLevel::const_iterator it = begin; it != end; ++it) + list.push_back(it->second->getAsFunction()); + } + + // See if there is already a function in the table having the given non-function-style name. + bool hasFunctionName(const TString& name) const + { + tLevel::const_iterator candidate = level.lower_bound(name); + if (candidate != level.end()) { + const TString& candidateName = (*candidate).first; + TString::size_type parenAt = candidateName.find_first_of('('); + if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0) + + return true; + } + + return false; + } + + // See if there is a variable at this level having the given non-function-style name. + // Return true if name is found, and set variable to true if the name was a variable. + bool findFunctionVariableName(const TString& name, bool& variable) const + { + tLevel::const_iterator candidate = level.lower_bound(name); + if (candidate != level.end()) { + const TString& candidateName = (*candidate).first; + TString::size_type parenAt = candidateName.find_first_of('('); + if (parenAt == candidateName.npos) { + // not a mangled name + if (candidateName == name) { + // found a variable name match + variable = true; + return true; + } + } else { + // a mangled name + if (candidateName.compare(0, parenAt, name) == 0) { + // found a function name match + variable = false; + return true; + } + } + } + + return false; + } + + // Use this to do a lazy 'push' of precision defaults the first time + // a precision statement is seen in a new scope. Leave it at 0 for + // when no push was needed. Thus, it is not the current defaults, + // it is what to restore the defaults to when popping a level. + void setPreviousDefaultPrecisions(const TPrecisionQualifier *p) + { + // can call multiple times at one scope, will only latch on first call, + // as we're tracking the previous scope's values, not the current values + if (defaultPrecision != 0) + return; + + defaultPrecision = new TPrecisionQualifier[EbtNumTypes]; + for (int t = 0; t < EbtNumTypes; ++t) + defaultPrecision[t] = p[t]; + } + + void getPreviousDefaultPrecisions(TPrecisionQualifier *p) + { + // can be called for table level pops that didn't set the + // defaults + if (defaultPrecision == 0 || p == 0) + return; + + for (int t = 0; t < EbtNumTypes; ++t) + p[t] = defaultPrecision[t]; + } + + void relateToOperator(const char* name, TOperator op); + void setFunctionExtensions(const char* name, int num, const char* const extensions[]); +#ifndef GLSLANG_WEB + void dump(TInfoSink& infoSink, bool complete = false) const; +#endif + TSymbolTableLevel* clone() const; + void readOnly(); + + void setThisLevel() { thisLevel = true; } + bool isThisLevel() const { return thisLevel; } + +protected: + explicit TSymbolTableLevel(TSymbolTableLevel&); + TSymbolTableLevel& operator=(TSymbolTableLevel&); + + typedef std::map, pool_allocator > > tLevel; + typedef const tLevel::value_type tLevelPair; + typedef std::pair tInsertResult; + + tLevel level; // named mappings + TPrecisionQualifier *defaultPrecision; + int anonId; + bool thisLevel; // True if this level of the symbol table is a structure scope containing member function + // that are supposed to see anonymous access to member variables. +}; + +class TSymbolTable { +public: + TSymbolTable() : uniqueId(0), noBuiltInRedeclarations(false), separateNameSpaces(false), adoptedLevels(0) + { + // + // This symbol table cannot be used until push() is called. + // + } + ~TSymbolTable() + { + // this can be called explicitly; safest to code it so it can be called multiple times + + // don't deallocate levels passed in from elsewhere + while (table.size() > adoptedLevels) + pop(0); + } + + void adoptLevels(TSymbolTable& symTable) + { + for (unsigned int level = 0; level < symTable.table.size(); ++level) { + table.push_back(symTable.table[level]); + ++adoptedLevels; + } + uniqueId = symTable.uniqueId; + noBuiltInRedeclarations = symTable.noBuiltInRedeclarations; + separateNameSpaces = symTable.separateNameSpaces; + } + + // + // While level adopting is generic, the methods below enact a the following + // convention for levels: + // 0: common built-ins shared across all stages, all compiles, only one copy for all symbol tables + // 1: per-stage built-ins, shared across all compiles, but a different copy per stage + // 2: built-ins specific to a compile, like resources that are context-dependent, or redeclared built-ins + // 3: user-shader globals + // +protected: + static const int globalLevel = 3; + bool isSharedLevel(int level) { return level <= 1; } // exclude all per-compile levels + bool isBuiltInLevel(int level) { return level <= 2; } // exclude user globals + bool isGlobalLevel(int level) { return level <= globalLevel; } // include user globals +public: + bool isEmpty() { return table.size() == 0; } + bool atBuiltInLevel() { return isBuiltInLevel(currentLevel()); } + bool atGlobalLevel() { return isGlobalLevel(currentLevel()); } + + void setNoBuiltInRedeclarations() { noBuiltInRedeclarations = true; } + void setSeparateNameSpaces() { separateNameSpaces = true; } + + void push() + { + table.push_back(new TSymbolTableLevel); + } + + // Make a new symbol-table level to represent the scope introduced by a structure + // containing member functions, such that the member functions can find anonymous + // references to member variables. + // + // 'thisSymbol' should have a name of "" to trigger anonymous structure-member + // symbol finds. + void pushThis(TSymbol& thisSymbol) + { + assert(thisSymbol.getName().size() == 0); + table.push_back(new TSymbolTableLevel); + table.back()->setThisLevel(); + insert(thisSymbol); + } + + void pop(TPrecisionQualifier *p) + { + table[currentLevel()]->getPreviousDefaultPrecisions(p); + delete table.back(); + table.pop_back(); + } + + // + // Insert a visible symbol into the symbol table so it can + // be found later by name. + // + // Returns false if the was a name collision. + // + bool insert(TSymbol& symbol) + { + symbol.setUniqueId(++uniqueId); + + // make sure there isn't a function of this variable name + if (! separateNameSpaces && ! symbol.getAsFunction() && table[currentLevel()]->hasFunctionName(symbol.getName())) + return false; + + // check for not overloading or redefining a built-in function + if (noBuiltInRedeclarations) { + if (atGlobalLevel() && currentLevel() > 0) { + if (table[0]->hasFunctionName(symbol.getName())) + return false; + if (currentLevel() > 1 && table[1]->hasFunctionName(symbol.getName())) + return false; + } + } + + return table[currentLevel()]->insert(symbol, separateNameSpaces); + } + + // Add more members to an already inserted aggregate object + bool amend(TSymbol& symbol, int firstNewMember) + { + // See insert() for comments on basic explanation of insert. + // This operates similarly, but more simply. + return table[currentLevel()]->amend(symbol, firstNewMember); + } + + // + // To allocate an internal temporary, which will need to be uniquely + // identified by the consumer of the AST, but never need to + // found by doing a symbol table search by name, hence allowed an + // arbitrary name in the symbol with no worry of collision. + // + void makeInternalVariable(TSymbol& symbol) + { + symbol.setUniqueId(++uniqueId); + } + + // + // Copy a variable or anonymous member's structure from a shared level so that + // it can be added (soon after return) to the symbol table where it can be + // modified without impacting other users of the shared table. + // + TSymbol* copyUpDeferredInsert(TSymbol* shared) + { + if (shared->getAsVariable()) { + TSymbol* copy = shared->clone(); + copy->setUniqueId(shared->getUniqueId()); + return copy; + } else { + const TAnonMember* anon = shared->getAsAnonMember(); + assert(anon); + TVariable* container = anon->getAnonContainer().clone(); + container->changeName(NewPoolTString("")); + container->setUniqueId(anon->getAnonContainer().getUniqueId()); + return container; + } + } + + TSymbol* copyUp(TSymbol* shared) + { + TSymbol* copy = copyUpDeferredInsert(shared); + table[globalLevel]->insert(*copy, separateNameSpaces); + if (shared->getAsVariable()) + return copy; + else { + // return the copy of the anonymous member + return table[globalLevel]->find(shared->getName()); + } + } + + // Normal find of a symbol, that can optionally say whether the symbol was found + // at a built-in level or the current top-scope level. + TSymbol* find(const TString& name, bool* builtIn = 0, bool* currentScope = 0, int* thisDepthP = 0) + { + int level = currentLevel(); + TSymbol* symbol; + int thisDepth = 0; + do { + if (table[level]->isThisLevel()) + ++thisDepth; + symbol = table[level]->find(name); + --level; + } while (symbol == nullptr && level >= 0); + level++; + if (builtIn) + *builtIn = isBuiltInLevel(level); + if (currentScope) + *currentScope = isGlobalLevel(currentLevel()) || level == currentLevel(); // consider shared levels as "current scope" WRT user globals + if (thisDepthP != nullptr) { + if (! table[level]->isThisLevel()) + thisDepth = 0; + *thisDepthP = thisDepth; + } + + return symbol; + } + + // Find of a symbol that returns how many layers deep of nested + // structures-with-member-functions ('this' scopes) deep the symbol was + // found in. + TSymbol* find(const TString& name, int& thisDepth) + { + int level = currentLevel(); + TSymbol* symbol; + thisDepth = 0; + do { + if (table[level]->isThisLevel()) + ++thisDepth; + symbol = table[level]->find(name); + --level; + } while (symbol == 0 && level >= 0); + + if (! table[level + 1]->isThisLevel()) + thisDepth = 0; + + return symbol; + } + + bool isFunctionNameVariable(const TString& name) const + { + if (separateNameSpaces) + return false; + + int level = currentLevel(); + do { + bool variable; + bool found = table[level]->findFunctionVariableName(name, variable); + if (found) + return variable; + --level; + } while (level >= 0); + + return false; + } + + void findFunctionNameList(const TString& name, TVector& list, bool& builtIn) + { + // For user levels, return the set found in the first scope with a match + builtIn = false; + int level = currentLevel(); + do { + table[level]->findFunctionNameList(name, list); + --level; + } while (list.empty() && level >= globalLevel); + + if (! list.empty()) + return; + + // Gather across all built-in levels; they don't hide each other + builtIn = true; + do { + table[level]->findFunctionNameList(name, list); + --level; + } while (level >= 0); + } + + void relateToOperator(const char* name, TOperator op) + { + for (unsigned int level = 0; level < table.size(); ++level) + table[level]->relateToOperator(name, op); + } + + void setFunctionExtensions(const char* name, int num, const char* const extensions[]) + { + for (unsigned int level = 0; level < table.size(); ++level) + table[level]->setFunctionExtensions(name, num, extensions); + } + + void setVariableExtensions(const char* name, int numExts, const char* const extensions[]) + { + TSymbol* symbol = find(TString(name)); + if (symbol == nullptr) + return; + + symbol->setExtensions(numExts, extensions); + } + + void setVariableExtensions(const char* blockName, const char* name, int numExts, const char* const extensions[]) + { + TSymbol* symbol = find(TString(blockName)); + if (symbol == nullptr) + return; + TVariable* variable = symbol->getAsVariable(); + assert(variable != nullptr); + + const TTypeList& structure = *variable->getAsVariable()->getType().getStruct(); + for (int member = 0; member < (int)structure.size(); ++member) { + if (structure[member].type->getFieldName().compare(name) == 0) { + variable->setMemberExtensions(member, numExts, extensions); + return; + } + } + } + + int getMaxSymbolId() { return uniqueId; } +#ifndef GLSLANG_WEB + void dump(TInfoSink& infoSink, bool complete = false) const; +#endif + void copyTable(const TSymbolTable& copyOf); + + void setPreviousDefaultPrecisions(TPrecisionQualifier *p) { table[currentLevel()]->setPreviousDefaultPrecisions(p); } + + void readOnly() + { + for (unsigned int level = 0; level < table.size(); ++level) + table[level]->readOnly(); + } + +protected: + TSymbolTable(TSymbolTable&); + TSymbolTable& operator=(TSymbolTableLevel&); + + int currentLevel() const { return static_cast(table.size()) - 1; } + + std::vector table; + int uniqueId; // for unique identification in code generation + bool noBuiltInRedeclarations; + bool separateNameSpaces; + unsigned int adoptedLevels; +}; + +} // end namespace glslang + +#endif // _SYMBOL_TABLE_INCLUDED_ diff --git a/android/arm64-v8a/include/glslang/glslang/MachineIndependent/Versions.h b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/Versions.h new file mode 100644 index 00000000..98a88e1d --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/Versions.h @@ -0,0 +1,327 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 LunarG, Inc. +// Copyright (C) 2017 ARM Limited. +// Copyright (C) 2015-2018 Google, Inc. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +#ifndef _VERSIONS_INCLUDED_ +#define _VERSIONS_INCLUDED_ + +#define LAST_ELEMENT_MARKER(x) x + +// +// Help manage multiple profiles, versions, extensions etc. +// + +// +// Profiles are set up for masking operations, so queries can be done on multiple +// profiles at the same time. +// +// Don't maintain an ordinal set of enums (0,1,2,3...) to avoid all possible +// defects from mixing the two different forms. +// +typedef enum { + EBadProfile = 0, + ENoProfile = (1 << 0), // only for desktop, before profiles showed up + ECoreProfile = (1 << 1), + ECompatibilityProfile = (1 << 2), + EEsProfile = (1 << 3), + LAST_ELEMENT_MARKER(EProfileCount), +} EProfile; + +namespace glslang { + +// +// Map from profile enum to externally readable text name. +// +inline const char* ProfileName(EProfile profile) +{ + switch (profile) { + case ENoProfile: return "none"; + case ECoreProfile: return "core"; + case ECompatibilityProfile: return "compatibility"; + case EEsProfile: return "es"; + default: return "unknown profile"; + } +} + +// +// What source rules, validation rules, target language, etc. are needed or +// desired for SPIR-V? +// +// 0 means a target or rule set is not enabled (ignore rules from that entity). +// Non-0 means to apply semantic rules arising from that version of its rule set. +// The union of all requested rule sets will be applied. +// +struct SpvVersion { + SpvVersion() : spv(0), vulkanGlsl(0), vulkan(0), openGl(0) {} + unsigned int spv; // the version of SPIR-V to target, as defined by "word 1" of the SPIR-V binary header + int vulkanGlsl; // the version of GLSL semantics for Vulkan, from GL_KHR_vulkan_glsl, for "#define VULKAN XXX" + int vulkan; // the version of Vulkan, for which SPIR-V execution environment rules to use + int openGl; // the version of GLSL semantics for OpenGL, from GL_ARB_gl_spirv, for "#define GL_SPIRV XXX" +}; + +// +// The behaviors from the GLSL "#extension extension_name : behavior" +// +typedef enum { + EBhMissing = 0, + EBhRequire, + EBhEnable, + EBhWarn, + EBhDisable, + EBhDisablePartial // use as initial state of an extension that is only partially implemented +} TExtensionBehavior; + +// +// Symbolic names for extensions. Strings may be directly used when calling the +// functions, but better to have the compiler do spelling checks. +// +const char* const E_GL_OES_texture_3D = "GL_OES_texture_3D"; +const char* const E_GL_OES_standard_derivatives = "GL_OES_standard_derivatives"; +const char* const E_GL_EXT_frag_depth = "GL_EXT_frag_depth"; +const char* const E_GL_OES_EGL_image_external = "GL_OES_EGL_image_external"; +const char* const E_GL_OES_EGL_image_external_essl3 = "GL_OES_EGL_image_external_essl3"; +const char* const E_GL_EXT_YUV_target = "GL_EXT_YUV_target"; +const char* const E_GL_EXT_shader_texture_lod = "GL_EXT_shader_texture_lod"; +const char* const E_GL_EXT_shadow_samplers = "GL_EXT_shadow_samplers"; + +const char* const E_GL_ARB_texture_rectangle = "GL_ARB_texture_rectangle"; +const char* const E_GL_3DL_array_objects = "GL_3DL_array_objects"; +const char* const E_GL_ARB_shading_language_420pack = "GL_ARB_shading_language_420pack"; +const char* const E_GL_ARB_texture_gather = "GL_ARB_texture_gather"; +const char* const E_GL_ARB_gpu_shader5 = "GL_ARB_gpu_shader5"; +const char* const E_GL_ARB_separate_shader_objects = "GL_ARB_separate_shader_objects"; +const char* const E_GL_ARB_compute_shader = "GL_ARB_compute_shader"; +const char* const E_GL_ARB_tessellation_shader = "GL_ARB_tessellation_shader"; +const char* const E_GL_ARB_enhanced_layouts = "GL_ARB_enhanced_layouts"; +const char* const E_GL_ARB_texture_cube_map_array = "GL_ARB_texture_cube_map_array"; +const char* const E_GL_ARB_texture_multisample = "GL_ARB_texture_multisample"; +const char* const E_GL_ARB_shader_texture_lod = "GL_ARB_shader_texture_lod"; +const char* const E_GL_ARB_explicit_attrib_location = "GL_ARB_explicit_attrib_location"; +const char* const E_GL_ARB_explicit_uniform_location = "GL_ARB_explicit_uniform_location"; +const char* const E_GL_ARB_shader_image_load_store = "GL_ARB_shader_image_load_store"; +const char* const E_GL_ARB_shader_atomic_counters = "GL_ARB_shader_atomic_counters"; +const char* const E_GL_ARB_shader_draw_parameters = "GL_ARB_shader_draw_parameters"; +const char* const E_GL_ARB_shader_group_vote = "GL_ARB_shader_group_vote"; +const char* const E_GL_ARB_derivative_control = "GL_ARB_derivative_control"; +const char* const E_GL_ARB_shader_texture_image_samples = "GL_ARB_shader_texture_image_samples"; +const char* const E_GL_ARB_viewport_array = "GL_ARB_viewport_array"; +const char* const E_GL_ARB_gpu_shader_int64 = "GL_ARB_gpu_shader_int64"; +const char* const E_GL_ARB_gpu_shader_fp64 = "GL_ARB_gpu_shader_fp64"; +const char* const E_GL_ARB_shader_ballot = "GL_ARB_shader_ballot"; +const char* const E_GL_ARB_sparse_texture2 = "GL_ARB_sparse_texture2"; +const char* const E_GL_ARB_sparse_texture_clamp = "GL_ARB_sparse_texture_clamp"; +const char* const E_GL_ARB_shader_stencil_export = "GL_ARB_shader_stencil_export"; +// const char* const E_GL_ARB_cull_distance = "GL_ARB_cull_distance"; // present for 4.5, but need extension control over block members +const char* const E_GL_ARB_post_depth_coverage = "GL_ARB_post_depth_coverage"; +const char* const E_GL_ARB_shader_viewport_layer_array = "GL_ARB_shader_viewport_layer_array"; +const char* const E_GL_ARB_fragment_shader_interlock = "GL_ARB_fragment_shader_interlock"; +const char* const E_GL_ARB_shader_clock = "GL_ARB_shader_clock"; +const char* const E_GL_ARB_uniform_buffer_object = "GL_ARB_uniform_buffer_object"; +const char* const E_GL_ARB_sample_shading = "GL_ARB_sample_shading"; +const char* const E_GL_ARB_shader_bit_encoding = "GL_ARB_shader_bit_encoding"; +const char* const E_GL_ARB_shader_image_size = "GL_ARB_shader_image_size"; +const char* const E_GL_ARB_shader_storage_buffer_object = "GL_ARB_shader_storage_buffer_object"; +const char* const E_GL_ARB_shading_language_packing = "GL_ARB_shading_language_packing"; +const char* const E_GL_ARB_texture_query_lod = "GL_ARB_texture_query_lod"; + +const char* const E_GL_KHR_shader_subgroup_basic = "GL_KHR_shader_subgroup_basic"; +const char* const E_GL_KHR_shader_subgroup_vote = "GL_KHR_shader_subgroup_vote"; +const char* const E_GL_KHR_shader_subgroup_arithmetic = "GL_KHR_shader_subgroup_arithmetic"; +const char* const E_GL_KHR_shader_subgroup_ballot = "GL_KHR_shader_subgroup_ballot"; +const char* const E_GL_KHR_shader_subgroup_shuffle = "GL_KHR_shader_subgroup_shuffle"; +const char* const E_GL_KHR_shader_subgroup_shuffle_relative = "GL_KHR_shader_subgroup_shuffle_relative"; +const char* const E_GL_KHR_shader_subgroup_clustered = "GL_KHR_shader_subgroup_clustered"; +const char* const E_GL_KHR_shader_subgroup_quad = "GL_KHR_shader_subgroup_quad"; +const char* const E_GL_KHR_memory_scope_semantics = "GL_KHR_memory_scope_semantics"; + +const char* const E_GL_EXT_shader_atomic_int64 = "GL_EXT_shader_atomic_int64"; + +const char* const E_GL_EXT_shader_non_constant_global_initializers = "GL_EXT_shader_non_constant_global_initializers"; +const char* const E_GL_EXT_shader_image_load_formatted = "GL_EXT_shader_image_load_formatted"; + +const char* const E_GL_EXT_shader_16bit_storage = "GL_EXT_shader_16bit_storage"; +const char* const E_GL_EXT_shader_8bit_storage = "GL_EXT_shader_8bit_storage"; + + +// EXT extensions +const char* const E_GL_EXT_device_group = "GL_EXT_device_group"; +const char* const E_GL_EXT_multiview = "GL_EXT_multiview"; +const char* const E_GL_EXT_post_depth_coverage = "GL_EXT_post_depth_coverage"; +const char* const E_GL_EXT_control_flow_attributes = "GL_EXT_control_flow_attributes"; +const char* const E_GL_EXT_nonuniform_qualifier = "GL_EXT_nonuniform_qualifier"; +const char* const E_GL_EXT_samplerless_texture_functions = "GL_EXT_samplerless_texture_functions"; +const char* const E_GL_EXT_scalar_block_layout = "GL_EXT_scalar_block_layout"; +const char* const E_GL_EXT_fragment_invocation_density = "GL_EXT_fragment_invocation_density"; +const char* const E_GL_EXT_buffer_reference = "GL_EXT_buffer_reference"; +const char* const E_GL_EXT_buffer_reference2 = "GL_EXT_buffer_reference2"; +const char* const E_GL_EXT_buffer_reference_uvec2 = "GL_EXT_buffer_reference_uvec2"; +const char* const E_GL_EXT_demote_to_helper_invocation = "GL_EXT_demote_to_helper_invocation"; +const char* const E_GL_EXT_shader_realtime_clock = "GL_EXT_shader_realtime_clock"; +const char* const E_GL_EXT_debug_printf = "GL_EXT_debug_printf"; +const char* const E_GL_EXT_ray_tracing = "GL_EXT_ray_tracing"; +const char* const E_GL_EXT_ray_query = "GL_EXT_ray_query"; +const char* const E_GL_EXT_ray_flags_primitive_culling = "GL_EXT_ray_flags_primitive_culling"; + +// Arrays of extensions for the above viewportEXTs duplications + +const char* const post_depth_coverageEXTs[] = { E_GL_ARB_post_depth_coverage, E_GL_EXT_post_depth_coverage }; +const int Num_post_depth_coverageEXTs = sizeof(post_depth_coverageEXTs) / sizeof(post_depth_coverageEXTs[0]); + +// OVR extensions +const char* const E_GL_OVR_multiview = "GL_OVR_multiview"; +const char* const E_GL_OVR_multiview2 = "GL_OVR_multiview2"; + +const char* const OVR_multiview_EXTs[] = { E_GL_OVR_multiview, E_GL_OVR_multiview2 }; +const int Num_OVR_multiview_EXTs = sizeof(OVR_multiview_EXTs) / sizeof(OVR_multiview_EXTs[0]); + +// #line and #include +const char* const E_GL_GOOGLE_cpp_style_line_directive = "GL_GOOGLE_cpp_style_line_directive"; +const char* const E_GL_GOOGLE_include_directive = "GL_GOOGLE_include_directive"; + +const char* const E_GL_AMD_shader_ballot = "GL_AMD_shader_ballot"; +const char* const E_GL_AMD_shader_trinary_minmax = "GL_AMD_shader_trinary_minmax"; +const char* const E_GL_AMD_shader_explicit_vertex_parameter = "GL_AMD_shader_explicit_vertex_parameter"; +const char* const E_GL_AMD_gcn_shader = "GL_AMD_gcn_shader"; +const char* const E_GL_AMD_gpu_shader_half_float = "GL_AMD_gpu_shader_half_float"; +const char* const E_GL_AMD_texture_gather_bias_lod = "GL_AMD_texture_gather_bias_lod"; +const char* const E_GL_AMD_gpu_shader_int16 = "GL_AMD_gpu_shader_int16"; +const char* const E_GL_AMD_shader_image_load_store_lod = "GL_AMD_shader_image_load_store_lod"; +const char* const E_GL_AMD_shader_fragment_mask = "GL_AMD_shader_fragment_mask"; +const char* const E_GL_AMD_gpu_shader_half_float_fetch = "GL_AMD_gpu_shader_half_float_fetch"; + +const char* const E_GL_INTEL_shader_integer_functions2 = "GL_INTEL_shader_integer_functions2"; + +const char* const E_GL_NV_sample_mask_override_coverage = "GL_NV_sample_mask_override_coverage"; +const char* const E_SPV_NV_geometry_shader_passthrough = "GL_NV_geometry_shader_passthrough"; +const char* const E_GL_NV_viewport_array2 = "GL_NV_viewport_array2"; +const char* const E_GL_NV_stereo_view_rendering = "GL_NV_stereo_view_rendering"; +const char* const E_GL_NVX_multiview_per_view_attributes = "GL_NVX_multiview_per_view_attributes"; +const char* const E_GL_NV_shader_atomic_int64 = "GL_NV_shader_atomic_int64"; +const char* const E_GL_NV_conservative_raster_underestimation = "GL_NV_conservative_raster_underestimation"; +const char* const E_GL_NV_shader_noperspective_interpolation = "GL_NV_shader_noperspective_interpolation"; +const char* const E_GL_NV_shader_subgroup_partitioned = "GL_NV_shader_subgroup_partitioned"; +const char* const E_GL_NV_shading_rate_image = "GL_NV_shading_rate_image"; +const char* const E_GL_NV_ray_tracing = "GL_NV_ray_tracing"; +const char* const E_GL_NV_fragment_shader_barycentric = "GL_NV_fragment_shader_barycentric"; +const char* const E_GL_NV_compute_shader_derivatives = "GL_NV_compute_shader_derivatives"; +const char* const E_GL_NV_shader_texture_footprint = "GL_NV_shader_texture_footprint"; +const char* const E_GL_NV_mesh_shader = "GL_NV_mesh_shader"; + +// Arrays of extensions for the above viewportEXTs duplications + +const char* const viewportEXTs[] = { E_GL_ARB_shader_viewport_layer_array, E_GL_NV_viewport_array2 }; +const int Num_viewportEXTs = sizeof(viewportEXTs) / sizeof(viewportEXTs[0]); + +const char* const E_GL_NV_cooperative_matrix = "GL_NV_cooperative_matrix"; +const char* const E_GL_NV_shader_sm_builtins = "GL_NV_shader_sm_builtins"; +const char* const E_GL_NV_integer_cooperative_matrix = "GL_NV_integer_cooperative_matrix"; + +// AEP +const char* const E_GL_ANDROID_extension_pack_es31a = "GL_ANDROID_extension_pack_es31a"; +const char* const E_GL_KHR_blend_equation_advanced = "GL_KHR_blend_equation_advanced"; +const char* const E_GL_OES_sample_variables = "GL_OES_sample_variables"; +const char* const E_GL_OES_shader_image_atomic = "GL_OES_shader_image_atomic"; +const char* const E_GL_OES_shader_multisample_interpolation = "GL_OES_shader_multisample_interpolation"; +const char* const E_GL_OES_texture_storage_multisample_2d_array = "GL_OES_texture_storage_multisample_2d_array"; +const char* const E_GL_EXT_geometry_shader = "GL_EXT_geometry_shader"; +const char* const E_GL_EXT_geometry_point_size = "GL_EXT_geometry_point_size"; +const char* const E_GL_EXT_gpu_shader5 = "GL_EXT_gpu_shader5"; +const char* const E_GL_EXT_primitive_bounding_box = "GL_EXT_primitive_bounding_box"; +const char* const E_GL_EXT_shader_io_blocks = "GL_EXT_shader_io_blocks"; +const char* const E_GL_EXT_tessellation_shader = "GL_EXT_tessellation_shader"; +const char* const E_GL_EXT_tessellation_point_size = "GL_EXT_tessellation_point_size"; +const char* const E_GL_EXT_texture_buffer = "GL_EXT_texture_buffer"; +const char* const E_GL_EXT_texture_cube_map_array = "GL_EXT_texture_cube_map_array"; + +// OES matching AEP +const char* const E_GL_OES_geometry_shader = "GL_OES_geometry_shader"; +const char* const E_GL_OES_geometry_point_size = "GL_OES_geometry_point_size"; +const char* const E_GL_OES_gpu_shader5 = "GL_OES_gpu_shader5"; +const char* const E_GL_OES_primitive_bounding_box = "GL_OES_primitive_bounding_box"; +const char* const E_GL_OES_shader_io_blocks = "GL_OES_shader_io_blocks"; +const char* const E_GL_OES_tessellation_shader = "GL_OES_tessellation_shader"; +const char* const E_GL_OES_tessellation_point_size = "GL_OES_tessellation_point_size"; +const char* const E_GL_OES_texture_buffer = "GL_OES_texture_buffer"; +const char* const E_GL_OES_texture_cube_map_array = "GL_OES_texture_cube_map_array"; + +// EXT +const char* const E_GL_EXT_shader_explicit_arithmetic_types = "GL_EXT_shader_explicit_arithmetic_types"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_int8 = "GL_EXT_shader_explicit_arithmetic_types_int8"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_int16 = "GL_EXT_shader_explicit_arithmetic_types_int16"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_int32 = "GL_EXT_shader_explicit_arithmetic_types_int32"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_int64 = "GL_EXT_shader_explicit_arithmetic_types_int64"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_float16 = "GL_EXT_shader_explicit_arithmetic_types_float16"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_float32 = "GL_EXT_shader_explicit_arithmetic_types_float32"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_float64 = "GL_EXT_shader_explicit_arithmetic_types_float64"; + +const char* const E_GL_EXT_shader_subgroup_extended_types_int8 = "GL_EXT_shader_subgroup_extended_types_int8"; +const char* const E_GL_EXT_shader_subgroup_extended_types_int16 = "GL_EXT_shader_subgroup_extended_types_int16"; +const char* const E_GL_EXT_shader_subgroup_extended_types_int64 = "GL_EXT_shader_subgroup_extended_types_int64"; +const char* const E_GL_EXT_shader_subgroup_extended_types_float16 = "GL_EXT_shader_subgroup_extended_types_float16"; + +// Arrays of extensions for the above AEP duplications + +const char* const AEP_geometry_shader[] = { E_GL_EXT_geometry_shader, E_GL_OES_geometry_shader }; +const int Num_AEP_geometry_shader = sizeof(AEP_geometry_shader)/sizeof(AEP_geometry_shader[0]); + +const char* const AEP_geometry_point_size[] = { E_GL_EXT_geometry_point_size, E_GL_OES_geometry_point_size }; +const int Num_AEP_geometry_point_size = sizeof(AEP_geometry_point_size)/sizeof(AEP_geometry_point_size[0]); + +const char* const AEP_gpu_shader5[] = { E_GL_EXT_gpu_shader5, E_GL_OES_gpu_shader5 }; +const int Num_AEP_gpu_shader5 = sizeof(AEP_gpu_shader5)/sizeof(AEP_gpu_shader5[0]); + +const char* const AEP_primitive_bounding_box[] = { E_GL_EXT_primitive_bounding_box, E_GL_OES_primitive_bounding_box }; +const int Num_AEP_primitive_bounding_box = sizeof(AEP_primitive_bounding_box)/sizeof(AEP_primitive_bounding_box[0]); + +const char* const AEP_shader_io_blocks[] = { E_GL_EXT_shader_io_blocks, E_GL_OES_shader_io_blocks }; +const int Num_AEP_shader_io_blocks = sizeof(AEP_shader_io_blocks)/sizeof(AEP_shader_io_blocks[0]); + +const char* const AEP_tessellation_shader[] = { E_GL_EXT_tessellation_shader, E_GL_OES_tessellation_shader }; +const int Num_AEP_tessellation_shader = sizeof(AEP_tessellation_shader)/sizeof(AEP_tessellation_shader[0]); + +const char* const AEP_tessellation_point_size[] = { E_GL_EXT_tessellation_point_size, E_GL_OES_tessellation_point_size }; +const int Num_AEP_tessellation_point_size = sizeof(AEP_tessellation_point_size)/sizeof(AEP_tessellation_point_size[0]); + +const char* const AEP_texture_buffer[] = { E_GL_EXT_texture_buffer, E_GL_OES_texture_buffer }; +const int Num_AEP_texture_buffer = sizeof(AEP_texture_buffer)/sizeof(AEP_texture_buffer[0]); + +const char* const AEP_texture_cube_map_array[] = { E_GL_EXT_texture_cube_map_array, E_GL_OES_texture_cube_map_array }; +const int Num_AEP_texture_cube_map_array = sizeof(AEP_texture_cube_map_array)/sizeof(AEP_texture_cube_map_array[0]); + +} // end namespace glslang + +#endif // _VERSIONS_INCLUDED_ diff --git a/android/arm64-v8a/include/glslang/glslang/MachineIndependent/attribute.h b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/attribute.h new file mode 100644 index 00000000..38a943d2 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/attribute.h @@ -0,0 +1,149 @@ +// +// Copyright (C) 2017 LunarG, Inc. +// Copyright (C) 2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _ATTRIBUTE_INCLUDED_ +#define _ATTRIBUTE_INCLUDED_ + +#include "../Include/Common.h" +#include "../Include/ConstantUnion.h" + +namespace glslang { + + enum TAttributeType { + EatNone, + EatAllow_uav_condition, + EatBranch, + EatCall, + EatDomain, + EatEarlyDepthStencil, + EatFastOpt, + EatFlatten, + EatForceCase, + EatInstance, + EatMaxTessFactor, + EatNumThreads, + EatMaxVertexCount, + EatOutputControlPoints, + EatOutputTopology, + EatPartitioning, + EatPatchConstantFunc, + EatPatchSize, + EatUnroll, + EatLoop, + EatBinding, + EatGlobalBinding, + EatLocation, + EatInputAttachment, + EatBuiltIn, + EatPushConstant, + EatConstantId, + EatDependencyInfinite, + EatDependencyLength, + EatMinIterations, + EatMaxIterations, + EatIterationMultiple, + EatPeelCount, + EatPartialCount, + EatFormatRgba32f, + EatFormatRgba16f, + EatFormatR32f, + EatFormatRgba8, + EatFormatRgba8Snorm, + EatFormatRg32f, + EatFormatRg16f, + EatFormatR11fG11fB10f, + EatFormatR16f, + EatFormatRgba16, + EatFormatRgb10A2, + EatFormatRg16, + EatFormatRg8, + EatFormatR16, + EatFormatR8, + EatFormatRgba16Snorm, + EatFormatRg16Snorm, + EatFormatRg8Snorm, + EatFormatR16Snorm, + EatFormatR8Snorm, + EatFormatRgba32i, + EatFormatRgba16i, + EatFormatRgba8i, + EatFormatR32i, + EatFormatRg32i, + EatFormatRg16i, + EatFormatRg8i, + EatFormatR16i, + EatFormatR8i, + EatFormatRgba32ui, + EatFormatRgba16ui, + EatFormatRgba8ui, + EatFormatR32ui, + EatFormatRgb10a2ui, + EatFormatRg32ui, + EatFormatRg16ui, + EatFormatRg8ui, + EatFormatR16ui, + EatFormatR8ui, + EatFormatUnknown, + EatNonWritable, + EatNonReadable + }; + + class TIntermAggregate; + + struct TAttributeArgs { + TAttributeType name; + const TIntermAggregate* args; + + // Obtain attribute as integer + // Return false if it cannot be obtained + bool getInt(int& value, int argNum = 0) const; + + // Obtain attribute as string, with optional to-lower transform + // Return false if it cannot be obtained + bool getString(TString& value, int argNum = 0, bool convertToLower = true) const; + + // How many arguments were provided to the attribute? + int size() const; + + protected: + const TConstUnion* getConstUnion(TBasicType basicType, int argNum) const; + }; + + typedef TList TAttributes; + +} // end namespace glslang + +#endif // _ATTRIBUTE_INCLUDED_ diff --git a/android/arm64-v8a/include/glslang/glslang/MachineIndependent/gl_types.h b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/gl_types.h new file mode 100644 index 00000000..b6f613bc --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/gl_types.h @@ -0,0 +1,210 @@ +/* +** Copyright (c) 2013 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +#pragma once + +#define GL_FLOAT 0x1406 +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 + +#define GL_DOUBLE 0x140A +#define GL_DOUBLE_VEC2 0x8FFC +#define GL_DOUBLE_VEC3 0x8FFD +#define GL_DOUBLE_VEC4 0x8FFE + +#define GL_INT 0x1404 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 + +#define GL_UNSIGNED_INT 0x1405 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 + +#define GL_INT64_ARB 0x140E +#define GL_INT64_VEC2_ARB 0x8FE9 +#define GL_INT64_VEC3_ARB 0x8FEA +#define GL_INT64_VEC4_ARB 0x8FEB + +#define GL_UNSIGNED_INT64_ARB 0x140F +#define GL_UNSIGNED_INT64_VEC2_ARB 0x8FE5 +#define GL_UNSIGNED_INT64_VEC3_ARB 0x8FE6 +#define GL_UNSIGNED_INT64_VEC4_ARB 0x8FE7 + +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 + +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A + +#define GL_DOUBLE_MAT2 0x8F46 +#define GL_DOUBLE_MAT3 0x8F47 +#define GL_DOUBLE_MAT4 0x8F48 +#define GL_DOUBLE_MAT2x3 0x8F49 +#define GL_DOUBLE_MAT2x4 0x8F4A +#define GL_DOUBLE_MAT3x2 0x8F4B +#define GL_DOUBLE_MAT3x4 0x8F4C +#define GL_DOUBLE_MAT4x2 0x8F4D +#define GL_DOUBLE_MAT4x3 0x8F4E + +// Those constants are borrowed from extension NV_gpu_shader5 +#define GL_FLOAT16_NV 0x8FF8 +#define GL_FLOAT16_VEC2_NV 0x8FF9 +#define GL_FLOAT16_VEC3_NV 0x8FFA +#define GL_FLOAT16_VEC4_NV 0x8FFB + +#define GL_FLOAT16_MAT2_AMD 0x91C5 +#define GL_FLOAT16_MAT3_AMD 0x91C6 +#define GL_FLOAT16_MAT4_AMD 0x91C7 +#define GL_FLOAT16_MAT2x3_AMD 0x91C8 +#define GL_FLOAT16_MAT2x4_AMD 0x91C9 +#define GL_FLOAT16_MAT3x2_AMD 0x91CA +#define GL_FLOAT16_MAT3x4_AMD 0x91CB +#define GL_FLOAT16_MAT4x2_AMD 0x91CC +#define GL_FLOAT16_MAT4x3_AMD 0x91CD + +#define GL_SAMPLER_1D 0x8B5D +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_SAMPLER_BUFFER 0x8DC2 +#define GL_SAMPLER_1D_ARRAY 0x8DC0 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_SAMPLER_1D_SHADOW 0x8B61 +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_SAMPLER_2D_RECT 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64 +#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 +#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B +#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D +#define GL_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D + +#define GL_FLOAT16_SAMPLER_1D_AMD 0x91CE +#define GL_FLOAT16_SAMPLER_2D_AMD 0x91CF +#define GL_FLOAT16_SAMPLER_3D_AMD 0x91D0 +#define GL_FLOAT16_SAMPLER_CUBE_AMD 0x91D1 +#define GL_FLOAT16_SAMPLER_2D_RECT_AMD 0x91D2 +#define GL_FLOAT16_SAMPLER_1D_ARRAY_AMD 0x91D3 +#define GL_FLOAT16_SAMPLER_2D_ARRAY_AMD 0x91D4 +#define GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_AMD 0x91D5 +#define GL_FLOAT16_SAMPLER_BUFFER_AMD 0x91D6 +#define GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_AMD 0x91D7 +#define GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_ARRAY_AMD 0x91D8 + +#define GL_FLOAT16_SAMPLER_1D_SHADOW_AMD 0x91D9 +#define GL_FLOAT16_SAMPLER_2D_SHADOW_AMD 0x91DA +#define GL_FLOAT16_SAMPLER_2D_RECT_SHADOW_AMD 0x91DB +#define GL_FLOAT16_SAMPLER_1D_ARRAY_SHADOW_AMD 0x91DC +#define GL_FLOAT16_SAMPLER_2D_ARRAY_SHADOW_AMD 0x91DD +#define GL_FLOAT16_SAMPLER_CUBE_SHADOW_AMD 0x91DE +#define GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_SHADOW_AMD 0x91DF + +#define GL_FLOAT16_IMAGE_1D_AMD 0x91E0 +#define GL_FLOAT16_IMAGE_2D_AMD 0x91E1 +#define GL_FLOAT16_IMAGE_3D_AMD 0x91E2 +#define GL_FLOAT16_IMAGE_2D_RECT_AMD 0x91E3 +#define GL_FLOAT16_IMAGE_CUBE_AMD 0x91E4 +#define GL_FLOAT16_IMAGE_1D_ARRAY_AMD 0x91E5 +#define GL_FLOAT16_IMAGE_2D_ARRAY_AMD 0x91E6 +#define GL_FLOAT16_IMAGE_CUBE_MAP_ARRAY_AMD 0x91E7 +#define GL_FLOAT16_IMAGE_BUFFER_AMD 0x91E8 +#define GL_FLOAT16_IMAGE_2D_MULTISAMPLE_AMD 0x91E9 +#define GL_FLOAT16_IMAGE_2D_MULTISAMPLE_ARRAY_AMD 0x91EA + +#define GL_INT_SAMPLER_1D 0x8DC9 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_INT_SAMPLER_2D_RECT 0x8DCD +#define GL_INT_SAMPLER_BUFFER 0x8DD0 +#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 +#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900E + +#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8 +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900F +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A + +#define GL_IMAGE_1D 0x904C +#define GL_IMAGE_2D 0x904D +#define GL_IMAGE_3D 0x904E +#define GL_IMAGE_2D_RECT 0x904F +#define GL_IMAGE_CUBE 0x9050 +#define GL_IMAGE_BUFFER 0x9051 +#define GL_IMAGE_1D_ARRAY 0x9052 +#define GL_IMAGE_2D_ARRAY 0x9053 +#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054 +#define GL_IMAGE_2D_MULTISAMPLE 0x9055 +#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056 +#define GL_INT_IMAGE_1D 0x9057 +#define GL_INT_IMAGE_2D 0x9058 +#define GL_INT_IMAGE_3D 0x9059 +#define GL_INT_IMAGE_2D_RECT 0x905A +#define GL_INT_IMAGE_CUBE 0x905B +#define GL_INT_IMAGE_BUFFER 0x905C +#define GL_INT_IMAGE_1D_ARRAY 0x905D +#define GL_INT_IMAGE_2D_ARRAY 0x905E +#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F +#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060 +#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061 +#define GL_UNSIGNED_INT_IMAGE_1D 0x9062 +#define GL_UNSIGNED_INT_IMAGE_2D 0x9063 +#define GL_UNSIGNED_INT_IMAGE_3D 0x9064 +#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065 +#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066 +#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067 +#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068 +#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069 +#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C + +#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB diff --git a/android/arm64-v8a/include/glslang/glslang/MachineIndependent/glslang_tab.cpp.h b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/glslang_tab.cpp.h new file mode 100644 index 00000000..31c8f902 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/glslang_tab.cpp.h @@ -0,0 +1,521 @@ +/* A Bison parser, made by GNU Bison 3.0.4. */ + +/* Bison interface for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +#ifndef YY_YY_GLSLANG_TAB_CPP_H_INCLUDED +# define YY_YY_GLSLANG_TAB_CPP_H_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 1 +#endif +#if YYDEBUG +extern int yydebug; +#endif + +/* Token type. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + enum yytokentype + { + CONST = 258, + BOOL = 259, + INT = 260, + UINT = 261, + FLOAT = 262, + BVEC2 = 263, + BVEC3 = 264, + BVEC4 = 265, + IVEC2 = 266, + IVEC3 = 267, + IVEC4 = 268, + UVEC2 = 269, + UVEC3 = 270, + UVEC4 = 271, + VEC2 = 272, + VEC3 = 273, + VEC4 = 274, + MAT2 = 275, + MAT3 = 276, + MAT4 = 277, + MAT2X2 = 278, + MAT2X3 = 279, + MAT2X4 = 280, + MAT3X2 = 281, + MAT3X3 = 282, + MAT3X4 = 283, + MAT4X2 = 284, + MAT4X3 = 285, + MAT4X4 = 286, + SAMPLER2D = 287, + SAMPLER3D = 288, + SAMPLERCUBE = 289, + SAMPLER2DSHADOW = 290, + SAMPLERCUBESHADOW = 291, + SAMPLER2DARRAY = 292, + SAMPLER2DARRAYSHADOW = 293, + ISAMPLER2D = 294, + ISAMPLER3D = 295, + ISAMPLERCUBE = 296, + ISAMPLER2DARRAY = 297, + USAMPLER2D = 298, + USAMPLER3D = 299, + USAMPLERCUBE = 300, + USAMPLER2DARRAY = 301, + SAMPLER = 302, + SAMPLERSHADOW = 303, + TEXTURE2D = 304, + TEXTURE3D = 305, + TEXTURECUBE = 306, + TEXTURE2DARRAY = 307, + ITEXTURE2D = 308, + ITEXTURE3D = 309, + ITEXTURECUBE = 310, + ITEXTURE2DARRAY = 311, + UTEXTURE2D = 312, + UTEXTURE3D = 313, + UTEXTURECUBE = 314, + UTEXTURE2DARRAY = 315, + ATTRIBUTE = 316, + VARYING = 317, + FLOAT16_T = 318, + FLOAT32_T = 319, + DOUBLE = 320, + FLOAT64_T = 321, + INT64_T = 322, + UINT64_T = 323, + INT32_T = 324, + UINT32_T = 325, + INT16_T = 326, + UINT16_T = 327, + INT8_T = 328, + UINT8_T = 329, + I64VEC2 = 330, + I64VEC3 = 331, + I64VEC4 = 332, + U64VEC2 = 333, + U64VEC3 = 334, + U64VEC4 = 335, + I32VEC2 = 336, + I32VEC3 = 337, + I32VEC4 = 338, + U32VEC2 = 339, + U32VEC3 = 340, + U32VEC4 = 341, + I16VEC2 = 342, + I16VEC3 = 343, + I16VEC4 = 344, + U16VEC2 = 345, + U16VEC3 = 346, + U16VEC4 = 347, + I8VEC2 = 348, + I8VEC3 = 349, + I8VEC4 = 350, + U8VEC2 = 351, + U8VEC3 = 352, + U8VEC4 = 353, + DVEC2 = 354, + DVEC3 = 355, + DVEC4 = 356, + DMAT2 = 357, + DMAT3 = 358, + DMAT4 = 359, + F16VEC2 = 360, + F16VEC3 = 361, + F16VEC4 = 362, + F16MAT2 = 363, + F16MAT3 = 364, + F16MAT4 = 365, + F32VEC2 = 366, + F32VEC3 = 367, + F32VEC4 = 368, + F32MAT2 = 369, + F32MAT3 = 370, + F32MAT4 = 371, + F64VEC2 = 372, + F64VEC3 = 373, + F64VEC4 = 374, + F64MAT2 = 375, + F64MAT3 = 376, + F64MAT4 = 377, + DMAT2X2 = 378, + DMAT2X3 = 379, + DMAT2X4 = 380, + DMAT3X2 = 381, + DMAT3X3 = 382, + DMAT3X4 = 383, + DMAT4X2 = 384, + DMAT4X3 = 385, + DMAT4X4 = 386, + F16MAT2X2 = 387, + F16MAT2X3 = 388, + F16MAT2X4 = 389, + F16MAT3X2 = 390, + F16MAT3X3 = 391, + F16MAT3X4 = 392, + F16MAT4X2 = 393, + F16MAT4X3 = 394, + F16MAT4X4 = 395, + F32MAT2X2 = 396, + F32MAT2X3 = 397, + F32MAT2X4 = 398, + F32MAT3X2 = 399, + F32MAT3X3 = 400, + F32MAT3X4 = 401, + F32MAT4X2 = 402, + F32MAT4X3 = 403, + F32MAT4X4 = 404, + F64MAT2X2 = 405, + F64MAT2X3 = 406, + F64MAT2X4 = 407, + F64MAT3X2 = 408, + F64MAT3X3 = 409, + F64MAT3X4 = 410, + F64MAT4X2 = 411, + F64MAT4X3 = 412, + F64MAT4X4 = 413, + ATOMIC_UINT = 414, + ACCSTRUCTNV = 415, + ACCSTRUCTEXT = 416, + RAYQUERYEXT = 417, + FCOOPMATNV = 418, + ICOOPMATNV = 419, + UCOOPMATNV = 420, + SAMPLERCUBEARRAY = 421, + SAMPLERCUBEARRAYSHADOW = 422, + ISAMPLERCUBEARRAY = 423, + USAMPLERCUBEARRAY = 424, + SAMPLER1D = 425, + SAMPLER1DARRAY = 426, + SAMPLER1DARRAYSHADOW = 427, + ISAMPLER1D = 428, + SAMPLER1DSHADOW = 429, + SAMPLER2DRECT = 430, + SAMPLER2DRECTSHADOW = 431, + ISAMPLER2DRECT = 432, + USAMPLER2DRECT = 433, + SAMPLERBUFFER = 434, + ISAMPLERBUFFER = 435, + USAMPLERBUFFER = 436, + SAMPLER2DMS = 437, + ISAMPLER2DMS = 438, + USAMPLER2DMS = 439, + SAMPLER2DMSARRAY = 440, + ISAMPLER2DMSARRAY = 441, + USAMPLER2DMSARRAY = 442, + SAMPLEREXTERNALOES = 443, + SAMPLEREXTERNAL2DY2YEXT = 444, + ISAMPLER1DARRAY = 445, + USAMPLER1D = 446, + USAMPLER1DARRAY = 447, + F16SAMPLER1D = 448, + F16SAMPLER2D = 449, + F16SAMPLER3D = 450, + F16SAMPLER2DRECT = 451, + F16SAMPLERCUBE = 452, + F16SAMPLER1DARRAY = 453, + F16SAMPLER2DARRAY = 454, + F16SAMPLERCUBEARRAY = 455, + F16SAMPLERBUFFER = 456, + F16SAMPLER2DMS = 457, + F16SAMPLER2DMSARRAY = 458, + F16SAMPLER1DSHADOW = 459, + F16SAMPLER2DSHADOW = 460, + F16SAMPLER1DARRAYSHADOW = 461, + F16SAMPLER2DARRAYSHADOW = 462, + F16SAMPLER2DRECTSHADOW = 463, + F16SAMPLERCUBESHADOW = 464, + F16SAMPLERCUBEARRAYSHADOW = 465, + IMAGE1D = 466, + IIMAGE1D = 467, + UIMAGE1D = 468, + IMAGE2D = 469, + IIMAGE2D = 470, + UIMAGE2D = 471, + IMAGE3D = 472, + IIMAGE3D = 473, + UIMAGE3D = 474, + IMAGE2DRECT = 475, + IIMAGE2DRECT = 476, + UIMAGE2DRECT = 477, + IMAGECUBE = 478, + IIMAGECUBE = 479, + UIMAGECUBE = 480, + IMAGEBUFFER = 481, + IIMAGEBUFFER = 482, + UIMAGEBUFFER = 483, + IMAGE1DARRAY = 484, + IIMAGE1DARRAY = 485, + UIMAGE1DARRAY = 486, + IMAGE2DARRAY = 487, + IIMAGE2DARRAY = 488, + UIMAGE2DARRAY = 489, + IMAGECUBEARRAY = 490, + IIMAGECUBEARRAY = 491, + UIMAGECUBEARRAY = 492, + IMAGE2DMS = 493, + IIMAGE2DMS = 494, + UIMAGE2DMS = 495, + IMAGE2DMSARRAY = 496, + IIMAGE2DMSARRAY = 497, + UIMAGE2DMSARRAY = 498, + F16IMAGE1D = 499, + F16IMAGE2D = 500, + F16IMAGE3D = 501, + F16IMAGE2DRECT = 502, + F16IMAGECUBE = 503, + F16IMAGE1DARRAY = 504, + F16IMAGE2DARRAY = 505, + F16IMAGECUBEARRAY = 506, + F16IMAGEBUFFER = 507, + F16IMAGE2DMS = 508, + F16IMAGE2DMSARRAY = 509, + TEXTURECUBEARRAY = 510, + ITEXTURECUBEARRAY = 511, + UTEXTURECUBEARRAY = 512, + TEXTURE1D = 513, + ITEXTURE1D = 514, + UTEXTURE1D = 515, + TEXTURE1DARRAY = 516, + ITEXTURE1DARRAY = 517, + UTEXTURE1DARRAY = 518, + TEXTURE2DRECT = 519, + ITEXTURE2DRECT = 520, + UTEXTURE2DRECT = 521, + TEXTUREBUFFER = 522, + ITEXTUREBUFFER = 523, + UTEXTUREBUFFER = 524, + TEXTURE2DMS = 525, + ITEXTURE2DMS = 526, + UTEXTURE2DMS = 527, + TEXTURE2DMSARRAY = 528, + ITEXTURE2DMSARRAY = 529, + UTEXTURE2DMSARRAY = 530, + F16TEXTURE1D = 531, + F16TEXTURE2D = 532, + F16TEXTURE3D = 533, + F16TEXTURE2DRECT = 534, + F16TEXTURECUBE = 535, + F16TEXTURE1DARRAY = 536, + F16TEXTURE2DARRAY = 537, + F16TEXTURECUBEARRAY = 538, + F16TEXTUREBUFFER = 539, + F16TEXTURE2DMS = 540, + F16TEXTURE2DMSARRAY = 541, + SUBPASSINPUT = 542, + SUBPASSINPUTMS = 543, + ISUBPASSINPUT = 544, + ISUBPASSINPUTMS = 545, + USUBPASSINPUT = 546, + USUBPASSINPUTMS = 547, + F16SUBPASSINPUT = 548, + F16SUBPASSINPUTMS = 549, + LEFT_OP = 550, + RIGHT_OP = 551, + INC_OP = 552, + DEC_OP = 553, + LE_OP = 554, + GE_OP = 555, + EQ_OP = 556, + NE_OP = 557, + AND_OP = 558, + OR_OP = 559, + XOR_OP = 560, + MUL_ASSIGN = 561, + DIV_ASSIGN = 562, + ADD_ASSIGN = 563, + MOD_ASSIGN = 564, + LEFT_ASSIGN = 565, + RIGHT_ASSIGN = 566, + AND_ASSIGN = 567, + XOR_ASSIGN = 568, + OR_ASSIGN = 569, + SUB_ASSIGN = 570, + STRING_LITERAL = 571, + LEFT_PAREN = 572, + RIGHT_PAREN = 573, + LEFT_BRACKET = 574, + RIGHT_BRACKET = 575, + LEFT_BRACE = 576, + RIGHT_BRACE = 577, + DOT = 578, + COMMA = 579, + COLON = 580, + EQUAL = 581, + SEMICOLON = 582, + BANG = 583, + DASH = 584, + TILDE = 585, + PLUS = 586, + STAR = 587, + SLASH = 588, + PERCENT = 589, + LEFT_ANGLE = 590, + RIGHT_ANGLE = 591, + VERTICAL_BAR = 592, + CARET = 593, + AMPERSAND = 594, + QUESTION = 595, + INVARIANT = 596, + HIGH_PRECISION = 597, + MEDIUM_PRECISION = 598, + LOW_PRECISION = 599, + PRECISION = 600, + PACKED = 601, + RESOURCE = 602, + SUPERP = 603, + FLOATCONSTANT = 604, + INTCONSTANT = 605, + UINTCONSTANT = 606, + BOOLCONSTANT = 607, + IDENTIFIER = 608, + TYPE_NAME = 609, + CENTROID = 610, + IN = 611, + OUT = 612, + INOUT = 613, + STRUCT = 614, + VOID = 615, + WHILE = 616, + BREAK = 617, + CONTINUE = 618, + DO = 619, + ELSE = 620, + FOR = 621, + IF = 622, + DISCARD = 623, + RETURN = 624, + SWITCH = 625, + CASE = 626, + DEFAULT = 627, + UNIFORM = 628, + SHARED = 629, + BUFFER = 630, + FLAT = 631, + SMOOTH = 632, + LAYOUT = 633, + DOUBLECONSTANT = 634, + INT16CONSTANT = 635, + UINT16CONSTANT = 636, + FLOAT16CONSTANT = 637, + INT32CONSTANT = 638, + UINT32CONSTANT = 639, + INT64CONSTANT = 640, + UINT64CONSTANT = 641, + SUBROUTINE = 642, + DEMOTE = 643, + PAYLOADNV = 644, + PAYLOADINNV = 645, + HITATTRNV = 646, + CALLDATANV = 647, + CALLDATAINNV = 648, + PAYLOADEXT = 649, + PAYLOADINEXT = 650, + HITATTREXT = 651, + CALLDATAEXT = 652, + CALLDATAINEXT = 653, + PATCH = 654, + SAMPLE = 655, + NONUNIFORM = 656, + COHERENT = 657, + VOLATILE = 658, + RESTRICT = 659, + READONLY = 660, + WRITEONLY = 661, + DEVICECOHERENT = 662, + QUEUEFAMILYCOHERENT = 663, + WORKGROUPCOHERENT = 664, + SUBGROUPCOHERENT = 665, + NONPRIVATE = 666, + SHADERCALLCOHERENT = 667, + NOPERSPECTIVE = 668, + EXPLICITINTERPAMD = 669, + PERVERTEXNV = 670, + PERPRIMITIVENV = 671, + PERVIEWNV = 672, + PERTASKNV = 673, + PRECISE = 674 + }; +#endif + +/* Value type. */ +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED + +union YYSTYPE +{ +#line 97 "glslang.y" /* yacc.c:1909 */ + + struct { + glslang::TSourceLoc loc; + union { + glslang::TString *string; + int i; + unsigned int u; + long long i64; + unsigned long long u64; + bool b; + double d; + }; + glslang::TSymbol* symbol; + } lex; + struct { + glslang::TSourceLoc loc; + glslang::TOperator op; + union { + TIntermNode* intermNode; + glslang::TIntermNodePair nodePair; + glslang::TIntermTyped* intermTypedNode; + glslang::TAttributes* attributes; + }; + union { + glslang::TPublicType type; + glslang::TFunction* function; + glslang::TParameter param; + glslang::TTypeLoc typeLine; + glslang::TTypeList* typeList; + glslang::TArraySizes* arraySizes; + glslang::TIdentifierList* identifierList; + }; + glslang::TArraySizes* typeParameters; + } interm; + +#line 510 "glslang_tab.cpp.h" /* yacc.c:1909 */ +}; + +typedef union YYSTYPE YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif + + + +int yyparse (glslang::TParseContext* pParseContext); + +#endif /* !YY_YY_GLSLANG_TAB_CPP_H_INCLUDED */ diff --git a/android/arm64-v8a/include/glslang/glslang/MachineIndependent/iomapper.h b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/iomapper.h new file mode 100644 index 00000000..13a8932b --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/iomapper.h @@ -0,0 +1,300 @@ +// +// Copyright (C) 2016 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef GLSLANG_WEB + +#ifndef _IOMAPPER_INCLUDED +#define _IOMAPPER_INCLUDED + +#include +#include "LiveTraverser.h" +#include +#include +// +// A reflection database and its interface, consistent with the OpenGL API reflection queries. +// + +class TInfoSink; + +namespace glslang { + +class TIntermediate; +struct TVarEntryInfo { + int id; + TIntermSymbol* symbol; + bool live; + int newBinding; + int newSet; + int newLocation; + int newComponent; + int newIndex; + EShLanguage stage; + struct TOrderById { + inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) { return l.id < r.id; } + }; + + struct TOrderByPriority { + // ordering: + // 1) has both binding and set + // 2) has binding but no set + // 3) has no binding but set + // 4) has no binding and no set + inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) { + const TQualifier& lq = l.symbol->getQualifier(); + const TQualifier& rq = r.symbol->getQualifier(); + + // simple rules: + // has binding gives 2 points + // has set gives 1 point + // who has the most points is more important. + int lPoints = (lq.hasBinding() ? 2 : 0) + (lq.hasSet() ? 1 : 0); + int rPoints = (rq.hasBinding() ? 2 : 0) + (rq.hasSet() ? 1 : 0); + + if (lPoints == rPoints) + return l.id < r.id; + return lPoints > rPoints; + } + }; +}; + +// Base class for shared TIoMapResolver services, used by several derivations. +struct TDefaultIoResolverBase : public glslang::TIoMapResolver { +public: + TDefaultIoResolverBase(const TIntermediate& intermediate); + typedef std::vector TSlotSet; + typedef std::unordered_map TSlotSetMap; + + // grow the reflection stage by stage + void notifyBinding(EShLanguage, TVarEntryInfo& /*ent*/) override {} + void notifyInOut(EShLanguage, TVarEntryInfo& /*ent*/) override {} + void beginNotifications(EShLanguage) override {} + void endNotifications(EShLanguage) override {} + void beginResolve(EShLanguage) override {} + void endResolve(EShLanguage) override {} + void beginCollect(EShLanguage) override {} + void endCollect(EShLanguage) override {} + void reserverResourceSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {} + void reserverStorageSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {} + int getBaseBinding(TResourceType res, unsigned int set) const; + const std::vector& getResourceSetBinding() const; + virtual TResourceType getResourceType(const glslang::TType& type) = 0; + bool doAutoBindingMapping() const; + bool doAutoLocationMapping() const; + TSlotSet::iterator findSlot(int set, int slot); + bool checkEmpty(int set, int slot); + bool validateInOut(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; } + int reserveSlot(int set, int slot, int size = 1); + int getFreeSlot(int set, int base, int size = 1); + int resolveSet(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + int resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override; + int resolveInOutComponent(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + int resolveInOutIndex(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + void addStage(EShLanguage stage) override { + if (stage < EShLangCount) + stageMask[stage] = true; + } + uint32_t computeTypeLocationSize(const TType& type, EShLanguage stage); + + TSlotSetMap slots; + bool hasError = false; + +protected: + TDefaultIoResolverBase(TDefaultIoResolverBase&); + TDefaultIoResolverBase& operator=(TDefaultIoResolverBase&); + const TIntermediate& intermediate; + int nextUniformLocation; + int nextInputLocation; + int nextOutputLocation; + bool stageMask[EShLangCount + 1]; + // Return descriptor set specific base if there is one, and the generic base otherwise. + int selectBaseBinding(int base, int descriptorSetBase) const { + return descriptorSetBase != -1 ? descriptorSetBase : base; + } + + static int getLayoutSet(const glslang::TType& type) { + if (type.getQualifier().hasSet()) + return type.getQualifier().layoutSet; + else + return 0; + } + + static bool isSamplerType(const glslang::TType& type) { + return type.getBasicType() == glslang::EbtSampler && type.getSampler().isPureSampler(); + } + + static bool isTextureType(const glslang::TType& type) { + return (type.getBasicType() == glslang::EbtSampler && + (type.getSampler().isTexture() || type.getSampler().isSubpass())); + } + + static bool isUboType(const glslang::TType& type) { + return type.getQualifier().storage == EvqUniform; + } + + static bool isImageType(const glslang::TType& type) { + return type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage(); + } + + static bool isSsboType(const glslang::TType& type) { + return type.getQualifier().storage == EvqBuffer; + } + + // Return true if this is a SRV (shader resource view) type: + static bool isSrvType(const glslang::TType& type) { + return isTextureType(type) || type.getQualifier().storage == EvqBuffer; + } + + // Return true if this is a UAV (unordered access view) type: + static bool isUavType(const glslang::TType& type) { + if (type.getQualifier().isReadOnly()) + return false; + return (type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage()) || + (type.getQualifier().storage == EvqBuffer); + } +}; + +// Defaulf I/O resolver for OpenGL +struct TDefaultGlslIoResolver : public TDefaultIoResolverBase { +public: + typedef std::map TVarSlotMap; // + typedef std::map TSlotMap; // + TDefaultGlslIoResolver(const TIntermediate& intermediate); + bool validateBinding(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; } + TResourceType getResourceType(const glslang::TType& type) override; + int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override; + int resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + int resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + void beginResolve(EShLanguage /*stage*/) override; + void endResolve(EShLanguage stage) override; + void beginCollect(EShLanguage) override; + void endCollect(EShLanguage) override; + void reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override; + void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override; + // in/out symbol and uniform symbol are stored in the same resourceSlotMap, the storage key is used to identify each type of symbol. + // We use stage and storage qualifier to construct a storage key. it can help us identify the same storage resource used in different stage. + // if a resource is a program resource and we don't need know it usage stage, we can use same stage to build storage key. + // Note: both stage and type must less then 0xffff. + int buildStorageKey(EShLanguage stage, TStorageQualifier type) { + assert(static_cast(stage) <= 0x0000ffff && static_cast(type) <= 0x0000ffff); + return (stage << 16) | type; + } + +protected: + // Use for mark pre stage, to get more interface symbol information. + EShLanguage preStage; + // Use for mark current shader stage for resolver + EShLanguage currentStage; + // Slot map for storage resource(location of uniform and interface symbol) It's a program share slot + TSlotMap resourceSlotMap; + // Slot map for other resource(image, ubo, ssbo), It's a program share slot. + TSlotMap storageSlotMap; +}; + +typedef std::map TVarLiveMap; + +// override function "operator=", if a vector being sort, +// when use vc++, the sort function will call : +// pair& operator=(const pair<_Other1, _Other2>& _Right) +// { +// first = _Right.first; +// second = _Right.second; +// return (*this); +// } +// that will make a const type handing on left. +// override this function can avoid a compiler error. +// In the future, if the vc++ compiler can handle such a situation, +// this part of the code will be removed. +struct TVarLivePair : std::pair { + TVarLivePair(std::pair& _Right) : pair(_Right.first, _Right.second) {} + TVarLivePair& operator=(const TVarLivePair& _Right) { + const_cast(first) = _Right.first; + second = _Right.second; + return (*this); + } +}; +typedef std::vector TVarLiveVector; + +// I/O mapper +class TIoMapper { +public: + TIoMapper() {} + virtual ~TIoMapper() {} + // grow the reflection stage by stage + bool virtual addStage(EShLanguage, TIntermediate&, TInfoSink&, TIoMapResolver*); + bool virtual doMap(TIoMapResolver*, TInfoSink&) { return true; } +}; + +// I/O mapper for OpenGL +class TGlslIoMapper : public TIoMapper { +public: + TGlslIoMapper() { + memset(inVarMaps, 0, sizeof(TVarLiveMap*) * EShLangCount); + memset(outVarMaps, 0, sizeof(TVarLiveMap*) * EShLangCount); + memset(uniformVarMap, 0, sizeof(TVarLiveMap*) * EShLangCount); + memset(intermediates, 0, sizeof(TIntermediate*) * EShLangCount); + } + virtual ~TGlslIoMapper() { + for (size_t stage = 0; stage < EShLangCount; stage++) { + if (inVarMaps[stage] != nullptr) { + delete inVarMaps[stage]; + inVarMaps[stage] = nullptr; + } + if (outVarMaps[stage] != nullptr) { + delete outVarMaps[stage]; + outVarMaps[stage] = nullptr; + } + if (uniformVarMap[stage] != nullptr) { + delete uniformVarMap[stage]; + uniformVarMap[stage] = nullptr; + } + if (intermediates[stage] != nullptr) + intermediates[stage] = nullptr; + } + } + // grow the reflection stage by stage + bool addStage(EShLanguage, TIntermediate&, TInfoSink&, TIoMapResolver*) override; + bool doMap(TIoMapResolver*, TInfoSink&) override; + TVarLiveMap *inVarMaps[EShLangCount], *outVarMaps[EShLangCount], + *uniformVarMap[EShLangCount]; + TIntermediate* intermediates[EShLangCount]; + bool hadError = false; +}; + +} // end namespace glslang + +#endif // _IOMAPPER_INCLUDED + +#endif // GLSLANG_WEB diff --git a/android/arm64-v8a/include/glslang/glslang/MachineIndependent/localintermediate.h b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/localintermediate.h new file mode 100644 index 00000000..66f5a88a --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/localintermediate.h @@ -0,0 +1,1013 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2016 LunarG, Inc. +// Copyright (C) 2017 ARM Limited. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _LOCAL_INTERMEDIATE_INCLUDED_ +#define _LOCAL_INTERMEDIATE_INCLUDED_ + +#include "../Include/intermediate.h" +#include "../Public/ShaderLang.h" +#include "Versions.h" + +#include +#include +#include +#include +#include + +class TInfoSink; + +namespace glslang { + +struct TMatrixSelector { + int coord1; // stay agnostic about column/row; this is parse order + int coord2; +}; + +typedef int TVectorSelector; + +const int MaxSwizzleSelectors = 4; + +template +class TSwizzleSelectors { +public: + TSwizzleSelectors() : size_(0) { } + + void push_back(selectorType comp) + { + if (size_ < MaxSwizzleSelectors) + components[size_++] = comp; + } + void resize(int s) + { + assert(s <= size_); + size_ = s; + } + int size() const { return size_; } + selectorType operator[](int i) const + { + assert(i < MaxSwizzleSelectors); + return components[i]; + } + +private: + int size_; + selectorType components[MaxSwizzleSelectors]; +}; + +// +// Some helper structures for TIntermediate. Their contents are encapsulated +// by TIntermediate. +// + +// Used for call-graph algorithms for detecting recursion, missing bodies, and dead bodies. +// A "call" is a pair: . +// There can be duplicates. General assumption is the list is small. +struct TCall { + TCall(const TString& pCaller, const TString& pCallee) : caller(pCaller), callee(pCallee) { } + TString caller; + TString callee; + bool visited; + bool currentPath; + bool errorGiven; + int calleeBodyPosition; +}; + +// A generic 1-D range. +struct TRange { + TRange(int start, int last) : start(start), last(last) { } + bool overlap(const TRange& rhs) const + { + return last >= rhs.start && start <= rhs.last; + } + int start; + int last; +}; + +// An IO range is a 3-D rectangle; the set of (location, component, index) triples all lying +// within the same location range, component range, and index value. Locations don't alias unless +// all other dimensions of their range overlap. +struct TIoRange { + TIoRange(TRange location, TRange component, TBasicType basicType, int index) + : location(location), component(component), basicType(basicType), index(index) { } + bool overlap(const TIoRange& rhs) const + { + return location.overlap(rhs.location) && component.overlap(rhs.component) && index == rhs.index; + } + TRange location; + TRange component; + TBasicType basicType; + int index; +}; + +// An offset range is a 2-D rectangle; the set of (binding, offset) pairs all lying +// within the same binding and offset range. +struct TOffsetRange { + TOffsetRange(TRange binding, TRange offset) + : binding(binding), offset(offset) { } + bool overlap(const TOffsetRange& rhs) const + { + return binding.overlap(rhs.binding) && offset.overlap(rhs.offset); + } + TRange binding; + TRange offset; +}; + +#ifndef GLSLANG_WEB +// Things that need to be tracked per xfb buffer. +struct TXfbBuffer { + TXfbBuffer() : stride(TQualifier::layoutXfbStrideEnd), implicitStride(0), contains64BitType(false), + contains32BitType(false), contains16BitType(false) { } + std::vector ranges; // byte offsets that have already been assigned + unsigned int stride; + unsigned int implicitStride; + bool contains64BitType; + bool contains32BitType; + bool contains16BitType; +}; +#endif + +// Track a set of strings describing how the module was processed. +// This includes command line options, transforms, etc., ideally inclusive enough +// to reproduce the steps used to transform the input source to the output. +// E.g., see SPIR-V OpModuleProcessed. +// Each "process" or "transform" uses is expressed in the form: +// process arg0 arg1 arg2 ... +// process arg0 arg1 arg2 ... +// where everything is textual, and there can be zero or more arguments +class TProcesses { +public: + TProcesses() {} + ~TProcesses() {} + + void addProcess(const char* process) + { + processes.push_back(process); + } + void addProcess(const std::string& process) + { + processes.push_back(process); + } + void addArgument(int arg) + { + processes.back().append(" "); + std::string argString = std::to_string(arg); + processes.back().append(argString); + } + void addArgument(const char* arg) + { + processes.back().append(" "); + processes.back().append(arg); + } + void addArgument(const std::string& arg) + { + processes.back().append(" "); + processes.back().append(arg); + } + void addIfNonZero(const char* process, int value) + { + if (value != 0) { + addProcess(process); + addArgument(value); + } + } + + const std::vector& getProcesses() const { return processes; } + +private: + std::vector processes; +}; + +class TSymbolTable; +class TSymbol; +class TVariable; + +// +// Texture and Sampler transformation mode. +// +enum ComputeDerivativeMode { + LayoutDerivativeNone, // default layout as SPV_NV_compute_shader_derivatives not enabled + LayoutDerivativeGroupQuads, // derivative_group_quadsNV + LayoutDerivativeGroupLinear, // derivative_group_linearNV +}; + +class TIdMaps { +public: + TMap& operator[](int i) { return maps[i]; } + const TMap& operator[](int i) const { return maps[i]; } +private: + TMap maps[EsiCount]; +}; + + +// +// Set of helper functions to help parse and build the tree. +// +class TIntermediate { +public: + explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) : + language(l), + profile(p), version(v), treeRoot(0), + numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false), + invertY(false), + useStorageBuffer(false), + nanMinMaxClamp(false), + depthReplacing(false) +#ifndef GLSLANG_WEB + , + implicitThisName("@this"), implicitCounterName("@count"), + source(EShSourceNone), + useVulkanMemoryModel(false), + invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet), + inputPrimitive(ElgNone), outputPrimitive(ElgNone), + pixelCenterInteger(false), originUpperLeft(false), + vertexSpacing(EvsNone), vertexOrder(EvoNone), interlockOrdering(EioNone), pointMode(false), earlyFragmentTests(false), + postDepthCoverage(false), depthLayout(EldNone), + hlslFunctionality1(false), + blendEquations(0), xfbMode(false), multiStream(false), + layoutOverrideCoverage(false), + geoPassthroughEXT(false), + numShaderRecordBlocks(0), + computeDerivativeMode(LayoutDerivativeNone), + primitives(TQualifier::layoutNotSet), + numTaskNVBlocks(0), + autoMapBindings(false), + autoMapLocations(false), + flattenUniformArrays(false), + useUnknownFormat(false), + hlslOffsets(false), + hlslIoMapping(false), + useVariablePointers(false), + textureSamplerTransformMode(EShTexSampTransKeep), + needToLegalize(false), + binaryDoubleOutput(false), + usePhysicalStorageBuffer(false), + uniformLocationBase(0) +#endif + { + localSize[0] = 1; + localSize[1] = 1; + localSize[2] = 1; + localSizeNotDefault[0] = false; + localSizeNotDefault[1] = false; + localSizeNotDefault[2] = false; + localSizeSpecId[0] = TQualifier::layoutNotSet; + localSizeSpecId[1] = TQualifier::layoutNotSet; + localSizeSpecId[2] = TQualifier::layoutNotSet; +#ifndef GLSLANG_WEB + xfbBuffers.resize(TQualifier::layoutXfbBufferEnd); + shiftBinding.fill(0); +#endif + } + + void setVersion(int v) { version = v; } + int getVersion() const { return version; } + void setProfile(EProfile p) { profile = p; } + EProfile getProfile() const { return profile; } + void setSpv(const SpvVersion& s) + { + spvVersion = s; + + // client processes + if (spvVersion.vulkan > 0) + processes.addProcess("client vulkan100"); + if (spvVersion.openGl > 0) + processes.addProcess("client opengl100"); + + // target SPV + switch (spvVersion.spv) { + case 0: + break; + case EShTargetSpv_1_0: + break; + case EShTargetSpv_1_1: + processes.addProcess("target-env spirv1.1"); + break; + case EShTargetSpv_1_2: + processes.addProcess("target-env spirv1.2"); + break; + case EShTargetSpv_1_3: + processes.addProcess("target-env spirv1.3"); + break; + case EShTargetSpv_1_4: + processes.addProcess("target-env spirv1.4"); + break; + case EShTargetSpv_1_5: + processes.addProcess("target-env spirv1.5"); + break; + default: + processes.addProcess("target-env spirvUnknown"); + break; + } + + // target-environment processes + switch (spvVersion.vulkan) { + case 0: + break; + case EShTargetVulkan_1_0: + processes.addProcess("target-env vulkan1.0"); + break; + case EShTargetVulkan_1_1: + processes.addProcess("target-env vulkan1.1"); + break; + case EShTargetVulkan_1_2: + processes.addProcess("target-env vulkan1.2"); + break; + default: + processes.addProcess("target-env vulkanUnknown"); + break; + } + if (spvVersion.openGl > 0) + processes.addProcess("target-env opengl"); + } + const SpvVersion& getSpv() const { return spvVersion; } + EShLanguage getStage() const { return language; } + void addRequestedExtension(const char* extension) { requestedExtensions.insert(extension); } + const std::set& getRequestedExtensions() const { return requestedExtensions; } + + void setTreeRoot(TIntermNode* r) { treeRoot = r; } + TIntermNode* getTreeRoot() const { return treeRoot; } + void incrementEntryPointCount() { ++numEntryPoints; } + int getNumEntryPoints() const { return numEntryPoints; } + int getNumErrors() const { return numErrors; } + void addPushConstantCount() { ++numPushConstants; } + void setLimits(const TBuiltInResource& r) { resources = r; } + + bool postProcess(TIntermNode*, EShLanguage); + void removeTree(); + + void setEntryPointName(const char* ep) + { + entryPointName = ep; + processes.addProcess("entry-point"); + processes.addArgument(entryPointName); + } + void setEntryPointMangledName(const char* ep) { entryPointMangledName = ep; } + const std::string& getEntryPointName() const { return entryPointName; } + const std::string& getEntryPointMangledName() const { return entryPointMangledName; } + + void setInvertY(bool invert) + { + invertY = invert; + if (invertY) + processes.addProcess("invert-y"); + } + bool getInvertY() const { return invertY; } + +#ifdef ENABLE_HLSL + void setSource(EShSource s) { source = s; } + EShSource getSource() const { return source; } +#else + void setSource(EShSource s) { assert(s == EShSourceGlsl); } + EShSource getSource() const { return EShSourceGlsl; } +#endif + + bool isRecursive() const { return recursive; } + + TIntermSymbol* addSymbol(const TVariable&); + TIntermSymbol* addSymbol(const TVariable&, const TSourceLoc&); + TIntermSymbol* addSymbol(const TType&, const TSourceLoc&); + TIntermSymbol* addSymbol(const TIntermSymbol&); + TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*); + std::tuple addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1); + TIntermTyped* addUniShapeConversion(TOperator, const TType&, TIntermTyped*); + TIntermTyped* addConversion(TBasicType convertTo, TIntermTyped* node) const; + void addBiShapeConversion(TOperator, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode); + TIntermTyped* addShapeConversion(const TType&, TIntermTyped*); + TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc); + TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc); + TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc); + TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, TSourceLoc); + TIntermTyped* addBuiltInFunctionCall(const TSourceLoc& line, TOperator, bool unary, TIntermNode*, const TType& returnType); + bool canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op = EOpNull) const; + bool isIntegralPromotion(TBasicType from, TBasicType to) const; + bool isFPPromotion(TBasicType from, TBasicType to) const; + bool isIntegralConversion(TBasicType from, TBasicType to) const; + bool isFPConversion(TBasicType from, TBasicType to) const; + bool isFPIntegralConversion(TBasicType from, TBasicType to) const; + TOperator mapTypeToConstructorOp(const TType&) const; + TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right); + TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&); + TIntermAggregate* makeAggregate(TIntermNode* node); + TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&); + TIntermAggregate* makeAggregate(const TSourceLoc&); + TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, TSourceLoc); + bool areAllChildConst(TIntermAggregate* aggrNode); + TIntermSelection* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&); + TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&); + TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); + TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, const TSourceLoc&); + TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(signed char, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(unsigned char, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(signed short, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(unsigned short, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(int, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(unsigned int, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(long long, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(unsigned long long, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(bool, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(double, TBasicType, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(const TString*, const TSourceLoc&, bool literal = false) const; + TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const; + bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false); + TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&); + TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, + const TSourceLoc&, TIntermLoop*&); + TIntermBranch* addBranch(TOperator, const TSourceLoc&); + TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&); + template TIntermTyped* addSwizzle(TSwizzleSelectors&, const TSourceLoc&); + + // Low level functions to add nodes (no conversions or other higher level transformations) + // If a type is provided, the node's type will be set to it. + TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc) const; + TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, const TType&) const; + TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc) const; + TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc, const TType&) const; + + // Constant folding (in Constant.cpp) + TIntermTyped* fold(TIntermAggregate* aggrNode); + TIntermTyped* foldConstructor(TIntermAggregate* aggrNode); + TIntermTyped* foldDereference(TIntermTyped* node, int index, const TSourceLoc&); + TIntermTyped* foldSwizzle(TIntermTyped* node, TSwizzleSelectors& fields, const TSourceLoc&); + + // Tree ops + static const TIntermTyped* findLValueBase(const TIntermTyped*, bool swizzleOkay); + + // Linkage related + void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&); + void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&); + + void setUseStorageBuffer() + { + useStorageBuffer = true; + processes.addProcess("use-storage-buffer"); + } + bool usingStorageBuffer() const { return useStorageBuffer; } + void setDepthReplacing() { depthReplacing = true; } + bool isDepthReplacing() const { return depthReplacing; } + bool setLocalSize(int dim, int size) + { + if (localSizeNotDefault[dim]) + return size == localSize[dim]; + localSizeNotDefault[dim] = true; + localSize[dim] = size; + return true; + } + unsigned int getLocalSize(int dim) const { return localSize[dim]; } + bool setLocalSizeSpecId(int dim, int id) + { + if (localSizeSpecId[dim] != TQualifier::layoutNotSet) + return id == localSizeSpecId[dim]; + localSizeSpecId[dim] = id; + return true; + } + int getLocalSizeSpecId(int dim) const { return localSizeSpecId[dim]; } +#ifdef GLSLANG_WEB + void output(TInfoSink&, bool tree) { } + + bool isEsProfile() const { return false; } + bool getXfbMode() const { return false; } + bool isMultiStream() const { return false; } + TLayoutGeometry getOutputPrimitive() const { return ElgNone; } + bool getPostDepthCoverage() const { return false; } + bool getEarlyFragmentTests() const { return false; } + TLayoutDepth getDepth() const { return EldNone; } + bool getPixelCenterInteger() const { return false; } + void setOriginUpperLeft() { } + bool getOriginUpperLeft() const { return true; } + TInterlockOrdering getInterlockOrdering() const { return EioNone; } + + bool getAutoMapBindings() const { return false; } + bool getAutoMapLocations() const { return false; } + int getNumPushConstants() const { return 0; } + void addShaderRecordCount() { } + void addTaskNVCount() { } + void setUseVulkanMemoryModel() { } + bool usingVulkanMemoryModel() const { return false; } + bool usingPhysicalStorageBuffer() const { return false; } + bool usingVariablePointers() const { return false; } + unsigned getXfbStride(int buffer) const { return 0; } + bool hasLayoutDerivativeModeNone() const { return false; } + ComputeDerivativeMode getLayoutDerivativeModeNone() const { return LayoutDerivativeNone; } +#else + void output(TInfoSink&, bool tree); + + bool isEsProfile() const { return profile == EEsProfile; } + + void setShiftBinding(TResourceType res, unsigned int shift) + { + shiftBinding[res] = shift; + + const char* name = getResourceName(res); + if (name != nullptr) + processes.addIfNonZero(name, shift); + } + + unsigned int getShiftBinding(TResourceType res) const { return shiftBinding[res]; } + + void setShiftBindingForSet(TResourceType res, unsigned int shift, unsigned int set) + { + if (shift == 0) // ignore if there's no shift: it's a no-op. + return; + + shiftBindingForSet[res][set] = shift; + + const char* name = getResourceName(res); + if (name != nullptr) { + processes.addProcess(name); + processes.addArgument(shift); + processes.addArgument(set); + } + } + + int getShiftBindingForSet(TResourceType res, unsigned int set) const + { + const auto shift = shiftBindingForSet[res].find(set); + return shift == shiftBindingForSet[res].end() ? -1 : shift->second; + } + bool hasShiftBindingForSet(TResourceType res) const { return !shiftBindingForSet[res].empty(); } + + void setResourceSetBinding(const std::vector& shift) + { + resourceSetBinding = shift; + if (shift.size() > 0) { + processes.addProcess("resource-set-binding"); + for (int s = 0; s < (int)shift.size(); ++s) + processes.addArgument(shift[s]); + } + } + const std::vector& getResourceSetBinding() const { return resourceSetBinding; } + void setAutoMapBindings(bool map) + { + autoMapBindings = map; + if (autoMapBindings) + processes.addProcess("auto-map-bindings"); + } + bool getAutoMapBindings() const { return autoMapBindings; } + void setAutoMapLocations(bool map) + { + autoMapLocations = map; + if (autoMapLocations) + processes.addProcess("auto-map-locations"); + } + bool getAutoMapLocations() const { return autoMapLocations; } + +#ifdef ENABLE_HLSL + void setFlattenUniformArrays(bool flatten) + { + flattenUniformArrays = flatten; + if (flattenUniformArrays) + processes.addProcess("flatten-uniform-arrays"); + } + bool getFlattenUniformArrays() const { return flattenUniformArrays; } +#endif + void setNoStorageFormat(bool b) + { + useUnknownFormat = b; + if (useUnknownFormat) + processes.addProcess("no-storage-format"); + } + bool getNoStorageFormat() const { return useUnknownFormat; } + void setUseVulkanMemoryModel() + { + useVulkanMemoryModel = true; + processes.addProcess("use-vulkan-memory-model"); + } + bool usingVulkanMemoryModel() const { return useVulkanMemoryModel; } + void setUsePhysicalStorageBuffer() + { + usePhysicalStorageBuffer = true; + } + bool usingPhysicalStorageBuffer() const { return usePhysicalStorageBuffer; } + void setUseVariablePointers() + { + useVariablePointers = true; + processes.addProcess("use-variable-pointers"); + } + bool usingVariablePointers() const { return useVariablePointers; } + +#ifdef ENABLE_HLSL + template T addCounterBufferName(const T& name) const { return name + implicitCounterName; } + bool hasCounterBufferName(const TString& name) const { + size_t len = strlen(implicitCounterName); + return name.size() > len && + name.compare(name.size() - len, len, implicitCounterName) == 0; + } +#endif + + void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; } + int getNumPushConstants() const { return numPushConstants; } + void addShaderRecordCount() { ++numShaderRecordBlocks; } + void addTaskNVCount() { ++numTaskNVBlocks; } + + bool setInvocations(int i) + { + if (invocations != TQualifier::layoutNotSet) + return invocations == i; + invocations = i; + return true; + } + int getInvocations() const { return invocations; } + bool setVertices(int m) + { + if (vertices != TQualifier::layoutNotSet) + return vertices == m; + vertices = m; + return true; + } + int getVertices() const { return vertices; } + bool setInputPrimitive(TLayoutGeometry p) + { + if (inputPrimitive != ElgNone) + return inputPrimitive == p; + inputPrimitive = p; + return true; + } + TLayoutGeometry getInputPrimitive() const { return inputPrimitive; } + bool setVertexSpacing(TVertexSpacing s) + { + if (vertexSpacing != EvsNone) + return vertexSpacing == s; + vertexSpacing = s; + return true; + } + TVertexSpacing getVertexSpacing() const { return vertexSpacing; } + bool setVertexOrder(TVertexOrder o) + { + if (vertexOrder != EvoNone) + return vertexOrder == o; + vertexOrder = o; + return true; + } + TVertexOrder getVertexOrder() const { return vertexOrder; } + void setPointMode() { pointMode = true; } + bool getPointMode() const { return pointMode; } + + bool setInterlockOrdering(TInterlockOrdering o) + { + if (interlockOrdering != EioNone) + return interlockOrdering == o; + interlockOrdering = o; + return true; + } + TInterlockOrdering getInterlockOrdering() const { return interlockOrdering; } + + void setXfbMode() { xfbMode = true; } + bool getXfbMode() const { return xfbMode; } + void setMultiStream() { multiStream = true; } + bool isMultiStream() const { return multiStream; } + bool setOutputPrimitive(TLayoutGeometry p) + { + if (outputPrimitive != ElgNone) + return outputPrimitive == p; + outputPrimitive = p; + return true; + } + TLayoutGeometry getOutputPrimitive() const { return outputPrimitive; } + void setPostDepthCoverage() { postDepthCoverage = true; } + bool getPostDepthCoverage() const { return postDepthCoverage; } + void setEarlyFragmentTests() { earlyFragmentTests = true; } + bool getEarlyFragmentTests() const { return earlyFragmentTests; } + bool setDepth(TLayoutDepth d) + { + if (depthLayout != EldNone) + return depthLayout == d; + depthLayout = d; + return true; + } + TLayoutDepth getDepth() const { return depthLayout; } + void setOriginUpperLeft() { originUpperLeft = true; } + bool getOriginUpperLeft() const { return originUpperLeft; } + void setPixelCenterInteger() { pixelCenterInteger = true; } + bool getPixelCenterInteger() const { return pixelCenterInteger; } + void addBlendEquation(TBlendEquationShift b) { blendEquations |= (1 << b); } + unsigned int getBlendEquations() const { return blendEquations; } + bool setXfbBufferStride(int buffer, unsigned stride) + { + if (xfbBuffers[buffer].stride != TQualifier::layoutXfbStrideEnd) + return xfbBuffers[buffer].stride == stride; + xfbBuffers[buffer].stride = stride; + return true; + } + unsigned getXfbStride(int buffer) const { return xfbBuffers[buffer].stride; } + int addXfbBufferOffset(const TType&); + unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType, bool& contains32BitType, bool& contains16BitType) const; + unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType) const; + void setLayoutOverrideCoverage() { layoutOverrideCoverage = true; } + bool getLayoutOverrideCoverage() const { return layoutOverrideCoverage; } + void setGeoPassthroughEXT() { geoPassthroughEXT = true; } + bool getGeoPassthroughEXT() const { return geoPassthroughEXT; } + void setLayoutDerivativeMode(ComputeDerivativeMode mode) { computeDerivativeMode = mode; } + bool hasLayoutDerivativeModeNone() const { return computeDerivativeMode != LayoutDerivativeNone; } + ComputeDerivativeMode getLayoutDerivativeModeNone() const { return computeDerivativeMode; } + bool setPrimitives(int m) + { + if (primitives != TQualifier::layoutNotSet) + return primitives == m; + primitives = m; + return true; + } + int getPrimitives() const { return primitives; } + const char* addSemanticName(const TString& name) + { + return semanticNameSet.insert(name).first->c_str(); + } + void addUniformLocationOverride(const char* nameStr, int location) + { + std::string name = nameStr; + uniformLocationOverrides[name] = location; + } + + int getUniformLocationOverride(const char* nameStr) const + { + std::string name = nameStr; + auto pos = uniformLocationOverrides.find(name); + if (pos == uniformLocationOverrides.end()) + return -1; + else + return pos->second; + } + + void setUniformLocationBase(int base) { uniformLocationBase = base; } + int getUniformLocationBase() const { return uniformLocationBase; } + + void setNeedsLegalization() { needToLegalize = true; } + bool needsLegalization() const { return needToLegalize; } + + void setBinaryDoubleOutput() { binaryDoubleOutput = true; } + bool getBinaryDoubleOutput() { return binaryDoubleOutput; } +#endif // GLSLANG_WEB + +#ifdef ENABLE_HLSL + void setHlslFunctionality1() { hlslFunctionality1 = true; } + bool getHlslFunctionality1() const { return hlslFunctionality1; } + void setHlslOffsets() + { + hlslOffsets = true; + if (hlslOffsets) + processes.addProcess("hlsl-offsets"); + } + bool usingHlslOffsets() const { return hlslOffsets; } + void setHlslIoMapping(bool b) + { + hlslIoMapping = b; + if (hlslIoMapping) + processes.addProcess("hlsl-iomap"); + } + bool usingHlslIoMapping() { return hlslIoMapping; } +#else + bool getHlslFunctionality1() const { return false; } + bool usingHlslOffsets() const { return false; } + bool usingHlslIoMapping() { return false; } +#endif + + void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee); + void merge(TInfoSink&, TIntermediate&); + void finalCheck(TInfoSink&, bool keepUncalled); + + bool buildConvertOp(TBasicType dst, TBasicType src, TOperator& convertOp) const; + TIntermTyped* createConversion(TBasicType convertTo, TIntermTyped* node) const; + + void addIoAccessed(const TString& name) { ioAccessed.insert(name); } + bool inIoAccessed(const TString& name) const { return ioAccessed.find(name) != ioAccessed.end(); } + + int addUsedLocation(const TQualifier&, const TType&, bool& typeCollision); + int checkLocationRange(int set, const TIoRange& range, const TType&, bool& typeCollision); + int addUsedOffsets(int binding, int offset, int numOffsets); + bool addUsedConstantId(int id); + static int computeTypeLocationSize(const TType&, EShLanguage); + static int computeTypeUniformLocationSize(const TType&); + + static int getBaseAlignmentScalar(const TType&, int& size); + static int getBaseAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor); + static int getScalarAlignment(const TType&, int& size, int& stride, bool rowMajor); + static int getMemberAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor); + static bool improperStraddle(const TType& type, int size, int offset); + static void updateOffset(const TType& parentType, const TType& memberType, int& offset, int& memberSize); + static int getOffset(const TType& type, int index); + static int getBlockSize(const TType& blockType); + static int computeBufferReferenceTypeSize(const TType&); + bool promote(TIntermOperator*); + void setNanMinMaxClamp(bool setting) { nanMinMaxClamp = setting; } + bool getNanMinMaxClamp() const { return nanMinMaxClamp; } + + void setSourceFile(const char* file) { if (file != nullptr) sourceFile = file; } + const std::string& getSourceFile() const { return sourceFile; } + void addSourceText(const char* text, size_t len) { sourceText.append(text, len); } + const std::string& getSourceText() const { return sourceText; } + const std::map& getIncludeText() const { return includeText; } + void addIncludeText(const char* name, const char* text, size_t len) { includeText[name].assign(text,len); } + void addProcesses(const std::vector& p) + { + for (int i = 0; i < (int)p.size(); ++i) + processes.addProcess(p[i]); + } + void addProcess(const std::string& process) { processes.addProcess(process); } + void addProcessArgument(const std::string& arg) { processes.addArgument(arg); } + const std::vector& getProcesses() const { return processes.getProcesses(); } + + // Certain explicit conversions are allowed conditionally +#ifdef GLSLANG_WEB + bool getArithemeticInt8Enabled() const { return false; } + bool getArithemeticInt16Enabled() const { return false; } + bool getArithemeticFloat16Enabled() const { return false; } +#else + bool getArithemeticInt8Enabled() const { + return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || + extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8); + } + bool getArithemeticInt16Enabled() const { + return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || + extensionRequested(E_GL_AMD_gpu_shader_int16) || + extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16); + } + + bool getArithemeticFloat16Enabled() const { + return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || + extensionRequested(E_GL_AMD_gpu_shader_half_float) || + extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16); + } +#endif + +protected: + TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&); + void error(TInfoSink& infoSink, const char*); + void warn(TInfoSink& infoSink, const char*); + void mergeCallGraphs(TInfoSink&, TIntermediate&); + void mergeModes(TInfoSink&, TIntermediate&); + void mergeTrees(TInfoSink&, TIntermediate&); + void seedIdMap(TIdMaps& idMaps, int& maxId); + void remapIds(const TIdMaps& idMaps, int idShift, TIntermediate&); + void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals); + void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects); + void mergeImplicitArraySizes(TType&, const TType&); + void mergeErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, bool crossStage); + void checkCallGraphCycles(TInfoSink&); + void checkCallGraphBodies(TInfoSink&, bool keepUncalled); + void inOutLocationCheck(TInfoSink&); + TIntermAggregate* findLinkerObjects() const; + bool userOutputUsed() const; + bool isSpecializationOperation(const TIntermOperator&) const; + bool isNonuniformPropagating(TOperator) const; + bool promoteUnary(TIntermUnary&); + bool promoteBinary(TIntermBinary&); + void addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable&, const TString&); + bool promoteAggregate(TIntermAggregate&); + void pushSelector(TIntermSequence&, const TVectorSelector&, const TSourceLoc&); + void pushSelector(TIntermSequence&, const TMatrixSelector&, const TSourceLoc&); + bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&); + void performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root); + bool isConversionAllowed(TOperator op, TIntermTyped* node) const; + std::tuple getConversionDestinatonType(TBasicType type0, TBasicType type1, TOperator op) const; + + // JohnK: I think this function should go away. + // This data structure is just a log to pass on to back ends. + // Versioning and extensions are handled in Version.cpp, with a rich + // set of functions for querying stages, versions, extension enable/disabled, etc. +#ifdef GLSLANG_WEB + bool extensionRequested(const char *extension) const { return false; } +#else + bool extensionRequested(const char *extension) const {return requestedExtensions.find(extension) != requestedExtensions.end();} +#endif + + static const char* getResourceName(TResourceType); + + const EShLanguage language; // stage, known at construction time + std::string entryPointName; + std::string entryPointMangledName; + typedef std::list TGraph; + TGraph callGraph; + + EProfile profile; // source profile + int version; // source version + SpvVersion spvVersion; + TIntermNode* treeRoot; + std::set requestedExtensions; // cumulation of all enabled or required extensions; not connected to what subset of the shader used them + TBuiltInResource resources; + int numEntryPoints; + int numErrors; + int numPushConstants; + bool recursive; + bool invertY; + bool useStorageBuffer; + bool nanMinMaxClamp; // true if desiring min/max/clamp to favor non-NaN over NaN + bool depthReplacing; + int localSize[3]; + bool localSizeNotDefault[3]; + int localSizeSpecId[3]; +#ifndef GLSLANG_WEB +public: + const char* const implicitThisName; + const char* const implicitCounterName; +protected: + EShSource source; // source language, known a bit later + bool useVulkanMemoryModel; + int invocations; + int vertices; + TLayoutGeometry inputPrimitive; + TLayoutGeometry outputPrimitive; + bool pixelCenterInteger; + bool originUpperLeft; + TVertexSpacing vertexSpacing; + TVertexOrder vertexOrder; + TInterlockOrdering interlockOrdering; + bool pointMode; + bool earlyFragmentTests; + bool postDepthCoverage; + TLayoutDepth depthLayout; + bool hlslFunctionality1; + int blendEquations; // an 'or'ing of masks of shifts of TBlendEquationShift + bool xfbMode; + std::vector xfbBuffers; // all the data we need to track per xfb buffer + bool multiStream; + bool layoutOverrideCoverage; + bool geoPassthroughEXT; + int numShaderRecordBlocks; + ComputeDerivativeMode computeDerivativeMode; + int primitives; + int numTaskNVBlocks; + + // Base shift values + std::array shiftBinding; + + // Per-descriptor-set shift values + std::array, EResCount> shiftBindingForSet; + + std::vector resourceSetBinding; + bool autoMapBindings; + bool autoMapLocations; + bool flattenUniformArrays; + bool useUnknownFormat; + bool hlslOffsets; + bool hlslIoMapping; + bool useVariablePointers; + + std::set semanticNameSet; + + EShTextureSamplerTransformMode textureSamplerTransformMode; + + bool needToLegalize; + bool binaryDoubleOutput; + bool usePhysicalStorageBuffer; + + std::unordered_map uniformLocationOverrides; + int uniformLocationBase; +#endif + + std::unordered_set usedConstantId; // specialization constant ids used + std::vector usedAtomics; // sets of bindings used by atomic counters + std::vector usedIo[4]; // sets of used locations, one for each of in, out, uniform, and buffers + // set of names of statically read/written I/O that might need extra checking + std::set ioAccessed; + // source code of shader, useful as part of debug information + std::string sourceFile; + std::string sourceText; + + // Included text. First string is a name, second is the included text + std::map includeText; + + // for OpModuleProcessed, or equivalent + TProcesses processes; + +private: + void operator=(TIntermediate&); // prevent assignments +}; + +} // end namespace glslang + +#endif // _LOCAL_INTERMEDIATE_INCLUDED_ diff --git a/android/arm64-v8a/include/glslang/glslang/MachineIndependent/parseVersions.h b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/parseVersions.h new file mode 100644 index 00000000..aa1964fc --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/parseVersions.h @@ -0,0 +1,236 @@ +// +// Copyright (C) 2015-2018 Google, Inc. +// Copyright (C) 2017 ARM Limited. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +// This is implemented in Versions.cpp + +#ifndef _PARSE_VERSIONS_INCLUDED_ +#define _PARSE_VERSIONS_INCLUDED_ + +#include "../Public/ShaderLang.h" +#include "../Include/InfoSink.h" +#include "Scan.h" + +#include + +namespace glslang { + +// +// Base class for parse helpers. +// This just has version-related information and checking. +// This class should be sufficient for preprocessing. +// +class TParseVersions { +public: + TParseVersions(TIntermediate& interm, int version, EProfile profile, + const SpvVersion& spvVersion, EShLanguage language, TInfoSink& infoSink, + bool forwardCompatible, EShMessages messages) + : +#ifndef GLSLANG_WEB + forwardCompatible(forwardCompatible), + profile(profile), +#endif + infoSink(infoSink), version(version), + language(language), + spvVersion(spvVersion), + intermediate(interm), messages(messages), numErrors(0), currentScanner(0) { } + virtual ~TParseVersions() { } + void requireStage(const TSourceLoc&, EShLanguageMask, const char* featureDesc); + void requireStage(const TSourceLoc&, EShLanguage, const char* featureDesc); +#ifdef GLSLANG_WEB + const EProfile profile = EEsProfile; + bool isEsProfile() const { return true; } + void requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc) + { + if (! (EEsProfile & profileMask)) + error(loc, "not supported with this profile:", featureDesc, ProfileName(profile)); + } + void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions, + const char* const extensions[], const char* featureDesc) + { + if ((EEsProfile & profileMask) && (minVersion == 0 || version < minVersion)) + error(loc, "not supported for this version or the enabled extensions", featureDesc, ""); + } + void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, const char* extension, + const char* featureDesc) + { + profileRequires(loc, profileMask, minVersion, extension ? 1 : 0, &extension, featureDesc); + } + void initializeExtensionBehavior() { } + void checkDeprecated(const TSourceLoc&, int queryProfiles, int depVersion, const char* featureDesc) { } + void requireNotRemoved(const TSourceLoc&, int queryProfiles, int removedVersion, const char* featureDesc) { } + void requireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], + const char* featureDesc) { } + void ppRequireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], + const char* featureDesc) { } + TExtensionBehavior getExtensionBehavior(const char*) { return EBhMissing; } + bool extensionTurnedOn(const char* const extension) { return false; } + bool extensionsTurnedOn(int numExtensions, const char* const extensions[]) { return false; } + void updateExtensionBehavior(int line, const char* const extension, const char* behavior) { } + void updateExtensionBehavior(const char* const extension, TExtensionBehavior) { } + void checkExtensionStage(const TSourceLoc&, const char* const extension) { } + void fullIntegerCheck(const TSourceLoc&, const char* op) { } + void doubleCheck(const TSourceLoc&, const char* op) { } + bool float16Arithmetic() { return false; } + void requireFloat16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc) { } + bool int16Arithmetic() { return false; } + void requireInt16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc) { } + bool int8Arithmetic() { return false; } + void requireInt8Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc) { } + void int64Check(const TSourceLoc&, const char* op, bool builtIn = false) { } + void explicitFloat32Check(const TSourceLoc&, const char* op, bool builtIn = false) { } + void explicitFloat64Check(const TSourceLoc&, const char* op, bool builtIn = false) { } + bool relaxedErrors() const { return false; } + bool suppressWarnings() const { return true; } + bool isForwardCompatible() const { return false; } +#else + bool forwardCompatible; // true if errors are to be given for use of deprecated features + EProfile profile; // the declared profile in the shader (core by default) + bool isEsProfile() const { return profile == EEsProfile; } + void requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc); + void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions, + const char* const extensions[], const char* featureDesc); + void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, const char* extension, + const char* featureDesc); + virtual void initializeExtensionBehavior(); + virtual void checkDeprecated(const TSourceLoc&, int queryProfiles, int depVersion, const char* featureDesc); + virtual void requireNotRemoved(const TSourceLoc&, int queryProfiles, int removedVersion, const char* featureDesc); + virtual void requireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], + const char* featureDesc); + virtual void ppRequireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], + const char* featureDesc); + virtual TExtensionBehavior getExtensionBehavior(const char*); + virtual bool extensionTurnedOn(const char* const extension); + virtual bool extensionsTurnedOn(int numExtensions, const char* const extensions[]); + virtual void updateExtensionBehavior(int line, const char* const extension, const char* behavior); + virtual void updateExtensionBehavior(const char* const extension, TExtensionBehavior); + virtual bool checkExtensionsRequested(const TSourceLoc&, int numExtensions, const char* const extensions[], + const char* featureDesc); + virtual void checkExtensionStage(const TSourceLoc&, const char* const extension); + virtual void fullIntegerCheck(const TSourceLoc&, const char* op); + + virtual void unimplemented(const TSourceLoc&, const char* featureDesc); + virtual void doubleCheck(const TSourceLoc&, const char* op); + virtual void float16Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void float16ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false); + virtual bool float16Arithmetic(); + virtual void requireFloat16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc); + virtual void int16ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false); + virtual bool int16Arithmetic(); + virtual void requireInt16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc); + virtual void int8ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false); + virtual bool int8Arithmetic(); + virtual void requireInt8Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc); + virtual void float16OpaqueCheck(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void int64Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void explicitInt8Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void explicitInt16Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void explicitInt32Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void explicitFloat32Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void explicitFloat64Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void fcoopmatCheck(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void intcoopmatCheck(const TSourceLoc&, const char *op, bool builtIn = false); + bool relaxedErrors() const { return (messages & EShMsgRelaxedErrors) != 0; } + bool suppressWarnings() const { return (messages & EShMsgSuppressWarnings) != 0; } + bool isForwardCompatible() const { return forwardCompatible; } +#endif // GLSLANG_WEB + virtual void spvRemoved(const TSourceLoc&, const char* op); + virtual void vulkanRemoved(const TSourceLoc&, const char* op); + virtual void requireVulkan(const TSourceLoc&, const char* op); + virtual void requireSpv(const TSourceLoc&, const char* op); + + +#if defined(GLSLANG_WEB) && !defined(GLSLANG_WEB_DEVEL) + void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) { addError(); } + void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) { } + void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) { addError(); } + void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) { } +#else + virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) = 0; + virtual void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) = 0; + virtual void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) = 0; + virtual void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) = 0; +#endif + + void addError() { ++numErrors; } + int getNumErrors() const { return numErrors; } + + void setScanner(TInputScanner* scanner) { currentScanner = scanner; } + TInputScanner* getScanner() const { return currentScanner; } + const TSourceLoc& getCurrentLoc() const { return currentScanner->getSourceLoc(); } + void setCurrentLine(int line) { currentScanner->setLine(line); } + void setCurrentColumn(int col) { currentScanner->setColumn(col); } + void setCurrentSourceName(const char* name) { currentScanner->setFile(name); } + void setCurrentString(int string) { currentScanner->setString(string); } + + void getPreamble(std::string&); +#ifdef ENABLE_HLSL + bool isReadingHLSL() const { return (messages & EShMsgReadHlsl) == EShMsgReadHlsl; } + bool hlslEnable16BitTypes() const { return (messages & EShMsgHlslEnable16BitTypes) != 0; } + bool hlslDX9Compatible() const { return (messages & EShMsgHlslDX9Compatible) != 0; } +#else + bool isReadingHLSL() const { return false; } +#endif + + TInfoSink& infoSink; + + // compilation mode + int version; // version, updated by #version in the shader + EShLanguage language; // really the stage + SpvVersion spvVersion; + TIntermediate& intermediate; // helper for making and hooking up pieces of the parse tree + +protected: + TMap extensionBehavior; // for each extension string, what its current behavior is set to + EShMessages messages; // errors/warnings/rule-sets + int numErrors; // number of compile-time errors encountered + TInputScanner* currentScanner; + +private: + explicit TParseVersions(const TParseVersions&); + TParseVersions& operator=(const TParseVersions&); +}; + +} // end namespace glslang + +#endif // _PARSE_VERSIONS_INCLUDED_ diff --git a/android/arm64-v8a/include/glslang/glslang/MachineIndependent/preprocessor/PpContext.h b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/preprocessor/PpContext.h new file mode 100644 index 00000000..714b5ead --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/preprocessor/PpContext.h @@ -0,0 +1,703 @@ +// +// Copyright (C) 2013 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ + +#ifndef PPCONTEXT_H +#define PPCONTEXT_H + +#include +#include +#include + +#include "../ParseHelper.h" +#include "PpTokens.h" + +/* windows only pragma */ +#ifdef _MSC_VER + #pragma warning(disable : 4127) +#endif + +namespace glslang { + +class TPpToken { +public: + TPpToken() { clear(); } + void clear() + { + space = false; + i64val = 0; + loc.init(); + name[0] = 0; + } + + // Used for comparing macro definitions, so checks what is relevant for that. + bool operator==(const TPpToken& right) const + { + return space == right.space && + ival == right.ival && dval == right.dval && i64val == right.i64val && + strncmp(name, right.name, MaxTokenLength) == 0; + } + bool operator!=(const TPpToken& right) const { return ! operator==(right); } + + TSourceLoc loc; + // True if a space (for white space or a removed comment) should also be + // recognized, in front of the token returned: + bool space; + // Numeric value of the token: + union { + int ival; + double dval; + long long i64val; + }; + // Text string of the token: + char name[MaxTokenLength + 1]; +}; + +class TStringAtomMap { +// +// Implementation is in PpAtom.cpp +// +// Maintain a bi-directional mapping between relevant preprocessor strings and +// "atoms" which a unique integers (small, contiguous, not hash-like) per string. +// +public: + TStringAtomMap(); + + // Map string -> atom. + // Return 0 if no existing string. + int getAtom(const char* s) const + { + auto it = atomMap.find(s); + return it == atomMap.end() ? 0 : it->second; + } + + // Map a new or existing string -> atom, inventing a new atom if necessary. + int getAddAtom(const char* s) + { + int atom = getAtom(s); + if (atom == 0) { + atom = nextAtom++; + addAtomFixed(s, atom); + } + return atom; + } + + // Map atom -> string. + const char* getString(int atom) const { return stringMap[atom]->c_str(); } + +protected: + TStringAtomMap(TStringAtomMap&); + TStringAtomMap& operator=(TStringAtomMap&); + + TUnorderedMap atomMap; + TVector stringMap; // these point into the TString in atomMap + int nextAtom; + + // Bad source characters can lead to bad atoms, so gracefully handle those by + // pre-filling the table with them (to avoid if tests later). + TString badToken; + + // Add bi-directional mappings: + // - string -> atom + // - atom -> string + void addAtomFixed(const char* s, int atom) + { + auto it = atomMap.insert(std::pair(s, atom)).first; + if (stringMap.size() < (size_t)atom + 1) + stringMap.resize(atom + 100, &badToken); + stringMap[atom] = &it->first; + } +}; + +class TInputScanner; + +enum MacroExpandResult { + MacroExpandNotStarted, // macro not expanded, which might not be an error + MacroExpandError, // a clear error occurred while expanding, no expansion + MacroExpandStarted, // macro expansion process has started + MacroExpandUndef // macro is undefined and will be expanded +}; + +// This class is the result of turning a huge pile of C code communicating through globals +// into a class. This was done to allowing instancing to attain thread safety. +// Don't expect too much in terms of OO design. +class TPpContext { +public: + TPpContext(TParseContextBase&, const std::string& rootFileName, TShader::Includer&); + virtual ~TPpContext(); + + void setPreamble(const char* preamble, size_t length); + + int tokenize(TPpToken& ppToken); + int tokenPaste(int token, TPpToken&); + + class tInput { + public: + tInput(TPpContext* p) : done(false), pp(p) { } + virtual ~tInput() { } + + virtual int scan(TPpToken*) = 0; + virtual int getch() = 0; + virtual void ungetch() = 0; + virtual bool peekPasting() { return false; } // true when about to see ## + virtual bool peekContinuedPasting(int) { return false; } // true when non-spaced tokens can paste + virtual bool endOfReplacementList() { return false; } // true when at the end of a macro replacement list (RHS of #define) + virtual bool isMacroInput() { return false; } + + // Will be called when we start reading tokens from this instance + virtual void notifyActivated() {} + // Will be called when we do not read tokens from this instance anymore + virtual void notifyDeleted() {} + protected: + bool done; + TPpContext* pp; + }; + + void setInput(TInputScanner& input, bool versionWillBeError); + + void pushInput(tInput* in) + { + inputStack.push_back(in); + in->notifyActivated(); + } + void popInput() + { + inputStack.back()->notifyDeleted(); + delete inputStack.back(); + inputStack.pop_back(); + } + + // + // From PpTokens.cpp + // + + // Capture the needed parts of a token stream for macro recording/playback. + class TokenStream { + public: + // Manage a stream of these 'Token', which capture the relevant parts + // of a TPpToken, plus its atom. + class Token { + public: + Token(int atom, const TPpToken& ppToken) : + atom(atom), + space(ppToken.space), + i64val(ppToken.i64val), + name(ppToken.name) { } + int get(TPpToken& ppToken) + { + ppToken.clear(); + ppToken.space = space; + ppToken.i64val = i64val; + snprintf(ppToken.name, sizeof(ppToken.name), "%s", name.c_str()); + return atom; + } + bool isAtom(int a) const { return atom == a; } + int getAtom() const { return atom; } + bool nonSpaced() const { return !space; } + protected: + Token() {} + int atom; + bool space; // did a space precede the token? + long long i64val; + TString name; + }; + + TokenStream() : currentPos(0) { } + + void putToken(int token, TPpToken* ppToken); + bool peekToken(int atom) { return !atEnd() && stream[currentPos].isAtom(atom); } + bool peekContinuedPasting(int atom) + { + // This is basically necessary because, for example, the PP + // tokenizer only accepts valid numeric-literals plus suffixes, so + // separates numeric-literals plus bad suffix into two tokens, which + // should get both pasted together as one token when token pasting. + // + // The following code is a bit more generalized than the above example. + if (!atEnd() && atom == PpAtomIdentifier && stream[currentPos].nonSpaced()) { + switch(stream[currentPos].getAtom()) { + case PpAtomConstInt: + case PpAtomConstUint: + case PpAtomConstInt64: + case PpAtomConstUint64: + case PpAtomConstInt16: + case PpAtomConstUint16: + case PpAtomConstFloat: + case PpAtomConstDouble: + case PpAtomConstFloat16: + case PpAtomConstString: + case PpAtomIdentifier: + return true; + default: + break; + } + } + + return false; + } + int getToken(TParseContextBase&, TPpToken*); + bool atEnd() { return currentPos >= stream.size(); } + bool peekTokenizedPasting(bool lastTokenPastes); + bool peekUntokenizedPasting(); + void reset() { currentPos = 0; } + + protected: + TVector stream; + size_t currentPos; + }; + + // + // From Pp.cpp + // + + struct MacroSymbol { + MacroSymbol() : functionLike(0), busy(0), undef(0) { } + TVector args; + TokenStream body; + unsigned functionLike : 1; // 0 means object-like, 1 means function-like + unsigned busy : 1; + unsigned undef : 1; + }; + + typedef TMap TSymbolMap; + TSymbolMap macroDefs; // map atoms to macro definitions + MacroSymbol* lookupMacroDef(int atom) + { + auto existingMacroIt = macroDefs.find(atom); + return (existingMacroIt == macroDefs.end()) ? nullptr : &(existingMacroIt->second); + } + void addMacroDef(int atom, MacroSymbol& macroDef) { macroDefs[atom] = macroDef; } + +protected: + TPpContext(TPpContext&); + TPpContext& operator=(TPpContext&); + + TStringAtomMap atomStrings; + char* preamble; // string to parse, all before line 1 of string 0, it is 0 if no preamble + int preambleLength; + char** strings; // official strings of shader, starting a string 0 line 1 + size_t* lengths; + int numStrings; // how many official strings there are + int currentString; // which string we're currently parsing (-1 for preamble) + + // Scanner data: + int previous_token; + TParseContextBase& parseContext; + + // Get the next token from *stack* of input sources, popping input sources + // that are out of tokens, down until an input source is found that has a token. + // Return EndOfInput when there are no more tokens to be found by doing this. + int scanToken(TPpToken* ppToken) + { + int token = EndOfInput; + + while (! inputStack.empty()) { + token = inputStack.back()->scan(ppToken); + if (token != EndOfInput || inputStack.empty()) + break; + popInput(); + } + + return token; + } + int getChar() { return inputStack.back()->getch(); } + void ungetChar() { inputStack.back()->ungetch(); } + bool peekPasting() { return !inputStack.empty() && inputStack.back()->peekPasting(); } + bool peekContinuedPasting(int a) + { + return !inputStack.empty() && inputStack.back()->peekContinuedPasting(a); + } + bool endOfReplacementList() { return inputStack.empty() || inputStack.back()->endOfReplacementList(); } + bool isMacroInput() { return inputStack.size() > 0 && inputStack.back()->isMacroInput(); } + + static const int maxIfNesting = 65; + + int ifdepth; // current #if-#else-#endif nesting in the cpp.c file (pre-processor) + bool elseSeen[maxIfNesting]; // Keep a track of whether an else has been seen at a particular depth + int elsetracker; // #if-#else and #endif constructs...Counter. + + class tMacroInput : public tInput { + public: + tMacroInput(TPpContext* pp) : tInput(pp), prepaste(false), postpaste(false) { } + virtual ~tMacroInput() + { + for (size_t i = 0; i < args.size(); ++i) + delete args[i]; + for (size_t i = 0; i < expandedArgs.size(); ++i) + delete expandedArgs[i]; + } + + virtual int scan(TPpToken*) override; + virtual int getch() override { assert(0); return EndOfInput; } + virtual void ungetch() override { assert(0); } + bool peekPasting() override { return prepaste; } + bool peekContinuedPasting(int a) override { return mac->body.peekContinuedPasting(a); } + bool endOfReplacementList() override { return mac->body.atEnd(); } + bool isMacroInput() override { return true; } + + MacroSymbol *mac; + TVector args; + TVector expandedArgs; + + protected: + bool prepaste; // true if we are just before ## + bool postpaste; // true if we are right after ## + }; + + class tMarkerInput : public tInput { + public: + tMarkerInput(TPpContext* pp) : tInput(pp) { } + virtual int scan(TPpToken*) override + { + if (done) + return EndOfInput; + done = true; + + return marker; + } + virtual int getch() override { assert(0); return EndOfInput; } + virtual void ungetch() override { assert(0); } + static const int marker = -3; + }; + + class tZeroInput : public tInput { + public: + tZeroInput(TPpContext* pp) : tInput(pp) { } + virtual int scan(TPpToken*) override; + virtual int getch() override { assert(0); return EndOfInput; } + virtual void ungetch() override { assert(0); } + }; + + std::vector inputStack; + bool errorOnVersion; + bool versionSeen; + + // + // from Pp.cpp + // + + // Used to obtain #include content. + TShader::Includer& includer; + + int CPPdefine(TPpToken * ppToken); + int CPPundef(TPpToken * ppToken); + int CPPelse(int matchelse, TPpToken * ppToken); + int extraTokenCheck(int atom, TPpToken* ppToken, int token); + int eval(int token, int precedence, bool shortCircuit, int& res, bool& err, TPpToken * ppToken); + int evalToToken(int token, bool shortCircuit, int& res, bool& err, TPpToken * ppToken); + int CPPif (TPpToken * ppToken); + int CPPifdef(int defined, TPpToken * ppToken); + int CPPinclude(TPpToken * ppToken); + int CPPline(TPpToken * ppToken); + int CPPerror(TPpToken * ppToken); + int CPPpragma(TPpToken * ppToken); + int CPPversion(TPpToken * ppToken); + int CPPextension(TPpToken * ppToken); + int readCPPline(TPpToken * ppToken); + int scanHeaderName(TPpToken* ppToken, char delimit); + TokenStream* PrescanMacroArg(TokenStream&, TPpToken*, bool newLineOkay); + MacroExpandResult MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay); + + // + // From PpTokens.cpp + // + void pushTokenStreamInput(TokenStream&, bool pasting = false); + void UngetToken(int token, TPpToken*); + + class tTokenInput : public tInput { + public: + tTokenInput(TPpContext* pp, TokenStream* t, bool prepasting) : + tInput(pp), + tokens(t), + lastTokenPastes(prepasting) { } + virtual int scan(TPpToken *ppToken) override { return tokens->getToken(pp->parseContext, ppToken); } + virtual int getch() override { assert(0); return EndOfInput; } + virtual void ungetch() override { assert(0); } + virtual bool peekPasting() override { return tokens->peekTokenizedPasting(lastTokenPastes); } + bool peekContinuedPasting(int a) override { return tokens->peekContinuedPasting(a); } + protected: + TokenStream* tokens; + bool lastTokenPastes; // true if the last token in the input is to be pasted, rather than consumed as a token + }; + + class tUngotTokenInput : public tInput { + public: + tUngotTokenInput(TPpContext* pp, int t, TPpToken* p) : tInput(pp), token(t), lval(*p) { } + virtual int scan(TPpToken *) override; + virtual int getch() override { assert(0); return EndOfInput; } + virtual void ungetch() override { assert(0); } + protected: + int token; + TPpToken lval; + }; + + // + // From PpScanner.cpp + // + class tStringInput : public tInput { + public: + tStringInput(TPpContext* pp, TInputScanner& i) : tInput(pp), input(&i) { } + virtual int scan(TPpToken*) override; + + // Scanner used to get source stream characters. + // - Escaped newlines are handled here, invisibly to the caller. + // - All forms of newline are handled, and turned into just a '\n'. + int getch() override + { + int ch = input->get(); + + if (ch == '\\') { + // Move past escaped newlines, as many as sequentially exist + do { + if (input->peek() == '\r' || input->peek() == '\n') { + bool allowed = pp->parseContext.lineContinuationCheck(input->getSourceLoc(), pp->inComment); + if (! allowed && pp->inComment) + return '\\'; + + // escape one newline now + ch = input->get(); + int nextch = input->get(); + if (ch == '\r' && nextch == '\n') + ch = input->get(); + else + ch = nextch; + } else + return '\\'; + } while (ch == '\\'); + } + + // handle any non-escaped newline + if (ch == '\r' || ch == '\n') { + if (ch == '\r' && input->peek() == '\n') + input->get(); + return '\n'; + } + + return ch; + } + + // Scanner used to backup the source stream characters. Newlines are + // handled here, invisibly to the caller, meaning have to undo exactly + // what getch() above does (e.g., don't leave things in the middle of a + // sequence of escaped newlines). + void ungetch() override + { + input->unget(); + + do { + int ch = input->peek(); + if (ch == '\r' || ch == '\n') { + if (ch == '\n') { + // correct for two-character newline + input->unget(); + if (input->peek() != '\r') + input->get(); + } + // now in front of a complete newline, move past an escape character + input->unget(); + if (input->peek() == '\\') + input->unget(); + else { + input->get(); + break; + } + } else + break; + } while (true); + } + + protected: + TInputScanner* input; + }; + + // Holds a reference to included file data, as well as a + // prologue and an epilogue string. This can be scanned using the tInput + // interface and acts as a single source string. + class TokenizableIncludeFile : public tInput { + public: + // Copies prologue and epilogue. The includedFile must remain valid + // until this TokenizableIncludeFile is no longer used. + TokenizableIncludeFile(const TSourceLoc& startLoc, + const std::string& prologue, + TShader::Includer::IncludeResult* includedFile, + const std::string& epilogue, + TPpContext* pp) + : tInput(pp), + prologue_(prologue), + epilogue_(epilogue), + includedFile_(includedFile), + scanner(3, strings, lengths, nullptr, 0, 0, true), + prevScanner(nullptr), + stringInput(pp, scanner) + { + strings[0] = prologue_.data(); + strings[1] = includedFile_->headerData; + strings[2] = epilogue_.data(); + + lengths[0] = prologue_.size(); + lengths[1] = includedFile_->headerLength; + lengths[2] = epilogue_.size(); + + scanner.setLine(startLoc.line); + scanner.setString(startLoc.string); + + scanner.setFile(startLoc.getFilenameStr(), 0); + scanner.setFile(startLoc.getFilenameStr(), 1); + scanner.setFile(startLoc.getFilenameStr(), 2); + } + + // tInput methods: + int scan(TPpToken* t) override { return stringInput.scan(t); } + int getch() override { return stringInput.getch(); } + void ungetch() override { stringInput.ungetch(); } + + void notifyActivated() override + { + prevScanner = pp->parseContext.getScanner(); + pp->parseContext.setScanner(&scanner); + pp->push_include(includedFile_); + } + + void notifyDeleted() override + { + pp->parseContext.setScanner(prevScanner); + pp->pop_include(); + } + + private: + TokenizableIncludeFile& operator=(const TokenizableIncludeFile&); + + // Stores the prologue for this string. + const std::string prologue_; + + // Stores the epilogue for this string. + const std::string epilogue_; + + // Points to the IncludeResult that this TokenizableIncludeFile represents. + TShader::Includer::IncludeResult* includedFile_; + + // Will point to prologue_, includedFile_->headerData and epilogue_ + // This is passed to scanner constructor. + // These do not own the storage and it must remain valid until this + // object has been destroyed. + const char* strings[3]; + // Length of str_, passed to scanner constructor. + size_t lengths[3]; + // Scans over str_. + TInputScanner scanner; + // The previous effective scanner before the scanner in this instance + // has been activated. + TInputScanner* prevScanner; + // Delegate object implementing the tInput interface. + tStringInput stringInput; + }; + + int ScanFromString(char* s); + void missingEndifCheck(); + int lFloatConst(int len, int ch, TPpToken* ppToken); + int characterLiteral(TPpToken* ppToken); + + void push_include(TShader::Includer::IncludeResult* result) + { + currentSourceFile = result->headerName; + includeStack.push(result); + } + + void pop_include() + { + TShader::Includer::IncludeResult* include = includeStack.top(); + includeStack.pop(); + includer.releaseInclude(include); + if (includeStack.empty()) { + currentSourceFile = rootFileName; + } else { + currentSourceFile = includeStack.top()->headerName; + } + } + + bool inComment; + std::string rootFileName; + std::stack includeStack; + std::string currentSourceFile; + + std::istringstream strtodStream; + bool disableEscapeSequences; +}; + +} // end namespace glslang + +#endif // PPCONTEXT_H diff --git a/android/arm64-v8a/include/glslang/glslang/MachineIndependent/preprocessor/PpTokens.h b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/preprocessor/PpTokens.h new file mode 100644 index 00000000..7b0f8155 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/preprocessor/PpTokens.h @@ -0,0 +1,179 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ + +#ifndef PARSER_H +#define PARSER_H + +namespace glslang { + +// Multi-character tokens +enum EFixedAtoms { + // single character tokens get their own char value as their token; start here for multi-character tokens + PpAtomMaxSingle = 127, + + // replace bad character tokens with this, to avoid accidental aliasing with the below + PpAtomBadToken, + + // Operators + + PPAtomAddAssign, + PPAtomSubAssign, + PPAtomMulAssign, + PPAtomDivAssign, + PPAtomModAssign, + + PpAtomRight, + PpAtomLeft, + + PpAtomRightAssign, + PpAtomLeftAssign, + PpAtomAndAssign, + PpAtomOrAssign, + PpAtomXorAssign, + + PpAtomAnd, + PpAtomOr, + PpAtomXor, + + PpAtomEQ, + PpAtomNE, + PpAtomGE, + PpAtomLE, + + PpAtomDecrement, + PpAtomIncrement, + + PpAtomColonColon, + + PpAtomPaste, + + // Constants + + PpAtomConstInt, + PpAtomConstUint, + PpAtomConstInt64, + PpAtomConstUint64, + PpAtomConstInt16, + PpAtomConstUint16, + PpAtomConstFloat, + PpAtomConstDouble, + PpAtomConstFloat16, + PpAtomConstString, + + // Identifiers + PpAtomIdentifier, + + // preprocessor "keywords" + + PpAtomDefine, + PpAtomUndef, + + PpAtomIf, + PpAtomIfdef, + PpAtomIfndef, + PpAtomElse, + PpAtomElif, + PpAtomEndif, + + PpAtomLine, + PpAtomPragma, + PpAtomError, + + // #version ... + PpAtomVersion, + PpAtomCore, + PpAtomCompatibility, + PpAtomEs, + + // #extension + PpAtomExtension, + + // __LINE__, __FILE__, __VERSION__ + + PpAtomLineMacro, + PpAtomFileMacro, + PpAtomVersionMacro, + + // #include + PpAtomInclude, + + PpAtomLast, +}; + +} // end namespace glslang + +#endif /* not PARSER_H */ diff --git a/android/arm64-v8a/include/glslang/glslang/MachineIndependent/propagateNoContraction.h b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/propagateNoContraction.h new file mode 100644 index 00000000..8521ad7d --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/propagateNoContraction.h @@ -0,0 +1,55 @@ +// +// Copyright (C) 2015-2016 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Visit the nodes in the glslang intermediate tree representation to +// propagate 'noContraction' qualifier. +// + +#pragma once + +#include "../Include/intermediate.h" + +namespace glslang { + +// Propagates the 'precise' qualifier for objects (objects marked with +// 'noContraction' qualifier) from the shader source specified 'precise' +// variables to all the involved objects, and add 'noContraction' qualifier for +// the involved arithmetic operations. +// Note that the same qualifier: 'noContraction' is used in both object nodes +// and arithmetic operation nodes, but has different meaning. For object nodes, +// 'noContraction' means the object is 'precise'; and for arithmetic operation +// nodes, it means the operation should not be contracted. +void PropagateNoContraction(const glslang::TIntermediate& intermediate); +}; diff --git a/android/arm64-v8a/include/glslang/glslang/MachineIndependent/reflection.h b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/reflection.h new file mode 100644 index 00000000..0c33de45 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/MachineIndependent/reflection.h @@ -0,0 +1,223 @@ +// +// Copyright (C) 2013-2016 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef GLSLANG_WEB + +#ifndef _REFLECTION_INCLUDED +#define _REFLECTION_INCLUDED + +#include "../Public/ShaderLang.h" +#include "../Include/Types.h" + +#include +#include + +// +// A reflection database and its interface, consistent with the OpenGL API reflection queries. +// + +namespace glslang { + +class TIntermediate; +class TIntermAggregate; +class TReflectionTraverser; + +// The full reflection database +class TReflection { +public: + TReflection(EShReflectionOptions opts, EShLanguage first, EShLanguage last) + : options(opts), firstStage(first), lastStage(last), badReflection(TObjectReflection::badReflection()) + { + for (int dim=0; dim<3; ++dim) + localSize[dim] = 0; + } + + virtual ~TReflection() {} + + // grow the reflection stage by stage + bool addStage(EShLanguage, const TIntermediate&); + + // for mapping a uniform index to a uniform object's description + int getNumUniforms() { return (int)indexToUniform.size(); } + const TObjectReflection& getUniform(int i) const + { + if (i >= 0 && i < (int)indexToUniform.size()) + return indexToUniform[i]; + else + return badReflection; + } + + // for mapping a block index to the block's description + int getNumUniformBlocks() const { return (int)indexToUniformBlock.size(); } + const TObjectReflection& getUniformBlock(int i) const + { + if (i >= 0 && i < (int)indexToUniformBlock.size()) + return indexToUniformBlock[i]; + else + return badReflection; + } + + // for mapping an pipeline input index to the input's description + int getNumPipeInputs() { return (int)indexToPipeInput.size(); } + const TObjectReflection& getPipeInput(int i) const + { + if (i >= 0 && i < (int)indexToPipeInput.size()) + return indexToPipeInput[i]; + else + return badReflection; + } + + // for mapping an pipeline output index to the output's description + int getNumPipeOutputs() { return (int)indexToPipeOutput.size(); } + const TObjectReflection& getPipeOutput(int i) const + { + if (i >= 0 && i < (int)indexToPipeOutput.size()) + return indexToPipeOutput[i]; + else + return badReflection; + } + + // for mapping from an atomic counter to the uniform index + int getNumAtomicCounters() const { return (int)atomicCounterUniformIndices.size(); } + const TObjectReflection& getAtomicCounter(int i) const + { + if (i >= 0 && i < (int)atomicCounterUniformIndices.size()) + return getUniform(atomicCounterUniformIndices[i]); + else + return badReflection; + } + + // for mapping a buffer variable index to a buffer variable object's description + int getNumBufferVariables() { return (int)indexToBufferVariable.size(); } + const TObjectReflection& getBufferVariable(int i) const + { + if (i >= 0 && i < (int)indexToBufferVariable.size()) + return indexToBufferVariable[i]; + else + return badReflection; + } + + // for mapping a storage block index to the storage block's description + int getNumStorageBuffers() const { return (int)indexToBufferBlock.size(); } + const TObjectReflection& getStorageBufferBlock(int i) const + { + if (i >= 0 && i < (int)indexToBufferBlock.size()) + return indexToBufferBlock[i]; + else + return badReflection; + } + + // for mapping any name to its index (block names, uniform names and input/output names) + int getIndex(const char* name) const + { + TNameToIndex::const_iterator it = nameToIndex.find(name); + if (it == nameToIndex.end()) + return -1; + else + return it->second; + } + + // see getIndex(const char*) + int getIndex(const TString& name) const { return getIndex(name.c_str()); } + + + // for mapping any name to its index (only pipe input/output names) + int getPipeIOIndex(const char* name, const bool inOrOut) const + { + TNameToIndex::const_iterator it = inOrOut ? pipeInNameToIndex.find(name) : pipeOutNameToIndex.find(name); + if (it == (inOrOut ? pipeInNameToIndex.end() : pipeOutNameToIndex.end())) + return -1; + else + return it->second; + } + + // see gePipeIOIndex(const char*, const bool) + int getPipeIOIndex(const TString& name, const bool inOrOut) const { return getPipeIOIndex(name.c_str(), inOrOut); } + + // Thread local size + unsigned getLocalSize(int dim) const { return dim <= 2 ? localSize[dim] : 0; } + + void dump(); + +protected: + friend class glslang::TReflectionTraverser; + + void buildCounterIndices(const TIntermediate&); + void buildUniformStageMask(const TIntermediate& intermediate); + void buildAttributeReflection(EShLanguage, const TIntermediate&); + + // Need a TString hash: typedef std::unordered_map TNameToIndex; + typedef std::map TNameToIndex; + typedef std::vector TMapIndexToReflection; + typedef std::vector TIndices; + + TMapIndexToReflection& GetBlockMapForStorage(TStorageQualifier storage) + { + if ((options & EShReflectionSeparateBuffers) && storage == EvqBuffer) + return indexToBufferBlock; + return indexToUniformBlock; + } + TMapIndexToReflection& GetVariableMapForStorage(TStorageQualifier storage) + { + if ((options & EShReflectionSeparateBuffers) && storage == EvqBuffer) + return indexToBufferVariable; + return indexToUniform; + } + + EShReflectionOptions options; + + EShLanguage firstStage; + EShLanguage lastStage; + + TObjectReflection badReflection; // return for queries of -1 or generally out of range; has expected descriptions with in it for this + TNameToIndex nameToIndex; // maps names to indexes; can hold all types of data: uniform/buffer and which function names have been processed + TNameToIndex pipeInNameToIndex; // maps pipe in names to indexes, this is a fix to seperate pipe I/O from uniforms and buffers. + TNameToIndex pipeOutNameToIndex; // maps pipe out names to indexes, this is a fix to seperate pipe I/O from uniforms and buffers. + TMapIndexToReflection indexToUniform; + TMapIndexToReflection indexToUniformBlock; + TMapIndexToReflection indexToBufferVariable; + TMapIndexToReflection indexToBufferBlock; + TMapIndexToReflection indexToPipeInput; + TMapIndexToReflection indexToPipeOutput; + TIndices atomicCounterUniformIndices; + + unsigned int localSize[3]; +}; + +} // end namespace glslang + +#endif // _REFLECTION_INCLUDED + +#endif // GLSLANG_WEB diff --git a/android/arm64-v8a/include/glslang/glslang/Public/ShaderLang.h b/android/arm64-v8a/include/glslang/glslang/Public/ShaderLang.h new file mode 100644 index 00000000..acb2a078 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/Public/ShaderLang.h @@ -0,0 +1,927 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013-2016 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +#ifndef _COMPILER_INTERFACE_INCLUDED_ +#define _COMPILER_INTERFACE_INCLUDED_ + +#include "../Include/ResourceLimits.h" +#include "../MachineIndependent/Versions.h" + +#include +#include + +#ifdef _WIN32 +#define C_DECL __cdecl +//#ifdef SH_EXPORTING +// #define SH_IMPORT_EXPORT __declspec(dllexport) +//#else +// #define SH_IMPORT_EXPORT __declspec(dllimport) +//#endif +#define SH_IMPORT_EXPORT +#else +#define SH_IMPORT_EXPORT +#define C_DECL +#endif + +// +// This is the platform independent interface between an OGL driver +// and the shading language compiler/linker. +// + +#ifdef __cplusplus + extern "C" { +#endif + +// This should always increase, as some paths to do not consume +// a more major number. +// It should increment by one when new functionality is added. +#define GLSLANG_MINOR_VERSION 13 + +// +// Call before doing any other compiler/linker operations. +// +// (Call once per process, not once per thread.) +// +SH_IMPORT_EXPORT int ShInitialize(); + +// +// Call this at process shutdown to clean up memory. +// +SH_IMPORT_EXPORT int ShFinalize(); + +// +// Types of languages the compiler can consume. +// +typedef enum { + EShLangVertex, + EShLangTessControl, + EShLangTessEvaluation, + EShLangGeometry, + EShLangFragment, + EShLangCompute, + EShLangRayGen, + EShLangRayGenNV = EShLangRayGen, + EShLangIntersect, + EShLangIntersectNV = EShLangIntersect, + EShLangAnyHit, + EShLangAnyHitNV = EShLangAnyHit, + EShLangClosestHit, + EShLangClosestHitNV = EShLangClosestHit, + EShLangMiss, + EShLangMissNV = EShLangMiss, + EShLangCallable, + EShLangCallableNV = EShLangCallable, + EShLangTaskNV, + EShLangMeshNV, + LAST_ELEMENT_MARKER(EShLangCount), +} EShLanguage; // would be better as stage, but this is ancient now + +typedef enum { + EShLangVertexMask = (1 << EShLangVertex), + EShLangTessControlMask = (1 << EShLangTessControl), + EShLangTessEvaluationMask = (1 << EShLangTessEvaluation), + EShLangGeometryMask = (1 << EShLangGeometry), + EShLangFragmentMask = (1 << EShLangFragment), + EShLangComputeMask = (1 << EShLangCompute), + EShLangRayGenMask = (1 << EShLangRayGen), + EShLangRayGenNVMask = EShLangRayGenMask, + EShLangIntersectMask = (1 << EShLangIntersect), + EShLangIntersectNVMask = EShLangIntersectMask, + EShLangAnyHitMask = (1 << EShLangAnyHit), + EShLangAnyHitNVMask = EShLangAnyHitMask, + EShLangClosestHitMask = (1 << EShLangClosestHit), + EShLangClosestHitNVMask = EShLangClosestHitMask, + EShLangMissMask = (1 << EShLangMiss), + EShLangMissNVMask = EShLangMissMask, + EShLangCallableMask = (1 << EShLangCallable), + EShLangCallableNVMask = EShLangCallableMask, + EShLangTaskNVMask = (1 << EShLangTaskNV), + EShLangMeshNVMask = (1 << EShLangMeshNV), + LAST_ELEMENT_MARKER(EShLanguageMaskCount), +} EShLanguageMask; + +namespace glslang { + +class TType; + +typedef enum { + EShSourceNone, + EShSourceGlsl, // GLSL, includes ESSL (OpenGL ES GLSL) + EShSourceHlsl, // HLSL + LAST_ELEMENT_MARKER(EShSourceCount), +} EShSource; // if EShLanguage were EShStage, this could be EShLanguage instead + +typedef enum { + EShClientNone, // use when there is no client, e.g. for validation + EShClientVulkan, + EShClientOpenGL, + LAST_ELEMENT_MARKER(EShClientCount), +} EShClient; + +typedef enum { + EShTargetNone, + EShTargetSpv, // SPIR-V (preferred spelling) + EshTargetSpv = EShTargetSpv, // legacy spelling + LAST_ELEMENT_MARKER(EShTargetCount), +} EShTargetLanguage; + +typedef enum { + EShTargetVulkan_1_0 = (1 << 22), // Vulkan 1.0 + EShTargetVulkan_1_1 = (1 << 22) | (1 << 12), // Vulkan 1.1 + EShTargetVulkan_1_2 = (1 << 22) | (2 << 12), // Vulkan 1.2 + EShTargetOpenGL_450 = 450, // OpenGL + LAST_ELEMENT_MARKER(EShTargetClientVersionCount), +} EShTargetClientVersion; + +typedef EShTargetClientVersion EshTargetClientVersion; + +typedef enum { + EShTargetSpv_1_0 = (1 << 16), // SPIR-V 1.0 + EShTargetSpv_1_1 = (1 << 16) | (1 << 8), // SPIR-V 1.1 + EShTargetSpv_1_2 = (1 << 16) | (2 << 8), // SPIR-V 1.2 + EShTargetSpv_1_3 = (1 << 16) | (3 << 8), // SPIR-V 1.3 + EShTargetSpv_1_4 = (1 << 16) | (4 << 8), // SPIR-V 1.4 + EShTargetSpv_1_5 = (1 << 16) | (5 << 8), // SPIR-V 1.5 + LAST_ELEMENT_MARKER(EShTargetLanguageVersionCount), +} EShTargetLanguageVersion; + +struct TInputLanguage { + EShSource languageFamily; // redundant information with other input, this one overrides when not EShSourceNone + EShLanguage stage; // redundant information with other input, this one overrides when not EShSourceNone + EShClient dialect; + int dialectVersion; // version of client's language definition, not the client (when not EShClientNone) +}; + +struct TClient { + EShClient client; + EShTargetClientVersion version; // version of client itself (not the client's input dialect) +}; + +struct TTarget { + EShTargetLanguage language; + EShTargetLanguageVersion version; // version to target, if SPIR-V, defined by "word 1" of the SPIR-V header + bool hlslFunctionality1; // can target hlsl_functionality1 extension(s) +}; + +// All source/client/target versions and settings. +// Can override previous methods of setting, when items are set here. +// Expected to grow, as more are added, rather than growing parameter lists. +struct TEnvironment { + TInputLanguage input; // definition of the input language + TClient client; // what client is the overall compilation being done for? + TTarget target; // what to generate +}; + +const char* StageName(EShLanguage); + +} // end namespace glslang + +// +// Types of output the linker will create. +// +typedef enum { + EShExVertexFragment, + EShExFragment +} EShExecutable; + +// +// Optimization level for the compiler. +// +typedef enum { + EShOptNoGeneration, + EShOptNone, + EShOptSimple, // Optimizations that can be done quickly + EShOptFull, // Optimizations that will take more time + LAST_ELEMENT_MARKER(EshOptLevelCount), +} EShOptimizationLevel; + +// +// Texture and Sampler transformation mode. +// +typedef enum { + EShTexSampTransKeep, // keep textures and samplers as is (default) + EShTexSampTransUpgradeTextureRemoveSampler, // change texture w/o embeded sampler into sampled texture and throw away all samplers + LAST_ELEMENT_MARKER(EShTexSampTransCount), +} EShTextureSamplerTransformMode; + +// +// Message choices for what errors and warnings are given. +// +enum EShMessages { + EShMsgDefault = 0, // default is to give all required errors and extra warnings + EShMsgRelaxedErrors = (1 << 0), // be liberal in accepting input + EShMsgSuppressWarnings = (1 << 1), // suppress all warnings, except those required by the specification + EShMsgAST = (1 << 2), // print the AST intermediate representation + EShMsgSpvRules = (1 << 3), // issue messages for SPIR-V generation + EShMsgVulkanRules = (1 << 4), // issue messages for Vulkan-requirements of GLSL for SPIR-V + EShMsgOnlyPreprocessor = (1 << 5), // only print out errors produced by the preprocessor + EShMsgReadHlsl = (1 << 6), // use HLSL parsing rules and semantics + EShMsgCascadingErrors = (1 << 7), // get cascading errors; risks error-recovery issues, instead of an early exit + EShMsgKeepUncalled = (1 << 8), // for testing, don't eliminate uncalled functions + EShMsgHlslOffsets = (1 << 9), // allow block offsets to follow HLSL rules instead of GLSL rules + EShMsgDebugInfo = (1 << 10), // save debug information + EShMsgHlslEnable16BitTypes = (1 << 11), // enable use of 16-bit types in SPIR-V for HLSL + EShMsgHlslLegalization = (1 << 12), // enable HLSL Legalization messages + EShMsgHlslDX9Compatible = (1 << 13), // enable HLSL DX9 compatible mode (right now only for samplers) + EShMsgBuiltinSymbolTable = (1 << 14), // print the builtin symbol table + LAST_ELEMENT_MARKER(EShMsgCount), +}; + +// +// Options for building reflection +// +typedef enum { + EShReflectionDefault = 0, // default is original behaviour before options were added + EShReflectionStrictArraySuffix = (1 << 0), // reflection will follow stricter rules for array-of-structs suffixes + EShReflectionBasicArraySuffix = (1 << 1), // arrays of basic types will be appended with [0] as in GL reflection + EShReflectionIntermediateIO = (1 << 2), // reflect inputs and outputs to program, even with no vertex shader + EShReflectionSeparateBuffers = (1 << 3), // buffer variables and buffer blocks are reflected separately + EShReflectionAllBlockVariables = (1 << 4), // reflect all variables in blocks, even if they are inactive + EShReflectionUnwrapIOBlocks = (1 << 5), // unwrap input/output blocks the same as with uniform blocks + LAST_ELEMENT_MARKER(EShReflectionCount), +} EShReflectionOptions; + +// +// Build a table for bindings. This can be used for locating +// attributes, uniforms, globals, etc., as needed. +// +typedef struct { + const char* name; + int binding; +} ShBinding; + +typedef struct { + int numBindings; + ShBinding* bindings; // array of bindings +} ShBindingTable; + +// +// ShHandle held by but opaque to the driver. It is allocated, +// managed, and de-allocated by the compiler/linker. It's contents +// are defined by and used by the compiler and linker. For example, +// symbol table information and object code passed from the compiler +// to the linker can be stored where ShHandle points. +// +// If handle creation fails, 0 will be returned. +// +typedef void* ShHandle; + +// +// Driver calls these to create and destroy compiler/linker +// objects. +// +SH_IMPORT_EXPORT ShHandle ShConstructCompiler(const EShLanguage, int debugOptions); // one per shader +SH_IMPORT_EXPORT ShHandle ShConstructLinker(const EShExecutable, int debugOptions); // one per shader pair +SH_IMPORT_EXPORT ShHandle ShConstructUniformMap(); // one per uniform namespace (currently entire program object) +SH_IMPORT_EXPORT void ShDestruct(ShHandle); + +// +// The return value of ShCompile is boolean, non-zero indicating +// success. +// +// The info-log should be written by ShCompile into +// ShHandle, so it can answer future queries. +// +SH_IMPORT_EXPORT int ShCompile( + const ShHandle, + const char* const shaderStrings[], + const int numStrings, + const int* lengths, + const EShOptimizationLevel, + const TBuiltInResource *resources, + int debugOptions, + int defaultVersion = 110, // use 100 for ES environment, overridden by #version in shader + bool forwardCompatible = false, // give errors for use of deprecated features + EShMessages messages = EShMsgDefault // warnings and errors + ); + +SH_IMPORT_EXPORT int ShLinkExt( + const ShHandle, // linker object + const ShHandle h[], // compiler objects to link together + const int numHandles); + +// +// ShSetEncrpytionMethod is a place-holder for specifying +// how source code is encrypted. +// +SH_IMPORT_EXPORT void ShSetEncryptionMethod(ShHandle); + +// +// All the following return 0 if the information is not +// available in the object passed down, or the object is bad. +// +SH_IMPORT_EXPORT const char* ShGetInfoLog(const ShHandle); +SH_IMPORT_EXPORT const void* ShGetExecutable(const ShHandle); +SH_IMPORT_EXPORT int ShSetVirtualAttributeBindings(const ShHandle, const ShBindingTable*); // to detect user aliasing +SH_IMPORT_EXPORT int ShSetFixedAttributeBindings(const ShHandle, const ShBindingTable*); // to force any physical mappings +// +// Tell the linker to never assign a vertex attribute to this list of physical attributes +// +SH_IMPORT_EXPORT int ShExcludeAttributes(const ShHandle, int *attributes, int count); + +// +// Returns the location ID of the named uniform. +// Returns -1 if error. +// +SH_IMPORT_EXPORT int ShGetUniformLocation(const ShHandle uniformMap, const char* name); + +#ifdef __cplusplus + } // end extern "C" +#endif + +//////////////////////////////////////////////////////////////////////////////////////////// +// +// Deferred-Lowering C++ Interface +// ----------------------------------- +// +// Below is a new alternate C++ interface, which deprecates the above +// opaque handle-based interface. +// +// The below is further designed to handle multiple compilation units per stage, where +// the intermediate results, including the parse tree, are preserved until link time, +// rather than the above interface which is designed to have each compilation unit +// lowered at compile time. In the above model, linking occurs on the lowered results, +// whereas in this model intra-stage linking can occur at the parse tree +// (treeRoot in TIntermediate) level, and then a full stage can be lowered. +// + +#include +#include +#include + +class TCompiler; +class TInfoSink; + +namespace glslang { + +const char* GetEsslVersionString(); +const char* GetGlslVersionString(); +int GetKhronosToolId(); + +class TIntermediate; +class TProgram; +class TPoolAllocator; + +// Call this exactly once per process before using anything else +bool InitializeProcess(); + +// Call once per process to tear down everything +void FinalizeProcess(); + +// Resource type for IO resolver +enum TResourceType { + EResSampler, + EResTexture, + EResImage, + EResUbo, + EResSsbo, + EResUav, + EResCount +}; + +// Make one TShader per shader that you will link into a program. Then +// - provide the shader through setStrings() or setStringsWithLengths() +// - optionally call setEnv*(), see below for more detail +// - optionally use setPreamble() to set a special shader string that will be +// processed before all others but won't affect the validity of #version +// - optionally call addProcesses() for each setting/transform, +// see comment for class TProcesses +// - call parse(): source language and target environment must be selected +// either by correct setting of EShMessages sent to parse(), or by +// explicitly calling setEnv*() +// - query the info logs +// +// N.B.: Does not yet support having the same TShader instance being linked into +// multiple programs. +// +// N.B.: Destruct a linked program *before* destructing the shaders linked into it. +// +class TShader { +public: + explicit TShader(EShLanguage); + virtual ~TShader(); + void setStrings(const char* const* s, int n); + void setStringsWithLengths(const char* const* s, const int* l, int n); + void setStringsWithLengthsAndNames( + const char* const* s, const int* l, const char* const* names, int n); + void setPreamble(const char* s) { preamble = s; } + void setEntryPoint(const char* entryPoint); + void setSourceEntryPoint(const char* sourceEntryPointName); + void addProcesses(const std::vector&); + + // IO resolver binding data: see comments in ShaderLang.cpp + void setShiftBinding(TResourceType res, unsigned int base); + void setShiftSamplerBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftTextureBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftImageBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftUboBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftUavBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftCbufferBinding(unsigned int base); // synonym for setShiftUboBinding + void setShiftSsboBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftBindingForSet(TResourceType res, unsigned int base, unsigned int set); + void setResourceSetBinding(const std::vector& base); + void setAutoMapBindings(bool map); + void setAutoMapLocations(bool map); + void addUniformLocationOverride(const char* name, int loc); + void setUniformLocationBase(int base); + void setInvertY(bool invert); +#ifdef ENABLE_HLSL + void setHlslIoMapping(bool hlslIoMap); + void setFlattenUniformArrays(bool flatten); +#endif + void setNoStorageFormat(bool useUnknownFormat); + void setNanMinMaxClamp(bool nanMinMaxClamp); + void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode); + + // For setting up the environment (cleared to nothingness in the constructor). + // These must be called so that parsing is done for the right source language and + // target environment, either indirectly through TranslateEnvironment() based on + // EShMessages et. al., or directly by the user. + // + // setEnvInput: The input source language and stage. If generating code for a + // specific client, the input client semantics to use and the + // version of the that client's input semantics to use, otherwise + // use EShClientNone and version of 0, e.g. for validation mode. + // Note 'version' does not describe the target environment, + // just the version of the source dialect to compile under. + // + // See the definitions of TEnvironment, EShSource, EShLanguage, + // and EShClient for choices and more detail. + // + // setEnvClient: The client that will be hosting the execution, and it's version. + // Note 'version' is not the version of the languages involved, but + // the version of the client environment. + // Use EShClientNone and version of 0 if there is no client, e.g. + // for validation mode. + // + // See EShTargetClientVersion for choices. + // + // setEnvTarget: The language to translate to when generating code, and that + // language's version. + // Use EShTargetNone and version of 0 if there is no client, e.g. + // for validation mode. + // + void setEnvInput(EShSource lang, EShLanguage envStage, EShClient client, int version) + { + environment.input.languageFamily = lang; + environment.input.stage = envStage; + environment.input.dialect = client; + environment.input.dialectVersion = version; + } + void setEnvClient(EShClient client, EShTargetClientVersion version) + { + environment.client.client = client; + environment.client.version = version; + } + void setEnvTarget(EShTargetLanguage lang, EShTargetLanguageVersion version) + { + environment.target.language = lang; + environment.target.version = version; + } + + void getStrings(const char* const* &s, int& n) { s = strings; n = numStrings; } + +#ifdef ENABLE_HLSL + void setEnvTargetHlslFunctionality1() { environment.target.hlslFunctionality1 = true; } + bool getEnvTargetHlslFunctionality1() const { return environment.target.hlslFunctionality1; } +#else + bool getEnvTargetHlslFunctionality1() const { return false; } +#endif + + // Interface to #include handlers. + // + // To support #include, a client of Glslang does the following: + // 1. Call setStringsWithNames to set the source strings and associated + // names. For example, the names could be the names of the files + // containing the shader sources. + // 2. Call parse with an Includer. + // + // When the Glslang parser encounters an #include directive, it calls + // the Includer's include method with the requested include name + // together with the current string name. The returned IncludeResult + // contains the fully resolved name of the included source, together + // with the source text that should replace the #include directive + // in the source stream. After parsing that source, Glslang will + // release the IncludeResult object. + class Includer { + public: + // An IncludeResult contains the resolved name and content of a source + // inclusion. + struct IncludeResult { + IncludeResult(const std::string& headerName, const char* const headerData, const size_t headerLength, void* userData) : + headerName(headerName), headerData(headerData), headerLength(headerLength), userData(userData) { } + // For a successful inclusion, the fully resolved name of the requested + // include. For example, in a file system-based includer, full resolution + // should convert a relative path name into an absolute path name. + // For a failed inclusion, this is an empty string. + const std::string headerName; + // The content and byte length of the requested inclusion. The + // Includer producing this IncludeResult retains ownership of the + // storage. + // For a failed inclusion, the header + // field points to a string containing error details. + const char* const headerData; + const size_t headerLength; + // Include resolver's context. + void* userData; + protected: + IncludeResult& operator=(const IncludeResult&); + IncludeResult(); + }; + + // For both include methods below: + // + // Resolves an inclusion request by name, current source name, + // and include depth. + // On success, returns an IncludeResult containing the resolved name + // and content of the include. + // On failure, returns a nullptr, or an IncludeResult + // with an empty string for the headerName and error details in the + // header field. + // The Includer retains ownership of the contents + // of the returned IncludeResult value, and those contents must + // remain valid until the releaseInclude method is called on that + // IncludeResult object. + // + // Note "local" vs. "system" is not an "either/or": "local" is an + // extra thing to do over "system". Both might get called, as per + // the C++ specification. + + // For the "system" or <>-style includes; search the "system" paths. + virtual IncludeResult* includeSystem(const char* /*headerName*/, + const char* /*includerName*/, + size_t /*inclusionDepth*/) { return nullptr; } + + // For the "local"-only aspect of a "" include. Should not search in the + // "system" paths, because on returning a failure, the parser will + // call includeSystem() to look in the "system" locations. + virtual IncludeResult* includeLocal(const char* /*headerName*/, + const char* /*includerName*/, + size_t /*inclusionDepth*/) { return nullptr; } + + // Signals that the parser will no longer use the contents of the + // specified IncludeResult. + virtual void releaseInclude(IncludeResult*) = 0; + virtual ~Includer() {} + }; + + // Fail all Includer searches + class ForbidIncluder : public Includer { + public: + virtual void releaseInclude(IncludeResult*) override { } + }; + + bool parse(const TBuiltInResource*, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, + bool forwardCompatible, EShMessages, Includer&); + + bool parse(const TBuiltInResource* res, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, + bool forwardCompatible, EShMessages messages) + { + TShader::ForbidIncluder includer; + return parse(res, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, messages, includer); + } + + // Equivalent to parse() without a default profile and without forcing defaults. + bool parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages) + { + return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages); + } + + bool parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages, + Includer& includer) + { + return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages, includer); + } + + // NOTE: Doing just preprocessing to obtain a correct preprocessed shader string + // is not an officially supported or fully working path. + bool preprocess(const TBuiltInResource* builtInResources, + int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, + bool forwardCompatible, EShMessages message, std::string* outputString, + Includer& includer); + + const char* getInfoLog(); + const char* getInfoDebugLog(); + EShLanguage getStage() const { return stage; } + TIntermediate* getIntermediate() const { return intermediate; } + +protected: + TPoolAllocator* pool; + EShLanguage stage; + TCompiler* compiler; + TIntermediate* intermediate; + TInfoSink* infoSink; + // strings and lengths follow the standard for glShaderSource: + // strings is an array of numStrings pointers to string data. + // lengths can be null, but if not it is an array of numStrings + // integers containing the length of the associated strings. + // if lengths is null or lengths[n] < 0 the associated strings[n] is + // assumed to be null-terminated. + // stringNames is the optional names for all the strings. If stringNames + // is null, then none of the strings has name. If a certain element in + // stringNames is null, then the corresponding string does not have name. + const char* const* strings; // explicit code to compile, see previous comment + const int* lengths; + const char* const* stringNames; + int numStrings; // size of the above arrays + const char* preamble; // string of implicit code to compile before the explicitly provided code + + // a function in the source string can be renamed FROM this TO the name given in setEntryPoint. + std::string sourceEntryPointName; + + TEnvironment environment; + + friend class TProgram; + +private: + TShader& operator=(TShader&); +}; + +#ifndef GLSLANG_WEB + +// +// A reflection database and its interface, consistent with the OpenGL API reflection queries. +// + +// Data needed for just a single object at the granularity exchanged by the reflection API +class TObjectReflection { +public: + TObjectReflection(const std::string& pName, const TType& pType, int pOffset, int pGLDefineType, int pSize, int pIndex); + + const TType* getType() const { return type; } + int getBinding() const; + void dump() const; + static TObjectReflection badReflection() { return TObjectReflection(); } + + std::string name; + int offset; + int glDefineType; + int size; // data size in bytes for a block, array size for a (non-block) object that's an array + int index; + int counterIndex; + int numMembers; + int arrayStride; // stride of an array variable + int topLevelArrayStride; // stride of the top-level variable in a storage buffer member + EShLanguageMask stages; + +protected: + TObjectReflection() + : offset(-1), glDefineType(-1), size(-1), index(-1), counterIndex(-1), numMembers(-1), arrayStride(0), + topLevelArrayStride(0), stages(EShLanguageMask(0)), type(nullptr) + { + } + + const TType* type; +}; + +class TReflection; +class TIoMapper; +struct TVarEntryInfo; + +// Allows to customize the binding layout after linking. +// All used uniform variables will invoke at least validateBinding. +// If validateBinding returned true then the other resolveBinding, +// resolveSet, and resolveLocation are invoked to resolve the binding +// and descriptor set index respectively. +// +// Invocations happen in a particular order: +// 1) all shader inputs +// 2) all shader outputs +// 3) all uniforms with binding and set already defined +// 4) all uniforms with binding but no set defined +// 5) all uniforms with set but no binding defined +// 6) all uniforms with no binding and no set defined +// +// mapIO will use this resolver in two phases. The first +// phase is a notification phase, calling the corresponging +// notifiy callbacks, this phase ends with a call to endNotifications. +// Phase two starts directly after the call to endNotifications +// and calls all other callbacks to validate and to get the +// bindings, sets, locations, component and color indices. +// +// NOTE: that still limit checks are applied to bindings and sets +// and may result in an error. +class TIoMapResolver +{ +public: + virtual ~TIoMapResolver() {} + + // Should return true if the resulting/current binding would be okay. + // Basic idea is to do aliasing binding checks with this. + virtual bool validateBinding(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current binding should be overridden. + // Return -1 if the current binding (including no binding) should be kept. + virtual int resolveBinding(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current set should be overridden. + // Return -1 if the current set (including no set) should be kept. + virtual int resolveSet(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current location should be overridden. + // Return -1 if the current location (including no location) should be kept. + virtual int resolveUniformLocation(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return true if the resulting/current setup would be okay. + // Basic idea is to do aliasing checks and reject invalid semantic names. + virtual bool validateInOut(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current location should be overridden. + // Return -1 if the current location (including no location) should be kept. + virtual int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current component index should be overridden. + // Return -1 if the current component index (including no index) should be kept. + virtual int resolveInOutComponent(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current color index should be overridden. + // Return -1 if the current color index (including no index) should be kept. + virtual int resolveInOutIndex(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Notification of a uniform variable + virtual void notifyBinding(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Notification of a in or out variable + virtual void notifyInOut(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Called by mapIO when it starts its notify pass for the given stage + virtual void beginNotifications(EShLanguage stage) = 0; + // Called by mapIO when it has finished the notify pass + virtual void endNotifications(EShLanguage stage) = 0; + // Called by mipIO when it starts its resolve pass for the given stage + virtual void beginResolve(EShLanguage stage) = 0; + // Called by mapIO when it has finished the resolve pass + virtual void endResolve(EShLanguage stage) = 0; + // Called by mapIO when it starts its symbol collect for teh given stage + virtual void beginCollect(EShLanguage stage) = 0; + // Called by mapIO when it has finished the symbol collect + virtual void endCollect(EShLanguage stage) = 0; + // Called by TSlotCollector to resolve storage locations or bindings + virtual void reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) = 0; + // Called by TSlotCollector to resolve resource locations or bindings + virtual void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) = 0; + // Called by mapIO.addStage to set shader stage mask to mark a stage be added to this pipeline + virtual void addStage(EShLanguage stage) = 0; +}; + +#endif // GLSLANG_WEB + +// Make one TProgram per set of shaders that will get linked together. Add all +// the shaders that are to be linked together. After calling shader.parse() +// for all shaders, call link(). +// +// N.B.: Destruct a linked program *before* destructing the shaders linked into it. +// +class TProgram { +public: + TProgram(); + virtual ~TProgram(); + void addShader(TShader* shader) { stages[shader->stage].push_back(shader); } + std::list& getShaders(EShLanguage stage) { return stages[stage]; } + // Link Validation interface + bool link(EShMessages); + const char* getInfoLog(); + const char* getInfoDebugLog(); + + TIntermediate* getIntermediate(EShLanguage stage) const { return intermediate[stage]; } + +#ifndef GLSLANG_WEB + + // Reflection Interface + + // call first, to do liveness analysis, index mapping, etc.; returns false on failure + bool buildReflection(int opts = EShReflectionDefault); + unsigned getLocalSize(int dim) const; // return dim'th local size + int getReflectionIndex(const char *name) const; + int getReflectionPipeIOIndex(const char* name, const bool inOrOut) const; + int getNumUniformVariables() const; + const TObjectReflection& getUniform(int index) const; + int getNumUniformBlocks() const; + const TObjectReflection& getUniformBlock(int index) const; + int getNumPipeInputs() const; + const TObjectReflection& getPipeInput(int index) const; + int getNumPipeOutputs() const; + const TObjectReflection& getPipeOutput(int index) const; + int getNumBufferVariables() const; + const TObjectReflection& getBufferVariable(int index) const; + int getNumBufferBlocks() const; + const TObjectReflection& getBufferBlock(int index) const; + int getNumAtomicCounters() const; + const TObjectReflection& getAtomicCounter(int index) const; + + // Legacy Reflection Interface - expressed in terms of above interface + + // can be used for glGetProgramiv(GL_ACTIVE_UNIFORMS) + int getNumLiveUniformVariables() const { return getNumUniformVariables(); } + + // can be used for glGetProgramiv(GL_ACTIVE_UNIFORM_BLOCKS) + int getNumLiveUniformBlocks() const { return getNumUniformBlocks(); } + + // can be used for glGetProgramiv(GL_ACTIVE_ATTRIBUTES) + int getNumLiveAttributes() const { return getNumPipeInputs(); } + + // can be used for glGetUniformIndices() + int getUniformIndex(const char *name) const { return getReflectionIndex(name); } + + int getPipeIOIndex(const char *name, const bool inOrOut) const + { return getReflectionPipeIOIndex(name, inOrOut); } + + // can be used for "name" part of glGetActiveUniform() + const char *getUniformName(int index) const { return getUniform(index).name.c_str(); } + + // returns the binding number + int getUniformBinding(int index) const { return getUniform(index).getBinding(); } + + // returns Shaders Stages where a Uniform is present + EShLanguageMask getUniformStages(int index) const { return getUniform(index).stages; } + + // can be used for glGetActiveUniformsiv(GL_UNIFORM_BLOCK_INDEX) + int getUniformBlockIndex(int index) const { return getUniform(index).index; } + + // can be used for glGetActiveUniformsiv(GL_UNIFORM_TYPE) + int getUniformType(int index) const { return getUniform(index).glDefineType; } + + // can be used for glGetActiveUniformsiv(GL_UNIFORM_OFFSET) + int getUniformBufferOffset(int index) const { return getUniform(index).offset; } + + // can be used for glGetActiveUniformsiv(GL_UNIFORM_SIZE) + int getUniformArraySize(int index) const { return getUniform(index).size; } + + // returns a TType* + const TType *getUniformTType(int index) const { return getUniform(index).getType(); } + + // can be used for glGetActiveUniformBlockName() + const char *getUniformBlockName(int index) const { return getUniformBlock(index).name.c_str(); } + + // can be used for glGetActiveUniformBlockiv(UNIFORM_BLOCK_DATA_SIZE) + int getUniformBlockSize(int index) const { return getUniformBlock(index).size; } + + // returns the block binding number + int getUniformBlockBinding(int index) const { return getUniformBlock(index).getBinding(); } + + // returns block index of associated counter. + int getUniformBlockCounterIndex(int index) const { return getUniformBlock(index).counterIndex; } + + // returns a TType* + const TType *getUniformBlockTType(int index) const { return getUniformBlock(index).getType(); } + + // can be used for glGetActiveAttrib() + const char *getAttributeName(int index) const { return getPipeInput(index).name.c_str(); } + + // can be used for glGetActiveAttrib() + int getAttributeType(int index) const { return getPipeInput(index).glDefineType; } + + // returns a TType* + const TType *getAttributeTType(int index) const { return getPipeInput(index).getType(); } + + void dumpReflection(); + // I/O mapping: apply base offsets and map live unbound variables + // If resolver is not provided it uses the previous approach + // and respects auto assignment and offsets. + bool mapIO(TIoMapResolver* pResolver = nullptr, TIoMapper* pIoMapper = nullptr); +#endif + +protected: + bool linkStage(EShLanguage, EShMessages); + + TPoolAllocator* pool; + std::list stages[EShLangCount]; + TIntermediate* intermediate[EShLangCount]; + bool newedIntermediate[EShLangCount]; // track which intermediate were "new" versus reusing a singleton unit in a stage + TInfoSink* infoSink; +#ifndef GLSLANG_WEB + TReflection* reflection; +#endif + bool linked; + +private: + TProgram(TProgram&); + TProgram& operator=(TProgram&); +}; + +} // end namespace glslang + +#endif // _COMPILER_INTERFACE_INCLUDED_ diff --git a/android/arm64-v8a/include/glslang/glslang/SPIRV/GLSL.ext.AMD.h b/android/arm64-v8a/include/glslang/glslang/SPIRV/GLSL.ext.AMD.h new file mode 100644 index 00000000..009d2f1c --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/SPIRV/GLSL.ext.AMD.h @@ -0,0 +1,108 @@ +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextAMD_H +#define GLSLextAMD_H + +static const int GLSLextAMDVersion = 100; +static const int GLSLextAMDRevision = 7; + +// SPV_AMD_shader_ballot +static const char* const E_SPV_AMD_shader_ballot = "SPV_AMD_shader_ballot"; + +enum ShaderBallotAMD { + ShaderBallotBadAMD = 0, // Don't use + + SwizzleInvocationsAMD = 1, + SwizzleInvocationsMaskedAMD = 2, + WriteInvocationAMD = 3, + MbcntAMD = 4, + + ShaderBallotCountAMD +}; + +// SPV_AMD_shader_trinary_minmax +static const char* const E_SPV_AMD_shader_trinary_minmax = "SPV_AMD_shader_trinary_minmax"; + +enum ShaderTrinaryMinMaxAMD { + ShaderTrinaryMinMaxBadAMD = 0, // Don't use + + FMin3AMD = 1, + UMin3AMD = 2, + SMin3AMD = 3, + FMax3AMD = 4, + UMax3AMD = 5, + SMax3AMD = 6, + FMid3AMD = 7, + UMid3AMD = 8, + SMid3AMD = 9, + + ShaderTrinaryMinMaxCountAMD +}; + +// SPV_AMD_shader_explicit_vertex_parameter +static const char* const E_SPV_AMD_shader_explicit_vertex_parameter = "SPV_AMD_shader_explicit_vertex_parameter"; + +enum ShaderExplicitVertexParameterAMD { + ShaderExplicitVertexParameterBadAMD = 0, // Don't use + + InterpolateAtVertexAMD = 1, + + ShaderExplicitVertexParameterCountAMD +}; + +// SPV_AMD_gcn_shader +static const char* const E_SPV_AMD_gcn_shader = "SPV_AMD_gcn_shader"; + +enum GcnShaderAMD { + GcnShaderBadAMD = 0, // Don't use + + CubeFaceIndexAMD = 1, + CubeFaceCoordAMD = 2, + TimeAMD = 3, + + GcnShaderCountAMD +}; + +// SPV_AMD_gpu_shader_half_float +static const char* const E_SPV_AMD_gpu_shader_half_float = "SPV_AMD_gpu_shader_half_float"; + +// SPV_AMD_texture_gather_bias_lod +static const char* const E_SPV_AMD_texture_gather_bias_lod = "SPV_AMD_texture_gather_bias_lod"; + +// SPV_AMD_gpu_shader_int16 +static const char* const E_SPV_AMD_gpu_shader_int16 = "SPV_AMD_gpu_shader_int16"; + +// SPV_AMD_shader_image_load_store_lod +static const char* const E_SPV_AMD_shader_image_load_store_lod = "SPV_AMD_shader_image_load_store_lod"; + +// SPV_AMD_shader_fragment_mask +static const char* const E_SPV_AMD_shader_fragment_mask = "SPV_AMD_shader_fragment_mask"; + +// SPV_AMD_gpu_shader_half_float_fetch +static const char* const E_SPV_AMD_gpu_shader_half_float_fetch = "SPV_AMD_gpu_shader_half_float_fetch"; + +#endif // #ifndef GLSLextAMD_H diff --git a/android/arm64-v8a/include/glslang/glslang/SPIRV/GLSL.ext.EXT.h b/android/arm64-v8a/include/glslang/glslang/SPIRV/GLSL.ext.EXT.h new file mode 100644 index 00000000..40164b61 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/SPIRV/GLSL.ext.EXT.h @@ -0,0 +1,39 @@ +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextEXT_H +#define GLSLextEXT_H + +static const int GLSLextEXTVersion = 100; +static const int GLSLextEXTRevision = 2; + +static const char* const E_SPV_EXT_shader_stencil_export = "SPV_EXT_shader_stencil_export"; +static const char* const E_SPV_EXT_shader_viewport_index_layer = "SPV_EXT_shader_viewport_index_layer"; +static const char* const E_SPV_EXT_fragment_fully_covered = "SPV_EXT_fragment_fully_covered"; +static const char* const E_SPV_EXT_fragment_invocation_density = "SPV_EXT_fragment_invocation_density"; +static const char* const E_SPV_EXT_demote_to_helper_invocation = "SPV_EXT_demote_to_helper_invocation"; + +#endif // #ifndef GLSLextEXT_H diff --git a/android/arm64-v8a/include/glslang/glslang/SPIRV/GLSL.ext.KHR.h b/android/arm64-v8a/include/glslang/glslang/SPIRV/GLSL.ext.KHR.h new file mode 100644 index 00000000..d783a8f2 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/SPIRV/GLSL.ext.KHR.h @@ -0,0 +1,51 @@ +/* +** Copyright (c) 2014-2020 The Khronos Group Inc. +** Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextKHR_H +#define GLSLextKHR_H + +static const int GLSLextKHRVersion = 100; +static const int GLSLextKHRRevision = 2; + +static const char* const E_SPV_KHR_shader_ballot = "SPV_KHR_shader_ballot"; +static const char* const E_SPV_KHR_subgroup_vote = "SPV_KHR_subgroup_vote"; +static const char* const E_SPV_KHR_device_group = "SPV_KHR_device_group"; +static const char* const E_SPV_KHR_multiview = "SPV_KHR_multiview"; +static const char* const E_SPV_KHR_shader_draw_parameters = "SPV_KHR_shader_draw_parameters"; +static const char* const E_SPV_KHR_16bit_storage = "SPV_KHR_16bit_storage"; +static const char* const E_SPV_KHR_8bit_storage = "SPV_KHR_8bit_storage"; +static const char* const E_SPV_KHR_storage_buffer_storage_class = "SPV_KHR_storage_buffer_storage_class"; +static const char* const E_SPV_KHR_post_depth_coverage = "SPV_KHR_post_depth_coverage"; +static const char* const E_SPV_KHR_vulkan_memory_model = "SPV_KHR_vulkan_memory_model"; +static const char* const E_SPV_EXT_physical_storage_buffer = "SPV_EXT_physical_storage_buffer"; +static const char* const E_SPV_KHR_physical_storage_buffer = "SPV_KHR_physical_storage_buffer"; +static const char* const E_SPV_EXT_fragment_shader_interlock = "SPV_EXT_fragment_shader_interlock"; +static const char* const E_SPV_KHR_shader_clock = "SPV_KHR_shader_clock"; +static const char* const E_SPV_KHR_non_semantic_info = "SPV_KHR_non_semantic_info"; +static const char* const E_SPV_KHR_ray_tracing = "SPV_KHR_ray_tracing"; +static const char* const E_SPV_KHR_ray_query = "SPV_KHR_ray_query"; +#endif // #ifndef GLSLextKHR_H diff --git a/android/arm64-v8a/include/glslang/glslang/SPIRV/GLSL.ext.NV.h b/android/arm64-v8a/include/glslang/glslang/SPIRV/GLSL.ext.NV.h new file mode 100644 index 00000000..50146da1 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/SPIRV/GLSL.ext.NV.h @@ -0,0 +1,81 @@ +/* +** Copyright (c) 2014-2017 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextNV_H +#define GLSLextNV_H + +enum BuiltIn; +enum Decoration; +enum Op; +enum Capability; + +static const int GLSLextNVVersion = 100; +static const int GLSLextNVRevision = 11; + +//SPV_NV_sample_mask_override_coverage +const char* const E_SPV_NV_sample_mask_override_coverage = "SPV_NV_sample_mask_override_coverage"; + +//SPV_NV_geometry_shader_passthrough +const char* const E_SPV_NV_geometry_shader_passthrough = "SPV_NV_geometry_shader_passthrough"; + +//SPV_NV_viewport_array2 +const char* const E_SPV_NV_viewport_array2 = "SPV_NV_viewport_array2"; +const char* const E_ARB_shader_viewport_layer_array = "SPV_ARB_shader_viewport_layer_array"; + +//SPV_NV_stereo_view_rendering +const char* const E_SPV_NV_stereo_view_rendering = "SPV_NV_stereo_view_rendering"; + +//SPV_NVX_multiview_per_view_attributes +const char* const E_SPV_NVX_multiview_per_view_attributes = "SPV_NVX_multiview_per_view_attributes"; + +//SPV_NV_shader_subgroup_partitioned +const char* const E_SPV_NV_shader_subgroup_partitioned = "SPV_NV_shader_subgroup_partitioned"; + +//SPV_NV_fragment_shader_barycentric +const char* const E_SPV_NV_fragment_shader_barycentric = "SPV_NV_fragment_shader_barycentric"; + +//SPV_NV_compute_shader_derivatives +const char* const E_SPV_NV_compute_shader_derivatives = "SPV_NV_compute_shader_derivatives"; + +//SPV_NV_shader_image_footprint +const char* const E_SPV_NV_shader_image_footprint = "SPV_NV_shader_image_footprint"; + +//SPV_NV_mesh_shader +const char* const E_SPV_NV_mesh_shader = "SPV_NV_mesh_shader"; + +//SPV_NV_raytracing +const char* const E_SPV_NV_ray_tracing = "SPV_NV_ray_tracing"; + +//SPV_NV_shading_rate +const char* const E_SPV_NV_shading_rate = "SPV_NV_shading_rate"; + +//SPV_NV_cooperative_matrix +const char* const E_SPV_NV_cooperative_matrix = "SPV_NV_cooperative_matrix"; + +//SPV_NV_shader_sm_builtins +const char* const E_SPV_NV_shader_sm_builtins = "SPV_NV_shader_sm_builtins"; + +#endif // #ifndef GLSLextNV_H diff --git a/android/arm64-v8a/include/glslang/glslang/SPIRV/GLSL.std.450.h b/android/arm64-v8a/include/glslang/glslang/SPIRV/GLSL.std.450.h new file mode 100644 index 00000000..df31092b --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/SPIRV/GLSL.std.450.h @@ -0,0 +1,131 @@ +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLstd450_H +#define GLSLstd450_H + +static const int GLSLstd450Version = 100; +static const int GLSLstd450Revision = 1; + +enum GLSLstd450 { + GLSLstd450Bad = 0, // Don't use + + GLSLstd450Round = 1, + GLSLstd450RoundEven = 2, + GLSLstd450Trunc = 3, + GLSLstd450FAbs = 4, + GLSLstd450SAbs = 5, + GLSLstd450FSign = 6, + GLSLstd450SSign = 7, + GLSLstd450Floor = 8, + GLSLstd450Ceil = 9, + GLSLstd450Fract = 10, + + GLSLstd450Radians = 11, + GLSLstd450Degrees = 12, + GLSLstd450Sin = 13, + GLSLstd450Cos = 14, + GLSLstd450Tan = 15, + GLSLstd450Asin = 16, + GLSLstd450Acos = 17, + GLSLstd450Atan = 18, + GLSLstd450Sinh = 19, + GLSLstd450Cosh = 20, + GLSLstd450Tanh = 21, + GLSLstd450Asinh = 22, + GLSLstd450Acosh = 23, + GLSLstd450Atanh = 24, + GLSLstd450Atan2 = 25, + + GLSLstd450Pow = 26, + GLSLstd450Exp = 27, + GLSLstd450Log = 28, + GLSLstd450Exp2 = 29, + GLSLstd450Log2 = 30, + GLSLstd450Sqrt = 31, + GLSLstd450InverseSqrt = 32, + + GLSLstd450Determinant = 33, + GLSLstd450MatrixInverse = 34, + + GLSLstd450Modf = 35, // second operand needs an OpVariable to write to + GLSLstd450ModfStruct = 36, // no OpVariable operand + GLSLstd450FMin = 37, + GLSLstd450UMin = 38, + GLSLstd450SMin = 39, + GLSLstd450FMax = 40, + GLSLstd450UMax = 41, + GLSLstd450SMax = 42, + GLSLstd450FClamp = 43, + GLSLstd450UClamp = 44, + GLSLstd450SClamp = 45, + GLSLstd450FMix = 46, + GLSLstd450IMix = 47, // Reserved + GLSLstd450Step = 48, + GLSLstd450SmoothStep = 49, + + GLSLstd450Fma = 50, + GLSLstd450Frexp = 51, // second operand needs an OpVariable to write to + GLSLstd450FrexpStruct = 52, // no OpVariable operand + GLSLstd450Ldexp = 53, + + GLSLstd450PackSnorm4x8 = 54, + GLSLstd450PackUnorm4x8 = 55, + GLSLstd450PackSnorm2x16 = 56, + GLSLstd450PackUnorm2x16 = 57, + GLSLstd450PackHalf2x16 = 58, + GLSLstd450PackDouble2x32 = 59, + GLSLstd450UnpackSnorm2x16 = 60, + GLSLstd450UnpackUnorm2x16 = 61, + GLSLstd450UnpackHalf2x16 = 62, + GLSLstd450UnpackSnorm4x8 = 63, + GLSLstd450UnpackUnorm4x8 = 64, + GLSLstd450UnpackDouble2x32 = 65, + + GLSLstd450Length = 66, + GLSLstd450Distance = 67, + GLSLstd450Cross = 68, + GLSLstd450Normalize = 69, + GLSLstd450FaceForward = 70, + GLSLstd450Reflect = 71, + GLSLstd450Refract = 72, + + GLSLstd450FindILsb = 73, + GLSLstd450FindSMsb = 74, + GLSLstd450FindUMsb = 75, + + GLSLstd450InterpolateAtCentroid = 76, + GLSLstd450InterpolateAtSample = 77, + GLSLstd450InterpolateAtOffset = 78, + + GLSLstd450NMin = 79, + GLSLstd450NMax = 80, + GLSLstd450NClamp = 81, + + GLSLstd450Count +}; + +#endif // #ifndef GLSLstd450_H diff --git a/android/arm64-v8a/include/glslang/glslang/SPIRV/GlslangToSpv.h b/android/arm64-v8a/include/glslang/glslang/SPIRV/GlslangToSpv.h new file mode 100644 index 00000000..3907be43 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/SPIRV/GlslangToSpv.h @@ -0,0 +1,61 @@ +// +// Copyright (C) 2014 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#pragma once + +#if defined(_MSC_VER) && _MSC_VER >= 1900 + #pragma warning(disable : 4464) // relative include path contains '..' +#endif + +#include "SpvTools.h" +#include "glslang/Include/intermediate.h" + +#include +#include + +#include "Logger.h" + +namespace glslang { + +void GetSpirvVersion(std::string&); +int GetSpirvGeneratorVersion(); +void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, + SpvOptions* options = nullptr); +void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger* logger, SpvOptions* options = nullptr); +void OutputSpvBin(const std::vector& spirv, const char* baseName); +void OutputSpvHex(const std::vector& spirv, const char* baseName, const char* varName); + +} diff --git a/android/arm64-v8a/include/glslang/glslang/SPIRV/Logger.h b/android/arm64-v8a/include/glslang/glslang/SPIRV/Logger.h new file mode 100644 index 00000000..411367c0 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/SPIRV/Logger.h @@ -0,0 +1,83 @@ +// +// Copyright (C) 2016 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef GLSLANG_SPIRV_LOGGER_H +#define GLSLANG_SPIRV_LOGGER_H + +#include +#include + +namespace spv { + +// A class for holding all SPIR-V build status messages, including +// missing/TBD functionalities, warnings, and errors. +class SpvBuildLogger { +public: + SpvBuildLogger() {} + +#ifdef GLSLANG_WEB + void tbdFunctionality(const std::string& f) { } + void missingFunctionality(const std::string& f) { } + void warning(const std::string& w) { } + void error(const std::string& e) { errors.push_back(e); } + std::string getAllMessages() { return ""; } +#else + + // Registers a TBD functionality. + void tbdFunctionality(const std::string& f); + // Registers a missing functionality. + void missingFunctionality(const std::string& f); + + // Logs a warning. + void warning(const std::string& w) { warnings.push_back(w); } + // Logs an error. + void error(const std::string& e) { errors.push_back(e); } + + // Returns all messages accumulated in the order of: + // TBD functionalities, missing functionalities, warnings, errors. + std::string getAllMessages() const; +#endif + +private: + SpvBuildLogger(const SpvBuildLogger&); + + std::vector tbdFeatures; + std::vector missingFeatures; + std::vector warnings; + std::vector errors; +}; + +} // end spv namespace + +#endif // GLSLANG_SPIRV_LOGGER_H diff --git a/android/arm64-v8a/include/glslang/glslang/SPIRV/NonSemanticDebugPrintf.h b/android/arm64-v8a/include/glslang/glslang/SPIRV/NonSemanticDebugPrintf.h new file mode 100644 index 00000000..83796d75 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/SPIRV/NonSemanticDebugPrintf.h @@ -0,0 +1,50 @@ +// Copyright (c) 2020 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and/or associated documentation files (the +// "Materials"), to deal in the Materials without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Materials, and to +// permit persons to whom the Materials are furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS +// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS +// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT +// https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +// + +#ifndef SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ +#define SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + NonSemanticDebugPrintfRevision = 1, + NonSemanticDebugPrintfRevision_BitWidthPadding = 0x7fffffff +}; + +enum NonSemanticDebugPrintfInstructions { + NonSemanticDebugPrintfDebugPrintf = 1, + NonSemanticDebugPrintfInstructionsMax = 0x7fffffff +}; + + +#ifdef __cplusplus +} +#endif + +#endif // SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ diff --git a/android/arm64-v8a/include/glslang/glslang/SPIRV/SPVRemapper.h b/android/arm64-v8a/include/glslang/glslang/SPIRV/SPVRemapper.h new file mode 100644 index 00000000..d6b9c346 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/SPIRV/SPVRemapper.h @@ -0,0 +1,304 @@ +// +// Copyright (C) 2015 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef SPIRVREMAPPER_H +#define SPIRVREMAPPER_H + +#include +#include +#include +#include + +namespace spv { + +// MSVC defines __cplusplus as an older value, even when it supports almost all of 11. +// We handle that here by making our own symbol. +#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1700) +# define use_cpp11 1 +#endif + +class spirvbin_base_t +{ +public: + enum Options { + NONE = 0, + STRIP = (1<<0), + MAP_TYPES = (1<<1), + MAP_NAMES = (1<<2), + MAP_FUNCS = (1<<3), + DCE_FUNCS = (1<<4), + DCE_VARS = (1<<5), + DCE_TYPES = (1<<6), + OPT_LOADSTORE = (1<<7), + OPT_FWD_LS = (1<<8), // EXPERIMENTAL: PRODUCES INVALID SCHEMA-0 SPIRV + MAP_ALL = (MAP_TYPES | MAP_NAMES | MAP_FUNCS), + DCE_ALL = (DCE_FUNCS | DCE_VARS | DCE_TYPES), + OPT_ALL = (OPT_LOADSTORE), + + ALL_BUT_STRIP = (MAP_ALL | DCE_ALL | OPT_ALL), + DO_EVERYTHING = (STRIP | ALL_BUT_STRIP) + }; +}; + +} // namespace SPV + +#if !defined (use_cpp11) +#include +#include + +namespace spv { +class spirvbin_t : public spirvbin_base_t +{ +public: + spirvbin_t(int /*verbose = 0*/) { } + + void remap(std::vector& /*spv*/, unsigned int /*opts = 0*/) + { + printf("Tool not compiled for C++11, which is required for SPIR-V remapping.\n"); + exit(5); + } +}; + +} // namespace SPV + +#else // defined (use_cpp11) + +#include +#include +#include +#include +#include +#include +#include + +#include "spirv.hpp" +#include "spvIR.h" + +namespace spv { + +// class to hold SPIR-V binary data for remapping, DCE, and debug stripping +class spirvbin_t : public spirvbin_base_t +{ +public: + spirvbin_t(int verbose = 0) : entryPoint(spv::NoResult), largestNewId(0), verbose(verbose), errorLatch(false) + { } + + virtual ~spirvbin_t() { } + + // remap on an existing binary in memory + void remap(std::vector& spv, std::uint32_t opts = DO_EVERYTHING); + + // Type for error/log handler functions + typedef std::function errorfn_t; + typedef std::function logfn_t; + + // Register error/log handling functions (can be lambda fn / functor / etc) + static void registerErrorHandler(errorfn_t handler) { errorHandler = handler; } + static void registerLogHandler(logfn_t handler) { logHandler = handler; } + +protected: + // This can be overridden to provide other message behavior if needed + virtual void msg(int minVerbosity, int indent, const std::string& txt) const; + +private: + // Local to global, or global to local ID map + typedef std::unordered_map idmap_t; + typedef std::unordered_set idset_t; + typedef std::unordered_map blockmap_t; + + void remap(std::uint32_t opts = DO_EVERYTHING); + + // Map of names to IDs + typedef std::unordered_map namemap_t; + + typedef std::uint32_t spirword_t; + + typedef std::pair range_t; + typedef std::function idfn_t; + typedef std::function instfn_t; + + // Special Values for ID map: + static const spv::Id unmapped; // unchanged from default value + static const spv::Id unused; // unused ID + static const int header_size; // SPIR header = 5 words + + class id_iterator_t; + + // For mapping type entries between different shaders + typedef std::vector typeentry_t; + typedef std::map globaltypes_t; + + // A set that preserves position order, and a reverse map + typedef std::set posmap_t; + typedef std::unordered_map posmap_rev_t; + + // Maps and ID to the size of its base type, if known. + typedef std::unordered_map typesize_map_t; + + // handle error + void error(const std::string& txt) const { errorLatch = true; errorHandler(txt); } + + bool isConstOp(spv::Op opCode) const; + bool isTypeOp(spv::Op opCode) const; + bool isStripOp(spv::Op opCode) const; + bool isFlowCtrl(spv::Op opCode) const; + range_t literalRange(spv::Op opCode) const; + range_t typeRange(spv::Op opCode) const; + range_t constRange(spv::Op opCode) const; + unsigned typeSizeInWords(spv::Id id) const; + unsigned idTypeSizeInWords(spv::Id id) const; + + spv::Id& asId(unsigned word) { return spv[word]; } + const spv::Id& asId(unsigned word) const { return spv[word]; } + spv::Op asOpCode(unsigned word) const { return opOpCode(spv[word]); } + std::uint32_t asOpCodeHash(unsigned word); + spv::Decoration asDecoration(unsigned word) const { return spv::Decoration(spv[word]); } + unsigned asWordCount(unsigned word) const { return opWordCount(spv[word]); } + spv::Id asTypeConstId(unsigned word) const { return asId(word + (isTypeOp(asOpCode(word)) ? 1 : 2)); } + unsigned idPos(spv::Id id) const; + + static unsigned opWordCount(spirword_t data) { return data >> spv::WordCountShift; } + static spv::Op opOpCode(spirword_t data) { return spv::Op(data & spv::OpCodeMask); } + + // Header access & set methods + spirword_t magic() const { return spv[0]; } // return magic number + spirword_t bound() const { return spv[3]; } // return Id bound from header + spirword_t bound(spirword_t b) { return spv[3] = b; } + spirword_t genmagic() const { return spv[2]; } // generator magic + spirword_t genmagic(spirword_t m) { return spv[2] = m; } + spirword_t schemaNum() const { return spv[4]; } // schema number from header + + // Mapping fns: get + spv::Id localId(spv::Id id) const { return idMapL[id]; } + + // Mapping fns: set + inline spv::Id localId(spv::Id id, spv::Id newId); + void countIds(spv::Id id); + + // Return next unused new local ID. + // NOTE: boost::dynamic_bitset would be more efficient due to find_next(), + // which std::vector doens't have. + inline spv::Id nextUnusedId(spv::Id id); + + void buildLocalMaps(); + std::string literalString(unsigned word) const; // Return literal as a std::string + int literalStringWords(const std::string& str) const { return (int(str.size())+4)/4; } + + bool isNewIdMapped(spv::Id newId) const { return isMapped(newId); } + bool isOldIdUnmapped(spv::Id oldId) const { return localId(oldId) == unmapped; } + bool isOldIdUnused(spv::Id oldId) const { return localId(oldId) == unused; } + bool isOldIdMapped(spv::Id oldId) const { return !isOldIdUnused(oldId) && !isOldIdUnmapped(oldId); } + bool isFunction(spv::Id oldId) const { return fnPos.find(oldId) != fnPos.end(); } + + // bool matchType(const globaltypes_t& globalTypes, spv::Id lt, spv::Id gt) const; + // spv::Id findType(const globaltypes_t& globalTypes, spv::Id lt) const; + std::uint32_t hashType(unsigned typeStart) const; + + spirvbin_t& process(instfn_t, idfn_t, unsigned begin = 0, unsigned end = 0); + int processInstruction(unsigned word, instfn_t, idfn_t); + + void validate() const; + void mapTypeConst(); + void mapFnBodies(); + void optLoadStore(); + void dceFuncs(); + void dceVars(); + void dceTypes(); + void mapNames(); + void foldIds(); // fold IDs to smallest space + void forwardLoadStores(); // load store forwarding (EXPERIMENTAL) + void offsetIds(); // create relative offset IDs + + void applyMap(); // remap per local name map + void mapRemainder(); // map any IDs we haven't touched yet + void stripDebug(); // strip all debug info + void stripDeadRefs(); // strips debug info for now-dead references after DCE + void strip(); // remove debug symbols + + std::vector spv; // SPIR words + + namemap_t nameMap; // ID names from OpName + + // Since we want to also do binary ops, we can't use std::vector. we could use + // boost::dynamic_bitset, but we're trying to avoid a boost dependency. + typedef std::uint64_t bits_t; + std::vector mapped; // which new IDs have been mapped + static const int mBits = sizeof(bits_t) * 4; + + bool isMapped(spv::Id id) const { return id < maxMappedId() && ((mapped[id/mBits] & (1LL<<(id%mBits))) != 0); } + void setMapped(spv::Id id) { resizeMapped(id); mapped[id/mBits] |= (1LL<<(id%mBits)); } + void resizeMapped(spv::Id id) { if (id >= maxMappedId()) mapped.resize(id/mBits+1, 0); } + size_t maxMappedId() const { return mapped.size() * mBits; } + + // Add a strip range for a given instruction starting at 'start' + // Note: avoiding brace initializers to please older versions os MSVC. + void stripInst(unsigned start) { stripRange.push_back(range_t(start, start + asWordCount(start))); } + + // Function start and end. use unordered_map because we'll have + // many fewer functions than IDs. + std::unordered_map fnPos; + + // Which functions are called, anywhere in the module, with a call count + std::unordered_map fnCalls; + + posmap_t typeConstPos; // word positions that define types & consts (ordered) + posmap_rev_t idPosR; // reverse map from IDs to positions + typesize_map_t idTypeSizeMap; // maps each ID to its type size, if known. + + std::vector idMapL; // ID {M}ap from {L}ocal to {G}lobal IDs + + spv::Id entryPoint; // module entry point + spv::Id largestNewId; // biggest new ID we have mapped anything to + + // Sections of the binary to strip, given as [begin,end) + std::vector stripRange; + + // processing options: + std::uint32_t options; + int verbose; // verbosity level + + // Error latch: this is set if the error handler is ever executed. It would be better to + // use a try/catch block and throw, but that's not desired for certain environments, so + // this is the alternative. + mutable bool errorLatch; + + static errorfn_t errorHandler; + static logfn_t logHandler; +}; + +} // namespace SPV + +#endif // defined (use_cpp11) +#endif // SPIRVREMAPPER_H diff --git a/android/arm64-v8a/include/glslang/glslang/SPIRV/SpvBuilder.h b/android/arm64-v8a/include/glslang/glslang/SPIRV/SpvBuilder.h new file mode 100644 index 00000000..71b90d60 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/SPIRV/SpvBuilder.h @@ -0,0 +1,838 @@ +// +// Copyright (C) 2014-2015 LunarG, Inc. +// Copyright (C) 2015-2020 Google, Inc. +// Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// "Builder" is an interface to fully build SPIR-V IR. Allocate one of +// these to build (a thread safe) internal SPIR-V representation (IR), +// and then dump it as a binary stream according to the SPIR-V specification. +// +// A Builder has a 1:1 relationship with a SPIR-V module. +// + +#pragma once +#ifndef SpvBuilder_H +#define SpvBuilder_H + +#include "Logger.h" +#include "spirv.hpp" +#include "spvIR.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace spv { + +typedef enum { + Spv_1_0 = (1 << 16), + Spv_1_1 = (1 << 16) | (1 << 8), + Spv_1_2 = (1 << 16) | (2 << 8), + Spv_1_3 = (1 << 16) | (3 << 8), + Spv_1_4 = (1 << 16) | (4 << 8), + Spv_1_5 = (1 << 16) | (5 << 8), +} SpvVersion; + +class Builder { +public: + Builder(unsigned int spvVersion, unsigned int userNumber, SpvBuildLogger* logger); + virtual ~Builder(); + + static const int maxMatrixSize = 4; + + unsigned int getSpvVersion() const { return spvVersion; } + + void setSource(spv::SourceLanguage lang, int version) + { + source = lang; + sourceVersion = version; + } + spv::Id getStringId(const std::string& str) + { + auto sItr = stringIds.find(str); + if (sItr != stringIds.end()) + return sItr->second; + spv::Id strId = getUniqueId(); + Instruction* fileString = new Instruction(strId, NoType, OpString); + const char* file_c_str = str.c_str(); + fileString->addStringOperand(file_c_str); + strings.push_back(std::unique_ptr(fileString)); + module.mapInstruction(fileString); + stringIds[file_c_str] = strId; + return strId; + } + void setSourceFile(const std::string& file) + { + sourceFileStringId = getStringId(file); + } + void setSourceText(const std::string& text) { sourceText = text; } + void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); } + void addModuleProcessed(const std::string& p) { moduleProcesses.push_back(p.c_str()); } + void setEmitOpLines() { emitOpLines = true; } + void addExtension(const char* ext) { extensions.insert(ext); } + void removeExtension(const char* ext) + { + extensions.erase(ext); + } + void addIncorporatedExtension(const char* ext, SpvVersion incorporatedVersion) + { + if (getSpvVersion() < static_cast(incorporatedVersion)) + addExtension(ext); + } + void promoteIncorporatedExtension(const char* baseExt, const char* promoExt, SpvVersion incorporatedVersion) + { + removeExtension(baseExt); + addIncorporatedExtension(promoExt, incorporatedVersion); + } + void addInclude(const std::string& name, const std::string& text) + { + spv::Id incId = getStringId(name); + includeFiles[incId] = &text; + } + Id import(const char*); + void setMemoryModel(spv::AddressingModel addr, spv::MemoryModel mem) + { + addressModel = addr; + memoryModel = mem; + } + + void addCapability(spv::Capability cap) { capabilities.insert(cap); } + + // To get a new for anything needing a new one. + Id getUniqueId() { return ++uniqueId; } + + // To get a set of new s, e.g., for a set of function parameters + Id getUniqueIds(int numIds) + { + Id id = uniqueId + 1; + uniqueId += numIds; + return id; + } + + // Generate OpLine for non-filename-based #line directives (ie no filename + // seen yet): Log the current line, and if different than the last one, + // issue a new OpLine using the new line and current source file name. + void setLine(int line); + + // If filename null, generate OpLine for non-filename-based line directives, + // else do filename-based: Log the current line and file, and if different + // than the last one, issue a new OpLine using the new line and file + // name. + void setLine(int line, const char* filename); + // Low-level OpLine. See setLine() for a layered helper. + void addLine(Id fileName, int line, int column); + + // For creating new types (will return old type if the requested one was already made). + Id makeVoidType(); + Id makeBoolType(); + Id makePointer(StorageClass, Id pointee); + Id makeForwardPointer(StorageClass); + Id makePointerFromForwardPointer(StorageClass, Id forwardPointerType, Id pointee); + Id makeIntegerType(int width, bool hasSign); // generic + Id makeIntType(int width) { return makeIntegerType(width, true); } + Id makeUintType(int width) { return makeIntegerType(width, false); } + Id makeFloatType(int width); + Id makeStructType(const std::vector& members, const char*); + Id makeStructResultType(Id type0, Id type1); + Id makeVectorType(Id component, int size); + Id makeMatrixType(Id component, int cols, int rows); + Id makeArrayType(Id element, Id sizeId, int stride); // 0 stride means no stride decoration + Id makeRuntimeArray(Id element); + Id makeFunctionType(Id returnType, const std::vector& paramTypes); + Id makeImageType(Id sampledType, Dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format); + Id makeSamplerType(); + Id makeSampledImageType(Id imageType); + Id makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols); + + // accelerationStructureNV type + Id makeAccelerationStructureType(); + // rayQueryEXT type + Id makeRayQueryType(); + + // For querying about types. + Id getTypeId(Id resultId) const { return module.getTypeId(resultId); } + Id getDerefTypeId(Id resultId) const; + Op getOpCode(Id id) const { return module.getInstruction(id)->getOpCode(); } + Op getTypeClass(Id typeId) const { return getOpCode(typeId); } + Op getMostBasicTypeClass(Id typeId) const; + int getNumComponents(Id resultId) const { return getNumTypeComponents(getTypeId(resultId)); } + int getNumTypeConstituents(Id typeId) const; + int getNumTypeComponents(Id typeId) const { return getNumTypeConstituents(typeId); } + Id getScalarTypeId(Id typeId) const; + Id getContainedTypeId(Id typeId) const; + Id getContainedTypeId(Id typeId, int) const; + StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); } + ImageFormat getImageTypeFormat(Id typeId) const + { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); } + + bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); } + bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); } + bool isVector(Id resultId) const { return isVectorType(getTypeId(resultId)); } + bool isMatrix(Id resultId) const { return isMatrixType(getTypeId(resultId)); } + bool isCooperativeMatrix(Id resultId)const { return isCooperativeMatrixType(getTypeId(resultId)); } + bool isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); } + bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); } + + bool isBoolType(Id typeId) + { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); } + bool isIntType(Id typeId) const + { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; } + bool isUintType(Id typeId) const + { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; } + bool isFloatType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat; } + bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; } + bool isScalarType(Id typeId) const + { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt || + getTypeClass(typeId) == OpTypeBool; } + bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; } + bool isMatrixType(Id typeId) const { return getTypeClass(typeId) == OpTypeMatrix; } + bool isStructType(Id typeId) const { return getTypeClass(typeId) == OpTypeStruct; } + bool isArrayType(Id typeId) const { return getTypeClass(typeId) == OpTypeArray; } +#ifdef GLSLANG_WEB + bool isCooperativeMatrixType(Id typeId)const { return false; } +#else + bool isCooperativeMatrixType(Id typeId)const { return getTypeClass(typeId) == OpTypeCooperativeMatrixNV; } +#endif + bool isAggregateType(Id typeId) const + { return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); } + bool isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; } + bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; } + bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; } + bool containsType(Id typeId, Op typeOp, unsigned int width) const; + bool containsPhysicalStorageBufferOrArray(Id typeId) const; + + bool isConstantOpCode(Op opcode) const; + bool isSpecConstantOpCode(Op opcode) const; + bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); } + bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; } + bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); } + unsigned int getConstantScalar(Id resultId) const + { return module.getInstruction(resultId)->getImmediateOperand(0); } + StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); } + + int getScalarTypeWidth(Id typeId) const + { + Id scalarTypeId = getScalarTypeId(typeId); + assert(getTypeClass(scalarTypeId) == OpTypeInt || getTypeClass(scalarTypeId) == OpTypeFloat); + return module.getInstruction(scalarTypeId)->getImmediateOperand(0); + } + + int getTypeNumColumns(Id typeId) const + { + assert(isMatrixType(typeId)); + return getNumTypeConstituents(typeId); + } + int getNumColumns(Id resultId) const { return getTypeNumColumns(getTypeId(resultId)); } + int getTypeNumRows(Id typeId) const + { + assert(isMatrixType(typeId)); + return getNumTypeComponents(getContainedTypeId(typeId)); + } + int getNumRows(Id resultId) const { return getTypeNumRows(getTypeId(resultId)); } + + Dim getTypeDimensionality(Id typeId) const + { + assert(isImageType(typeId)); + return (Dim)module.getInstruction(typeId)->getImmediateOperand(1); + } + Id getImageType(Id resultId) const + { + Id typeId = getTypeId(resultId); + assert(isImageType(typeId) || isSampledImageType(typeId)); + return isSampledImageType(typeId) ? module.getInstruction(typeId)->getIdOperand(0) : typeId; + } + bool isArrayedImageType(Id typeId) const + { + assert(isImageType(typeId)); + return module.getInstruction(typeId)->getImmediateOperand(3) != 0; + } + + // For making new constants (will return old constant if the requested one was already made). + Id makeBoolConstant(bool b, bool specConstant = false); + Id makeInt8Constant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); } + Id makeUint8Constant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(8), u, specConstant); } + Id makeInt16Constant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(16), (unsigned)i, specConstant); } + Id makeUint16Constant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(16), u, specConstant); } + Id makeIntConstant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); } + Id makeUintConstant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(32), u, specConstant); } + Id makeInt64Constant(long long i, bool specConstant = false) + { return makeInt64Constant(makeIntType(64), (unsigned long long)i, specConstant); } + Id makeUint64Constant(unsigned long long u, bool specConstant = false) + { return makeInt64Constant(makeUintType(64), u, specConstant); } + Id makeFloatConstant(float f, bool specConstant = false); + Id makeDoubleConstant(double d, bool specConstant = false); + Id makeFloat16Constant(float f16, bool specConstant = false); + Id makeFpConstant(Id type, double d, bool specConstant = false); + + // Turn the array of constants into a proper spv constant of the requested type. + Id makeCompositeConstant(Id type, const std::vector& comps, bool specConst = false); + + // Methods for adding information outside the CFG. + Instruction* addEntryPoint(ExecutionModel, Function*, const char* name); + void addExecutionMode(Function*, ExecutionMode mode, int value1 = -1, int value2 = -1, int value3 = -1); + void addName(Id, const char* name); + void addMemberName(Id, int member, const char* name); + void addDecoration(Id, Decoration, int num = -1); + void addDecoration(Id, Decoration, const char*); + void addDecorationId(Id id, Decoration, Id idDecoration); + void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1); + void addMemberDecoration(Id, unsigned int member, Decoration, const char*); + + // At the end of what block do the next create*() instructions go? + void setBuildPoint(Block* bp) { buildPoint = bp; } + Block* getBuildPoint() const { return buildPoint; } + + // Make the entry-point function. The returned pointer is only valid + // for the lifetime of this builder. + Function* makeEntryPoint(const char*); + + // Make a shader-style function, and create its entry block if entry is non-zero. + // Return the function, pass back the entry. + // The returned pointer is only valid for the lifetime of this builder. + Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, + const std::vector& paramTypes, const std::vector>& precisions, Block **entry = 0); + + // Create a return. An 'implicit' return is one not appearing in the source + // code. In the case of an implicit return, no post-return block is inserted. + void makeReturn(bool implicit, Id retVal = 0); + + // Generate all the code needed to finish up a function. + void leaveFunction(); + + // Create a discard. + void makeDiscard(); + + // Create a global or function local or IO variable. + Id createVariable(StorageClass, Id type, const char* name = 0, Id initializer = NoResult); + + // Create an intermediate with an undefined value. + Id createUndefined(Id type); + + // Store into an Id and return the l-value + void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + + // Load from an Id and return it + Id createLoad(Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + + // Create an OpAccessChain instruction + Id createAccessChain(StorageClass, Id base, const std::vector& offsets); + + // Create an OpArrayLength instruction + Id createArrayLength(Id base, unsigned int member); + + // Create an OpCooperativeMatrixLengthNV instruction + Id createCooperativeMatrixLength(Id type); + + // Create an OpCompositeExtract instruction + Id createCompositeExtract(Id composite, Id typeId, unsigned index); + Id createCompositeExtract(Id composite, Id typeId, const std::vector& indexes); + Id createCompositeInsert(Id object, Id composite, Id typeId, unsigned index); + Id createCompositeInsert(Id object, Id composite, Id typeId, const std::vector& indexes); + + Id createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex); + Id createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex); + + void createNoResultOp(Op); + void createNoResultOp(Op, Id operand); + void createNoResultOp(Op, const std::vector& operands); + void createNoResultOp(Op, const std::vector& operands); + void createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask); + void createMemoryBarrier(unsigned executionScope, unsigned memorySemantics); + Id createUnaryOp(Op, Id typeId, Id operand); + Id createBinOp(Op, Id typeId, Id operand1, Id operand2); + Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3); + Id createOp(Op, Id typeId, const std::vector& operands); + Id createOp(Op, Id typeId, const std::vector& operands); + Id createFunctionCall(spv::Function*, const std::vector&); + Id createSpecConstantOp(Op, Id typeId, const std::vector& operands, const std::vector& literals); + + // Take an rvalue (source) and a set of channels to extract from it to + // make a new rvalue, which is returned. + Id createRvalueSwizzle(Decoration precision, Id typeId, Id source, const std::vector& channels); + + // Take a copy of an lvalue (target) and a source of components, and set the + // source components into the lvalue where the 'channels' say to put them. + // An updated version of the target is returned. + // (No true lvalue or stores are used.) + Id createLvalueSwizzle(Id typeId, Id target, Id source, const std::vector& channels); + + // If both the id and precision are valid, the id + // gets tagged with the requested precision. + // The passed in id is always the returned id, to simplify use patterns. + Id setPrecision(Id id, Decoration precision) + { + if (precision != NoPrecision && id != NoResult) + addDecoration(id, precision); + + return id; + } + + // Can smear a scalar to a vector for the following forms: + // - promoteScalar(scalar, vector) // smear scalar to width of vector + // - promoteScalar(vector, scalar) // smear scalar to width of vector + // - promoteScalar(pointer, scalar) // smear scalar to width of what pointer points to + // - promoteScalar(scalar, scalar) // do nothing + // Other forms are not allowed. + // + // Generally, the type of 'scalar' does not need to be the same type as the components in 'vector'. + // The type of the created vector is a vector of components of the same type as the scalar. + // + // Note: One of the arguments will change, with the result coming back that way rather than + // through the return value. + void promoteScalar(Decoration precision, Id& left, Id& right); + + // Make a value by smearing the scalar to fill the type. + // vectorType should be the correct type for making a vector of scalarVal. + // (No conversions are done.) + Id smearScalar(Decoration precision, Id scalarVal, Id vectorType); + + // Create a call to a built-in function. + Id createBuiltinCall(Id resultType, Id builtins, int entryPoint, const std::vector& args); + + // List of parameters used to create a texture operation + struct TextureParameters { + Id sampler; + Id coords; + Id bias; + Id lod; + Id Dref; + Id offset; + Id offsets; + Id gradX; + Id gradY; + Id sample; + Id component; + Id texelOut; + Id lodClamp; + Id granularity; + Id coarse; + bool nonprivate; + bool volatil; + }; + + // Select the correct texture operation based on all inputs, and emit the correct instruction + Id createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, + bool noImplicit, const TextureParameters&, ImageOperandsMask); + + // Emit the OpTextureQuery* instruction that was passed in. + // Figure out the right return value and type, and return it. + Id createTextureQueryCall(Op, const TextureParameters&, bool isUnsignedResult); + + Id createSamplePositionCall(Decoration precision, Id, Id); + + Id createBitFieldExtractCall(Decoration precision, Id, Id, Id, bool isSigned); + Id createBitFieldInsertCall(Decoration precision, Id, Id, Id, Id); + + // Reduction comparison for composites: For equal and not-equal resulting in a scalar. + Id createCompositeCompare(Decoration precision, Id, Id, bool /* true if for equal, false if for not-equal */); + + // OpCompositeConstruct + Id createCompositeConstruct(Id typeId, const std::vector& constituents); + + // vector or scalar constructor + Id createConstructor(Decoration precision, const std::vector& sources, Id resultTypeId); + + // matrix constructor + Id createMatrixConstructor(Decoration precision, const std::vector& sources, Id constructee); + + // Helper to use for building nested control flow with if-then-else. + class If { + public: + If(Id condition, unsigned int ctrl, Builder& builder); + ~If() {} + + void makeBeginElse(); + void makeEndIf(); + + private: + If(const If&); + If& operator=(If&); + + Builder& builder; + Id condition; + unsigned int control; + Function* function; + Block* headerBlock; + Block* thenBlock; + Block* elseBlock; + Block* mergeBlock; + }; + + // Make a switch statement. A switch has 'numSegments' of pieces of code, not containing + // any case/default labels, all separated by one or more case/default labels. Each possible + // case value v is a jump to the caseValues[v] segment. The defaultSegment is also in this + // number space. How to compute the value is given by 'condition', as in switch(condition). + // + // The SPIR-V Builder will maintain the stack of post-switch merge blocks for nested switches. + // + // Use a defaultSegment < 0 if there is no default segment (to branch to post switch). + // + // Returns the right set of basic blocks to start each code segment with, so that the caller's + // recursion stack can hold the memory for it. + // + void makeSwitch(Id condition, unsigned int control, int numSegments, const std::vector& caseValues, + const std::vector& valueToSegment, int defaultSegment, std::vector& segmentBB); + + // Add a branch to the innermost switch's merge block. + void addSwitchBreak(); + + // Move to the next code segment, passing in the return argument in makeSwitch() + void nextSwitchSegment(std::vector& segmentBB, int segment); + + // Finish off the innermost switch. + void endSwitch(std::vector& segmentBB); + + struct LoopBlocks { + LoopBlocks(Block& head, Block& body, Block& merge, Block& continue_target) : + head(head), body(body), merge(merge), continue_target(continue_target) { } + Block &head, &body, &merge, &continue_target; + private: + LoopBlocks(); + LoopBlocks& operator=(const LoopBlocks&) = delete; + }; + + // Start a new loop and prepare the builder to generate code for it. Until + // closeLoop() is called for this loop, createLoopContinue() and + // createLoopExit() will target its corresponding blocks. + LoopBlocks& makeNewLoop(); + + // Create a new block in the function containing the build point. Memory is + // owned by the function object. + Block& makeNewBlock(); + + // Add a branch to the continue_target of the current (innermost) loop. + void createLoopContinue(); + + // Add an exit (e.g. "break") from the innermost loop that we're currently + // in. + void createLoopExit(); + + // Close the innermost loop that you're in + void closeLoop(); + + // + // Access chain design for an R-Value vs. L-Value: + // + // There is a single access chain the builder is building at + // any particular time. Such a chain can be used to either to a load or + // a store, when desired. + // + // Expressions can be r-values, l-values, or both, or only r-values: + // a[b.c].d = .... // l-value + // ... = a[b.c].d; // r-value, that also looks like an l-value + // ++a[b.c].d; // r-value and l-value + // (x + y)[2]; // r-value only, can't possibly be l-value + // + // Computing an r-value means generating code. Hence, + // r-values should only be computed when they are needed, not speculatively. + // + // Computing an l-value means saving away information for later use in the compiler, + // no code is generated until the l-value is later dereferenced. It is okay + // to speculatively generate an l-value, just not okay to speculatively dereference it. + // + // The base of the access chain (the left-most variable or expression + // from which everything is based) can be set either as an l-value + // or as an r-value. Most efficient would be to set an l-value if one + // is available. If an expression was evaluated, the resulting r-value + // can be set as the chain base. + // + // The users of this single access chain can save and restore if they + // want to nest or manage multiple chains. + // + + struct AccessChain { + Id base; // for l-values, pointer to the base object, for r-values, the base object + std::vector indexChain; + Id instr; // cache the instruction that generates this access chain + std::vector swizzle; // each std::vector element selects the next GLSL component number + Id component; // a dynamic component index, can coexist with a swizzle, + // done after the swizzle, NoResult if not present + Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied; + // NoType unless a swizzle or component is present + bool isRValue; // true if 'base' is an r-value, otherwise, base is an l-value + unsigned int alignment; // bitwise OR of alignment values passed in. Accumulates worst alignment. + // Only tracks base and (optional) component selection alignment. + + // Accumulate whether anything in the chain of structures has coherent decorations. + struct CoherentFlags { + CoherentFlags() { clear(); } +#ifdef GLSLANG_WEB + void clear() { } + bool isVolatile() const { return false; } + CoherentFlags operator |=(const CoherentFlags &other) { return *this; } +#else + bool isVolatile() const { return volatil; } + bool anyCoherent() const { + return coherent || devicecoherent || queuefamilycoherent || workgroupcoherent || + subgroupcoherent || shadercallcoherent; + } + + unsigned coherent : 1; + unsigned devicecoherent : 1; + unsigned queuefamilycoherent : 1; + unsigned workgroupcoherent : 1; + unsigned subgroupcoherent : 1; + unsigned shadercallcoherent : 1; + unsigned nonprivate : 1; + unsigned volatil : 1; + unsigned isImage : 1; + + void clear() { + coherent = 0; + devicecoherent = 0; + queuefamilycoherent = 0; + workgroupcoherent = 0; + subgroupcoherent = 0; + shadercallcoherent = 0; + nonprivate = 0; + volatil = 0; + isImage = 0; + } + + CoherentFlags operator |=(const CoherentFlags &other) { + coherent |= other.coherent; + devicecoherent |= other.devicecoherent; + queuefamilycoherent |= other.queuefamilycoherent; + workgroupcoherent |= other.workgroupcoherent; + subgroupcoherent |= other.subgroupcoherent; + shadercallcoherent |= other.shadercallcoherent; + nonprivate |= other.nonprivate; + volatil |= other.volatil; + isImage |= other.isImage; + return *this; + } +#endif + }; + CoherentFlags coherentFlags; + }; + + // + // the SPIR-V builder maintains a single active chain that + // the following methods operate on + // + + // for external save and restore + AccessChain getAccessChain() { return accessChain; } + void setAccessChain(AccessChain newChain) { accessChain = newChain; } + + // clear accessChain + void clearAccessChain(); + + // set new base as an l-value base + void setAccessChainLValue(Id lValue) + { + assert(isPointer(lValue)); + accessChain.base = lValue; + } + + // set new base value as an r-value + void setAccessChainRValue(Id rValue) + { + accessChain.isRValue = true; + accessChain.base = rValue; + } + + // push offset onto the end of the chain + void accessChainPush(Id offset, AccessChain::CoherentFlags coherentFlags, unsigned int alignment) + { + accessChain.indexChain.push_back(offset); + accessChain.coherentFlags |= coherentFlags; + accessChain.alignment |= alignment; + } + + // push new swizzle onto the end of any existing swizzle, merging into a single swizzle + void accessChainPushSwizzle(std::vector& swizzle, Id preSwizzleBaseType, + AccessChain::CoherentFlags coherentFlags, unsigned int alignment); + + // push a dynamic component selection onto the access chain, only applicable with a + // non-trivial swizzle or no swizzle + void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, + unsigned int alignment) + { + if (accessChain.swizzle.size() != 1) { + accessChain.component = component; + if (accessChain.preSwizzleBaseType == NoType) + accessChain.preSwizzleBaseType = preSwizzleBaseType; + } + accessChain.coherentFlags |= coherentFlags; + accessChain.alignment |= alignment; + } + + // use accessChain and swizzle to store value + void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + + // use accessChain and swizzle to load an r-value + Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType, + spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, + unsigned int alignment = 0); + + // Return whether or not the access chain can be represented in SPIR-V + // as an l-value. + // E.g., a[3].yx cannot be, while a[3].y and a[3].y[x] can be. + bool isSpvLvalue() const { return accessChain.swizzle.size() <= 1; } + + // get the direct pointer for an l-value + Id accessChainGetLValue(); + + // Get the inferred SPIR-V type of the result of the current access chain, + // based on the type of the base and the chain of dereferences. + Id accessChainGetInferredType(); + + // Add capabilities, extensions, remove unneeded decorations, etc., + // based on the resulting SPIR-V. + void postProcess(); + + // Prune unreachable blocks in the CFG and remove unneeded decorations. + void postProcessCFG(); + +#ifndef GLSLANG_WEB + // Add capabilities, extensions based on instructions in the module. + void postProcessFeatures(); + // Hook to visit each instruction in a block in a function + void postProcess(Instruction&); + // Hook to visit each non-32-bit sized float/int operation in a block. + void postProcessType(const Instruction&, spv::Id typeId); +#endif + + void dump(std::vector&) const; + + void createBranch(Block* block); + void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock); + void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, + const std::vector& operands); + + // Sets to generate opcode for specialization constants. + void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; } + // Sets to generate opcode for non-specialization constants (normal mode). + void setToNormalCodeGenMode() { generatingOpCodeForSpecConst = false; } + // Check if the builder is generating code for spec constants. + bool isInSpecConstCodeGenMode() { return generatingOpCodeForSpecConst; } + + protected: + Id makeIntConstant(Id typeId, unsigned value, bool specConstant); + Id makeInt64Constant(Id typeId, unsigned long long value, bool specConstant); + Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value); + Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2); + Id findCompositeConstant(Op typeClass, Id typeId, const std::vector& comps); + Id findStructConstant(Id typeId, const std::vector& comps); + Id collapseAccessChain(); + void remapDynamicSwizzle(); + void transferAccessChainSwizzle(bool dynamic); + void simplifyAccessChainSwizzle(); + void createAndSetNoPredecessorBlock(const char*); + void createSelectionMerge(Block* mergeBlock, unsigned int control); + void dumpSourceInstructions(std::vector&) const; + void dumpSourceInstructions(const spv::Id fileId, const std::string& text, std::vector&) const; + void dumpInstructions(std::vector&, const std::vector >&) const; + void dumpModuleProcesses(std::vector&) const; + spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) + const; + + unsigned int spvVersion; // the version of SPIR-V to emit in the header + SourceLanguage source; + int sourceVersion; + spv::Id sourceFileStringId; + std::string sourceText; + int currentLine; + const char* currentFile; + bool emitOpLines; + std::set extensions; + std::vector sourceExtensions; + std::vector moduleProcesses; + AddressingModel addressModel; + MemoryModel memoryModel; + std::set capabilities; + int builderNumber; + Module module; + Block* buildPoint; + Id uniqueId; + Function* entryPointFunction; + bool generatingOpCodeForSpecConst; + AccessChain accessChain; + + // special blocks of instructions for output + std::vector > strings; + std::vector > imports; + std::vector > entryPoints; + std::vector > executionModes; + std::vector > names; + std::vector > decorations; + std::vector > constantsTypesGlobals; + std::vector > externals; + std::vector > functions; + + // not output, internally used for quick & dirty canonical (unique) creation + + // map type opcodes to constant inst. + std::unordered_map> groupedConstants; + // map struct-id to constant instructions + std::unordered_map> groupedStructConstants; + // map type opcodes to type instructions + std::unordered_map> groupedTypes; + + // stack of switches + std::stack switchMerges; + + // Our loop stack. + std::stack loops; + + // map from strings to their string ids + std::unordered_map stringIds; + + // map from include file name ids to their contents + std::map includeFiles; + + // The stream for outputting warnings and errors. + SpvBuildLogger* logger; +}; // end Builder class + +}; // end spv namespace + +#endif // SpvBuilder_H diff --git a/android/arm64-v8a/include/glslang/glslang/SPIRV/SpvTools.h b/android/arm64-v8a/include/glslang/glslang/SPIRV/SpvTools.h new file mode 100644 index 00000000..59c914da --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/SPIRV/SpvTools.h @@ -0,0 +1,82 @@ +// +// Copyright (C) 2014-2016 LunarG, Inc. +// Copyright (C) 2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Call into SPIRV-Tools to disassemble, validate, and optimize. +// + +#pragma once +#ifndef GLSLANG_SPV_TOOLS_H +#define GLSLANG_SPV_TOOLS_H + +#ifdef ENABLE_OPT +#include +#include +#endif + +#include "glslang/MachineIndependent/localintermediate.h" +#include "Logger.h" + +namespace glslang { + +struct SpvOptions { + SpvOptions() : generateDebugInfo(false), disableOptimizer(true), + optimizeSize(false), disassemble(false), validate(false) { } + bool generateDebugInfo; + bool disableOptimizer; + bool optimizeSize; + bool disassemble; + bool validate; +}; + +#ifdef ENABLE_OPT + +// Use the SPIRV-Tools disassembler to print SPIR-V. +void SpirvToolsDisassemble(std::ostream& out, const std::vector& spirv); + +// Apply the SPIRV-Tools validator to generated SPIR-V. +void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger*, bool prelegalization); + +// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of +// legalizing HLSL SPIR-V. +void SpirvToolsLegalize(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger*, const SpvOptions*); + +#endif + +} // end namespace glslang + +#endif // GLSLANG_SPV_TOOLS_H diff --git a/android/arm64-v8a/include/glslang/glslang/SPIRV/bitutils.h b/android/arm64-v8a/include/glslang/glslang/SPIRV/bitutils.h new file mode 100644 index 00000000..22e44cec --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/SPIRV/bitutils.h @@ -0,0 +1,81 @@ +// Copyright (c) 2015-2016 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef LIBSPIRV_UTIL_BITUTILS_H_ +#define LIBSPIRV_UTIL_BITUTILS_H_ + +#include +#include + +namespace spvutils { + +// Performs a bitwise copy of source to the destination type Dest. +template +Dest BitwiseCast(Src source) { + Dest dest; + static_assert(sizeof(source) == sizeof(dest), + "BitwiseCast: Source and destination must have the same size"); + std::memcpy(static_cast(&dest), &source, sizeof(dest)); + return dest; +} + +// SetBits returns an integer of type with bits set +// for position through , counting from the least +// significant bit. In particular when Num == 0, no positions are set to 1. +// A static assert will be triggered if First + Num > sizeof(T) * 8, that is, +// a bit that will not fit in the underlying type is set. +template +struct SetBits { + static_assert(First < sizeof(T) * 8, + "Tried to set a bit that is shifted too far."); + const static T get = (T(1) << First) | SetBits::get; +}; + +template +struct SetBits { + const static T get = T(0); +}; + +// This is all compile-time so we can put our tests right here. +static_assert(SetBits::get == uint32_t(0x00000000), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x00000001), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x80000000), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x00000006), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0xc0000000), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x7FFFFFFF), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0xFFFFFFFF), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0xFFFF0000), + "SetBits failed"); + +static_assert(SetBits::get == uint64_t(0x0000000000000001LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0x8000000000000000LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0xc000000000000000LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0x0000000080000000LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0x00000000FFFF0000LL), + "SetBits failed"); + +} // namespace spvutils + +#endif // LIBSPIRV_UTIL_BITUTILS_H_ diff --git a/android/arm64-v8a/include/glslang/glslang/SPIRV/disassemble.h b/android/arm64-v8a/include/glslang/glslang/SPIRV/disassemble.h new file mode 100644 index 00000000..b6a46357 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/SPIRV/disassemble.h @@ -0,0 +1,53 @@ +// +// Copyright (C) 2014-2015 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Disassembler for SPIR-V. +// + +#pragma once +#ifndef disassembler_H +#define disassembler_H + +#include +#include + +namespace spv { + + // disassemble with glslang custom disassembler + void Disassemble(std::ostream& out, const std::vector&); + +} // end namespace spv + +#endif // disassembler_H diff --git a/android/arm64-v8a/include/glslang/glslang/SPIRV/doc.h b/android/arm64-v8a/include/glslang/glslang/SPIRV/doc.h new file mode 100644 index 00000000..293256a2 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/SPIRV/doc.h @@ -0,0 +1,258 @@ +// +// Copyright (C) 2014-2015 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Parameterize the SPIR-V enumerants. +// + +#pragma once + +#include "spirv.hpp" + +#include + +namespace spv { + +// Fill in all the parameters +void Parameterize(); + +// Return the English names of all the enums. +const char* SourceString(int); +const char* AddressingString(int); +const char* MemoryString(int); +const char* ExecutionModelString(int); +const char* ExecutionModeString(int); +const char* StorageClassString(int); +const char* DecorationString(int); +const char* BuiltInString(int); +const char* DimensionString(int); +const char* SelectControlString(int); +const char* LoopControlString(int); +const char* FunctionControlString(int); +const char* SamplerAddressingModeString(int); +const char* SamplerFilterModeString(int); +const char* ImageFormatString(int); +const char* ImageChannelOrderString(int); +const char* ImageChannelTypeString(int); +const char* ImageChannelDataTypeString(int type); +const char* ImageOperandsString(int format); +const char* ImageOperands(int); +const char* FPFastMathString(int); +const char* FPRoundingModeString(int); +const char* LinkageTypeString(int); +const char* FuncParamAttrString(int); +const char* AccessQualifierString(int); +const char* MemorySemanticsString(int); +const char* MemoryAccessString(int); +const char* ExecutionScopeString(int); +const char* GroupOperationString(int); +const char* KernelEnqueueFlagsString(int); +const char* KernelProfilingInfoString(int); +const char* CapabilityString(int); +const char* OpcodeString(int); +const char* ScopeString(int mem); + +// For grouping opcodes into subsections +enum OpcodeClass { + OpClassMisc, + OpClassDebug, + OpClassAnnotate, + OpClassExtension, + OpClassMode, + OpClassType, + OpClassConstant, + OpClassMemory, + OpClassFunction, + OpClassImage, + OpClassConvert, + OpClassComposite, + OpClassArithmetic, + OpClassBit, + OpClassRelationalLogical, + OpClassDerivative, + OpClassFlowControl, + OpClassAtomic, + OpClassPrimitive, + OpClassBarrier, + OpClassGroup, + OpClassDeviceSideEnqueue, + OpClassPipe, + + OpClassCount, + OpClassMissing // all instructions start out as missing +}; + +// For parameterizing operands. +enum OperandClass { + OperandNone, + OperandId, + OperandVariableIds, + OperandOptionalLiteral, + OperandOptionalLiteralString, + OperandVariableLiterals, + OperandVariableIdLiteral, + OperandVariableLiteralId, + OperandLiteralNumber, + OperandLiteralString, + OperandSource, + OperandExecutionModel, + OperandAddressing, + OperandMemory, + OperandExecutionMode, + OperandStorage, + OperandDimensionality, + OperandSamplerAddressingMode, + OperandSamplerFilterMode, + OperandSamplerImageFormat, + OperandImageChannelOrder, + OperandImageChannelDataType, + OperandImageOperands, + OperandFPFastMath, + OperandFPRoundingMode, + OperandLinkageType, + OperandAccessQualifier, + OperandFuncParamAttr, + OperandDecoration, + OperandBuiltIn, + OperandSelect, + OperandLoop, + OperandFunction, + OperandMemorySemantics, + OperandMemoryAccess, + OperandScope, + OperandGroupOperation, + OperandKernelEnqueueFlags, + OperandKernelProfilingInfo, + OperandCapability, + + OperandOpcode, + + OperandCount +}; + +// Any specific enum can have a set of capabilities that allow it: +typedef std::vector EnumCaps; + +// Parameterize a set of operands with their OperandClass(es) and descriptions. +class OperandParameters { +public: + OperandParameters() { } + void push(OperandClass oc, const char* d, bool opt = false) + { + opClass.push_back(oc); + desc.push_back(d); + optional.push_back(opt); + } + void setOptional(); + OperandClass getClass(int op) const { return opClass[op]; } + const char* getDesc(int op) const { return desc[op]; } + bool isOptional(int op) const { return optional[op]; } + int getNum() const { return (int)opClass.size(); } + +protected: + std::vector opClass; + std::vector desc; + std::vector optional; +}; + +// Parameterize an enumerant +class EnumParameters { +public: + EnumParameters() : desc(0) { } + const char* desc; +}; + +// Parameterize a set of enumerants that form an enum +class EnumDefinition : public EnumParameters { +public: + EnumDefinition() : + ceiling(0), bitmask(false), getName(0), enumParams(0), operandParams(0) { } + void set(int ceil, const char* (*name)(int), EnumParameters* ep, bool mask = false) + { + ceiling = ceil; + getName = name; + bitmask = mask; + enumParams = ep; + } + void setOperands(OperandParameters* op) { operandParams = op; } + int ceiling; // ceiling of enumerants + bool bitmask; // true if these enumerants combine into a bitmask + const char* (*getName)(int); // a function that returns the name for each enumerant value (or shift) + EnumParameters* enumParams; // parameters for each individual enumerant + OperandParameters* operandParams; // sets of operands +}; + +// Parameterize an instruction's logical format, including its known set of operands, +// per OperandParameters above. +class InstructionParameters { +public: + InstructionParameters() : + opDesc("TBD"), + opClass(OpClassMissing), + typePresent(true), // most normal, only exceptions have to be spelled out + resultPresent(true) // most normal, only exceptions have to be spelled out + { } + + void setResultAndType(bool r, bool t) + { + resultPresent = r; + typePresent = t; + } + + bool hasResult() const { return resultPresent != 0; } + bool hasType() const { return typePresent != 0; } + + const char* opDesc; + OpcodeClass opClass; + OperandParameters operands; + +protected: + int typePresent : 1; + int resultPresent : 1; +}; + +// The set of objects that hold all the instruction/operand +// parameterization information. +extern InstructionParameters InstructionDesc[]; + +// These hold definitions of the enumerants used for operands +extern EnumDefinition OperandClassParams[]; + +const char* GetOperandDesc(OperandClass operand); +void PrintImmediateRow(int imm, const char* name, const EnumParameters* enumParams, bool caps, bool hex = false); +const char* AccessQualifierString(int attr); + +void PrintOperands(const OperandParameters& operands, int reservedOperands); + +} // end namespace spv diff --git a/android/arm64-v8a/include/glslang/glslang/SPIRV/hex_float.h b/android/arm64-v8a/include/glslang/glslang/SPIRV/hex_float.h new file mode 100644 index 00000000..8be8e9f7 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/SPIRV/hex_float.h @@ -0,0 +1,1078 @@ +// Copyright (c) 2015-2016 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef LIBSPIRV_UTIL_HEX_FLOAT_H_ +#define LIBSPIRV_UTIL_HEX_FLOAT_H_ + +#include +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) && _MSC_VER < 1800 +namespace std { +bool isnan(double f) +{ + return ::_isnan(f) != 0; +} +bool isinf(double f) +{ + return ::_finite(f) == 0; +} +} +#endif + +#include "bitutils.h" + +namespace spvutils { + +class Float16 { + public: + Float16(uint16_t v) : val(v) {} + Float16() {} + static bool isNan(const Float16& val) { + return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) != 0); + } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(const Float16& val) { + return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) == 0); + } + Float16(const Float16& other) { val = other.val; } + uint16_t get_value() const { return val; } + + // Returns the maximum normal value. + static Float16 max() { return Float16(0x7bff); } + // Returns the lowest normal value. + static Float16 lowest() { return Float16(0xfbff); } + + private: + uint16_t val; +}; + +// To specialize this type, you must override uint_type to define +// an unsigned integer that can fit your floating point type. +// You must also add a isNan function that returns true if +// a value is Nan. +template +struct FloatProxyTraits { + typedef void uint_type; +}; + +template <> +struct FloatProxyTraits { + typedef uint32_t uint_type; + static bool isNan(float f) { return std::isnan(f); } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(float f) { return std::isinf(f); } + // Returns the maximum normal value. + static float max() { return std::numeric_limits::max(); } + // Returns the lowest normal value. + static float lowest() { return std::numeric_limits::lowest(); } +}; + +template <> +struct FloatProxyTraits { + typedef uint64_t uint_type; + static bool isNan(double f) { return std::isnan(f); } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(double f) { return std::isinf(f); } + // Returns the maximum normal value. + static double max() { return std::numeric_limits::max(); } + // Returns the lowest normal value. + static double lowest() { return std::numeric_limits::lowest(); } +}; + +template <> +struct FloatProxyTraits { + typedef uint16_t uint_type; + static bool isNan(Float16 f) { return Float16::isNan(f); } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(Float16 f) { return Float16::isInfinity(f); } + // Returns the maximum normal value. + static Float16 max() { return Float16::max(); } + // Returns the lowest normal value. + static Float16 lowest() { return Float16::lowest(); } +}; + +// Since copying a floating point number (especially if it is NaN) +// does not guarantee that bits are preserved, this class lets us +// store the type and use it as a float when necessary. +template +class FloatProxy { + public: + typedef typename FloatProxyTraits::uint_type uint_type; + + // Since this is to act similar to the normal floats, + // do not initialize the data by default. + FloatProxy() {} + + // Intentionally non-explicit. This is a proxy type so + // implicit conversions allow us to use it more transparently. + FloatProxy(T val) { data_ = BitwiseCast(val); } + + // Intentionally non-explicit. This is a proxy type so + // implicit conversions allow us to use it more transparently. + FloatProxy(uint_type val) { data_ = val; } + + // This is helpful to have and is guaranteed not to stomp bits. + FloatProxy operator-() const { + return static_cast(data_ ^ + (uint_type(0x1) << (sizeof(T) * 8 - 1))); + } + + // Returns the data as a floating point value. + T getAsFloat() const { return BitwiseCast(data_); } + + // Returns the raw data. + uint_type data() const { return data_; } + + // Returns true if the value represents any type of NaN. + bool isNan() { return FloatProxyTraits::isNan(getAsFloat()); } + // Returns true if the value represents any type of infinity. + bool isInfinity() { return FloatProxyTraits::isInfinity(getAsFloat()); } + + // Returns the maximum normal value. + static FloatProxy max() { + return FloatProxy(FloatProxyTraits::max()); + } + // Returns the lowest normal value. + static FloatProxy lowest() { + return FloatProxy(FloatProxyTraits::lowest()); + } + + private: + uint_type data_; +}; + +template +bool operator==(const FloatProxy& first, const FloatProxy& second) { + return first.data() == second.data(); +} + +// Reads a FloatProxy value as a normal float from a stream. +template +std::istream& operator>>(std::istream& is, FloatProxy& value) { + T float_val; + is >> float_val; + value = FloatProxy(float_val); + return is; +} + +// This is an example traits. It is not meant to be used in practice, but will +// be the default for any non-specialized type. +template +struct HexFloatTraits { + // Integer type that can store this hex-float. + typedef void uint_type; + // Signed integer type that can store this hex-float. + typedef void int_type; + // The numerical type that this HexFloat represents. + typedef void underlying_type; + // The type needed to construct the underlying type. + typedef void native_type; + // The number of bits that are actually relevant in the uint_type. + // This allows us to deal with, for example, 24-bit values in a 32-bit + // integer. + static const uint32_t num_used_bits = 0; + // Number of bits that represent the exponent. + static const uint32_t num_exponent_bits = 0; + // Number of bits that represent the fractional part. + static const uint32_t num_fraction_bits = 0; + // The bias of the exponent. (How much we need to subtract from the stored + // value to get the correct value.) + static const uint32_t exponent_bias = 0; +}; + +// Traits for IEEE float. +// 1 sign bit, 8 exponent bits, 23 fractional bits. +template <> +struct HexFloatTraits> { + typedef uint32_t uint_type; + typedef int32_t int_type; + typedef FloatProxy underlying_type; + typedef float native_type; + static const uint_type num_used_bits = 32; + static const uint_type num_exponent_bits = 8; + static const uint_type num_fraction_bits = 23; + static const uint_type exponent_bias = 127; +}; + +// Traits for IEEE double. +// 1 sign bit, 11 exponent bits, 52 fractional bits. +template <> +struct HexFloatTraits> { + typedef uint64_t uint_type; + typedef int64_t int_type; + typedef FloatProxy underlying_type; + typedef double native_type; + static const uint_type num_used_bits = 64; + static const uint_type num_exponent_bits = 11; + static const uint_type num_fraction_bits = 52; + static const uint_type exponent_bias = 1023; +}; + +// Traits for IEEE half. +// 1 sign bit, 5 exponent bits, 10 fractional bits. +template <> +struct HexFloatTraits> { + typedef uint16_t uint_type; + typedef int16_t int_type; + typedef uint16_t underlying_type; + typedef uint16_t native_type; + static const uint_type num_used_bits = 16; + static const uint_type num_exponent_bits = 5; + static const uint_type num_fraction_bits = 10; + static const uint_type exponent_bias = 15; +}; + +enum round_direction { + kRoundToZero, + kRoundToNearestEven, + kRoundToPositiveInfinity, + kRoundToNegativeInfinity +}; + +// Template class that houses a floating pointer number. +// It exposes a number of constants based on the provided traits to +// assist in interpreting the bits of the value. +template > +class HexFloat { + public: + typedef typename Traits::uint_type uint_type; + typedef typename Traits::int_type int_type; + typedef typename Traits::underlying_type underlying_type; + typedef typename Traits::native_type native_type; + + explicit HexFloat(T f) : value_(f) {} + + T value() const { return value_; } + void set_value(T f) { value_ = f; } + + // These are all written like this because it is convenient to have + // compile-time constants for all of these values. + + // Pass-through values to save typing. + static const uint32_t num_used_bits = Traits::num_used_bits; + static const uint32_t exponent_bias = Traits::exponent_bias; + static const uint32_t num_exponent_bits = Traits::num_exponent_bits; + static const uint32_t num_fraction_bits = Traits::num_fraction_bits; + + // Number of bits to shift left to set the highest relevant bit. + static const uint32_t top_bit_left_shift = num_used_bits - 1; + // How many nibbles (hex characters) the fractional part takes up. + static const uint32_t fraction_nibbles = (num_fraction_bits + 3) / 4; + // If the fractional part does not fit evenly into a hex character (4-bits) + // then we have to left-shift to get rid of leading 0s. This is the amount + // we have to shift (might be 0). + static const uint32_t num_overflow_bits = + fraction_nibbles * 4 - num_fraction_bits; + + // The representation of the fraction, not the actual bits. This + // includes the leading bit that is usually implicit. + static const uint_type fraction_represent_mask = + spvutils::SetBits::get; + + // The topmost bit in the nibble-aligned fraction. + static const uint_type fraction_top_bit = + uint_type(1) << (num_fraction_bits + num_overflow_bits - 1); + + // The least significant bit in the exponent, which is also the bit + // immediately to the left of the significand. + static const uint_type first_exponent_bit = uint_type(1) + << (num_fraction_bits); + + // The mask for the encoded fraction. It does not include the + // implicit bit. + static const uint_type fraction_encode_mask = + spvutils::SetBits::get; + + // The bit that is used as a sign. + static const uint_type sign_mask = uint_type(1) << top_bit_left_shift; + + // The bits that represent the exponent. + static const uint_type exponent_mask = + spvutils::SetBits::get; + + // How far left the exponent is shifted. + static const uint32_t exponent_left_shift = num_fraction_bits; + + // How far from the right edge the fraction is shifted. + static const uint32_t fraction_right_shift = + static_cast(sizeof(uint_type) * 8) - num_fraction_bits; + + // The maximum representable unbiased exponent. + static const int_type max_exponent = + (exponent_mask >> num_fraction_bits) - exponent_bias; + // The minimum representable exponent for normalized numbers. + static const int_type min_exponent = -static_cast(exponent_bias); + + // Returns the bits associated with the value. + uint_type getBits() const { return spvutils::BitwiseCast(value_); } + + // Returns the bits associated with the value, without the leading sign bit. + uint_type getUnsignedBits() const { + return static_cast(spvutils::BitwiseCast(value_) & + ~sign_mask); + } + + // Returns the bits associated with the exponent, shifted to start at the + // lsb of the type. + const uint_type getExponentBits() const { + return static_cast((getBits() & exponent_mask) >> + num_fraction_bits); + } + + // Returns the exponent in unbiased form. This is the exponent in the + // human-friendly form. + const int_type getUnbiasedExponent() const { + return static_cast(getExponentBits() - exponent_bias); + } + + // Returns just the significand bits from the value. + const uint_type getSignificandBits() const { + return getBits() & fraction_encode_mask; + } + + // If the number was normalized, returns the unbiased exponent. + // If the number was denormal, normalize the exponent first. + const int_type getUnbiasedNormalizedExponent() const { + if ((getBits() & ~sign_mask) == 0) { // special case if everything is 0 + return 0; + } + int_type exp = getUnbiasedExponent(); + if (exp == min_exponent) { // We are in denorm land. + uint_type significand_bits = getSignificandBits(); + while ((significand_bits & (first_exponent_bit >> 1)) == 0) { + significand_bits = static_cast(significand_bits << 1); + exp = static_cast(exp - 1); + } + significand_bits &= fraction_encode_mask; + } + return exp; + } + + // Returns the signficand after it has been normalized. + const uint_type getNormalizedSignificand() const { + int_type unbiased_exponent = getUnbiasedNormalizedExponent(); + uint_type significand = getSignificandBits(); + for (int_type i = unbiased_exponent; i <= min_exponent; ++i) { + significand = static_cast(significand << 1); + } + significand &= fraction_encode_mask; + return significand; + } + + // Returns true if this number represents a negative value. + bool isNegative() const { return (getBits() & sign_mask) != 0; } + + // Sets this HexFloat from the individual components. + // Note this assumes EVERY significand is normalized, and has an implicit + // leading one. This means that the only way that this method will set 0, + // is if you set a number so denormalized that it underflows. + // Do not use this method with raw bits extracted from a subnormal number, + // since subnormals do not have an implicit leading 1 in the significand. + // The significand is also expected to be in the + // lowest-most num_fraction_bits of the uint_type. + // The exponent is expected to be unbiased, meaning an exponent of + // 0 actually means 0. + // If underflow_round_up is set, then on underflow, if a number is non-0 + // and would underflow, we round up to the smallest denorm. + void setFromSignUnbiasedExponentAndNormalizedSignificand( + bool negative, int_type exponent, uint_type significand, + bool round_denorm_up) { + bool significand_is_zero = significand == 0; + + if (exponent <= min_exponent) { + // If this was denormalized, then we have to shift the bit on, meaning + // the significand is not zero. + significand_is_zero = false; + significand |= first_exponent_bit; + significand = static_cast(significand >> 1); + } + + while (exponent < min_exponent) { + significand = static_cast(significand >> 1); + ++exponent; + } + + if (exponent == min_exponent) { + if (significand == 0 && !significand_is_zero && round_denorm_up) { + significand = static_cast(0x1); + } + } + + uint_type new_value = 0; + if (negative) { + new_value = static_cast(new_value | sign_mask); + } + exponent = static_cast(exponent + exponent_bias); + assert(exponent >= 0); + + // put it all together + exponent = static_cast((exponent << exponent_left_shift) & + exponent_mask); + significand = static_cast(significand & fraction_encode_mask); + new_value = static_cast(new_value | (exponent | significand)); + value_ = BitwiseCast(new_value); + } + + // Increments the significand of this number by the given amount. + // If this would spill the significand into the implicit bit, + // carry is set to true and the significand is shifted to fit into + // the correct location, otherwise carry is set to false. + // All significands and to_increment are assumed to be within the bounds + // for a valid significand. + static uint_type incrementSignificand(uint_type significand, + uint_type to_increment, bool* carry) { + significand = static_cast(significand + to_increment); + *carry = false; + if (significand & first_exponent_bit) { + *carry = true; + // The implicit 1-bit will have carried, so we should zero-out the + // top bit and shift back. + significand = static_cast(significand & ~first_exponent_bit); + significand = static_cast(significand >> 1); + } + return significand; + } + + // These exist because MSVC throws warnings on negative right-shifts + // even if they are not going to be executed. Eg: + // constant_number < 0? 0: constant_number + // These convert the negative left-shifts into right shifts. + + template + uint_type negatable_left_shift(int_type N, uint_type val) + { + if(N >= 0) + return val << N; + + return val >> -N; + } + + template + uint_type negatable_right_shift(int_type N, uint_type val) + { + if(N >= 0) + return val >> N; + + return val << -N; + } + + // Returns the significand, rounded to fit in a significand in + // other_T. This is shifted so that the most significant + // bit of the rounded number lines up with the most significant bit + // of the returned significand. + template + typename other_T::uint_type getRoundedNormalizedSignificand( + round_direction dir, bool* carry_bit) { + typedef typename other_T::uint_type other_uint_type; + static const int_type num_throwaway_bits = + static_cast(num_fraction_bits) - + static_cast(other_T::num_fraction_bits); + + static const uint_type last_significant_bit = + (num_throwaway_bits < 0) + ? 0 + : negatable_left_shift(num_throwaway_bits, 1u); + static const uint_type first_rounded_bit = + (num_throwaway_bits < 1) + ? 0 + : negatable_left_shift(num_throwaway_bits - 1, 1u); + + static const uint_type throwaway_mask_bits = + num_throwaway_bits > 0 ? num_throwaway_bits : 0; + static const uint_type throwaway_mask = + spvutils::SetBits::get; + + *carry_bit = false; + other_uint_type out_val = 0; + uint_type significand = getNormalizedSignificand(); + // If we are up-casting, then we just have to shift to the right location. + if (num_throwaway_bits <= 0) { + out_val = static_cast(significand); + uint_type shift_amount = static_cast(-num_throwaway_bits); + out_val = static_cast(out_val << shift_amount); + return out_val; + } + + // If every non-representable bit is 0, then we don't have any casting to + // do. + if ((significand & throwaway_mask) == 0) { + return static_cast( + negatable_right_shift(num_throwaway_bits, significand)); + } + + bool round_away_from_zero = false; + // We actually have to narrow the significand here, so we have to follow the + // rounding rules. + switch (dir) { + case kRoundToZero: + break; + case kRoundToPositiveInfinity: + round_away_from_zero = !isNegative(); + break; + case kRoundToNegativeInfinity: + round_away_from_zero = isNegative(); + break; + case kRoundToNearestEven: + // Have to round down, round bit is 0 + if ((first_rounded_bit & significand) == 0) { + break; + } + if (((significand & throwaway_mask) & ~first_rounded_bit) != 0) { + // If any subsequent bit of the rounded portion is non-0 then we round + // up. + round_away_from_zero = true; + break; + } + // We are exactly half-way between 2 numbers, pick even. + if ((significand & last_significant_bit) != 0) { + // 1 for our last bit, round up. + round_away_from_zero = true; + break; + } + break; + } + + if (round_away_from_zero) { + return static_cast( + negatable_right_shift(num_throwaway_bits, incrementSignificand( + significand, last_significant_bit, carry_bit))); + } else { + return static_cast( + negatable_right_shift(num_throwaway_bits, significand)); + } + } + + // Casts this value to another HexFloat. If the cast is widening, + // then round_dir is ignored. If the cast is narrowing, then + // the result is rounded in the direction specified. + // This number will retain Nan and Inf values. + // It will also saturate to Inf if the number overflows, and + // underflow to (0 or min depending on rounding) if the number underflows. + template + void castTo(other_T& other, round_direction round_dir) { + other = other_T(static_cast(0)); + bool negate = isNegative(); + if (getUnsignedBits() == 0) { + if (negate) { + other.set_value(-other.value()); + } + return; + } + uint_type significand = getSignificandBits(); + bool carried = false; + typename other_T::uint_type rounded_significand = + getRoundedNormalizedSignificand(round_dir, &carried); + + int_type exponent = getUnbiasedExponent(); + if (exponent == min_exponent) { + // If we are denormal, normalize the exponent, so that we can encode + // easily. + exponent = static_cast(exponent + 1); + for (uint_type check_bit = first_exponent_bit >> 1; check_bit != 0; + check_bit = static_cast(check_bit >> 1)) { + exponent = static_cast(exponent - 1); + if (check_bit & significand) break; + } + } + + bool is_nan = + (getBits() & exponent_mask) == exponent_mask && significand != 0; + bool is_inf = + !is_nan && + ((exponent + carried) > static_cast(other_T::exponent_bias) || + (significand == 0 && (getBits() & exponent_mask) == exponent_mask)); + + // If we are Nan or Inf we should pass that through. + if (is_inf) { + other.set_value(BitwiseCast( + static_cast( + (negate ? other_T::sign_mask : 0) | other_T::exponent_mask))); + return; + } + if (is_nan) { + typename other_T::uint_type shifted_significand; + shifted_significand = static_cast( + negatable_left_shift( + static_cast(other_T::num_fraction_bits) - + static_cast(num_fraction_bits), significand)); + + // We are some sort of Nan. We try to keep the bit-pattern of the Nan + // as close as possible. If we had to shift off bits so we are 0, then we + // just set the last bit. + other.set_value(BitwiseCast( + static_cast( + (negate ? other_T::sign_mask : 0) | other_T::exponent_mask | + (shifted_significand == 0 ? 0x1 : shifted_significand)))); + return; + } + + bool round_underflow_up = + isNegative() ? round_dir == kRoundToNegativeInfinity + : round_dir == kRoundToPositiveInfinity; + typedef typename other_T::int_type other_int_type; + // setFromSignUnbiasedExponentAndNormalizedSignificand will + // zero out any underflowing value (but retain the sign). + other.setFromSignUnbiasedExponentAndNormalizedSignificand( + negate, static_cast(exponent), rounded_significand, + round_underflow_up); + return; + } + + private: + T value_; + + static_assert(num_used_bits == + Traits::num_exponent_bits + Traits::num_fraction_bits + 1, + "The number of bits do not fit"); + static_assert(sizeof(T) == sizeof(uint_type), "The type sizes do not match"); +}; + +// Returns 4 bits represented by the hex character. +inline uint8_t get_nibble_from_character(int character) { + const char* dec = "0123456789"; + const char* lower = "abcdef"; + const char* upper = "ABCDEF"; + const char* p = nullptr; + if ((p = strchr(dec, character))) { + return static_cast(p - dec); + } else if ((p = strchr(lower, character))) { + return static_cast(p - lower + 0xa); + } else if ((p = strchr(upper, character))) { + return static_cast(p - upper + 0xa); + } + + assert(false && "This was called with a non-hex character"); + return 0; +} + +// Outputs the given HexFloat to the stream. +template +std::ostream& operator<<(std::ostream& os, const HexFloat& value) { + typedef HexFloat HF; + typedef typename HF::uint_type uint_type; + typedef typename HF::int_type int_type; + + static_assert(HF::num_used_bits != 0, + "num_used_bits must be non-zero for a valid float"); + static_assert(HF::num_exponent_bits != 0, + "num_exponent_bits must be non-zero for a valid float"); + static_assert(HF::num_fraction_bits != 0, + "num_fractin_bits must be non-zero for a valid float"); + + const uint_type bits = spvutils::BitwiseCast(value.value()); + const char* const sign = (bits & HF::sign_mask) ? "-" : ""; + const uint_type exponent = static_cast( + (bits & HF::exponent_mask) >> HF::num_fraction_bits); + + uint_type fraction = static_cast((bits & HF::fraction_encode_mask) + << HF::num_overflow_bits); + + const bool is_zero = exponent == 0 && fraction == 0; + const bool is_denorm = exponent == 0 && !is_zero; + + // exponent contains the biased exponent we have to convert it back into + // the normal range. + int_type int_exponent = static_cast(exponent - HF::exponent_bias); + // If the number is all zeros, then we actually have to NOT shift the + // exponent. + int_exponent = is_zero ? 0 : int_exponent; + + // If we are denorm, then start shifting, and decreasing the exponent until + // our leading bit is 1. + + if (is_denorm) { + while ((fraction & HF::fraction_top_bit) == 0) { + fraction = static_cast(fraction << 1); + int_exponent = static_cast(int_exponent - 1); + } + // Since this is denormalized, we have to consume the leading 1 since it + // will end up being implicit. + fraction = static_cast(fraction << 1); // eat the leading 1 + fraction &= HF::fraction_represent_mask; + } + + uint_type fraction_nibbles = HF::fraction_nibbles; + // We do not have to display any trailing 0s, since this represents the + // fractional part. + while (fraction_nibbles > 0 && (fraction & 0xF) == 0) { + // Shift off any trailing values; + fraction = static_cast(fraction >> 4); + --fraction_nibbles; + } + + const auto saved_flags = os.flags(); + const auto saved_fill = os.fill(); + + os << sign << "0x" << (is_zero ? '0' : '1'); + if (fraction_nibbles) { + // Make sure to keep the leading 0s in place, since this is the fractional + // part. + os << "." << std::setw(static_cast(fraction_nibbles)) + << std::setfill('0') << std::hex << fraction; + } + os << "p" << std::dec << (int_exponent >= 0 ? "+" : "") << int_exponent; + + os.flags(saved_flags); + os.fill(saved_fill); + + return os; +} + +// Returns true if negate_value is true and the next character on the +// input stream is a plus or minus sign. In that case we also set the fail bit +// on the stream and set the value to the zero value for its type. +template +inline bool RejectParseDueToLeadingSign(std::istream& is, bool negate_value, + HexFloat& value) { + if (negate_value) { + auto next_char = is.peek(); + if (next_char == '-' || next_char == '+') { + // Fail the parse. Emulate standard behaviour by setting the value to + // the zero value, and set the fail bit on the stream. + value = HexFloat(typename HexFloat::uint_type(0)); + is.setstate(std::ios_base::failbit); + return true; + } + } + return false; +} + +// Parses a floating point number from the given stream and stores it into the +// value parameter. +// If negate_value is true then the number may not have a leading minus or +// plus, and if it successfully parses, then the number is negated before +// being stored into the value parameter. +// If the value cannot be correctly parsed or overflows the target floating +// point type, then set the fail bit on the stream. +// TODO(dneto): Promise C++11 standard behavior in how the value is set in +// the error case, but only after all target platforms implement it correctly. +// In particular, the Microsoft C++ runtime appears to be out of spec. +template +inline std::istream& ParseNormalFloat(std::istream& is, bool negate_value, + HexFloat& value) { + if (RejectParseDueToLeadingSign(is, negate_value, value)) { + return is; + } + T val; + is >> val; + if (negate_value) { + val = -val; + } + value.set_value(val); + // In the failure case, map -0.0 to 0.0. + if (is.fail() && value.getUnsignedBits() == 0u) { + value = HexFloat(typename HexFloat::uint_type(0)); + } + if (val.isInfinity()) { + // Fail the parse. Emulate standard behaviour by setting the value to + // the closest normal value, and set the fail bit on the stream. + value.set_value((value.isNegative() || negate_value) ? T::lowest() + : T::max()); + is.setstate(std::ios_base::failbit); + } + return is; +} + +// Specialization of ParseNormalFloat for FloatProxy values. +// This will parse the float as it were a 32-bit floating point number, +// and then round it down to fit into a Float16 value. +// The number is rounded towards zero. +// If negate_value is true then the number may not have a leading minus or +// plus, and if it successfully parses, then the number is negated before +// being stored into the value parameter. +// If the value cannot be correctly parsed or overflows the target floating +// point type, then set the fail bit on the stream. +// TODO(dneto): Promise C++11 standard behavior in how the value is set in +// the error case, but only after all target platforms implement it correctly. +// In particular, the Microsoft C++ runtime appears to be out of spec. +template <> +inline std::istream& +ParseNormalFloat, HexFloatTraits>>( + std::istream& is, bool negate_value, + HexFloat, HexFloatTraits>>& value) { + // First parse as a 32-bit float. + HexFloat> float_val(0.0f); + ParseNormalFloat(is, negate_value, float_val); + + // Then convert to 16-bit float, saturating at infinities, and + // rounding toward zero. + float_val.castTo(value, kRoundToZero); + + // Overflow on 16-bit behaves the same as for 32- and 64-bit: set the + // fail bit and set the lowest or highest value. + if (Float16::isInfinity(value.value().getAsFloat())) { + value.set_value(value.isNegative() ? Float16::lowest() : Float16::max()); + is.setstate(std::ios_base::failbit); + } + return is; +} + +// Reads a HexFloat from the given stream. +// If the float is not encoded as a hex-float then it will be parsed +// as a regular float. +// This may fail if your stream does not support at least one unget. +// Nan values can be encoded with "0x1.p+exponent_bias". +// This would normally overflow a float and round to +// infinity but this special pattern is the exact representation for a NaN, +// and therefore is actually encoded as the correct NaN. To encode inf, +// either 0x0p+exponent_bias can be specified or any exponent greater than +// exponent_bias. +// Examples using IEEE 32-bit float encoding. +// 0x1.0p+128 (+inf) +// -0x1.0p-128 (-inf) +// +// 0x1.1p+128 (+Nan) +// -0x1.1p+128 (-Nan) +// +// 0x1p+129 (+inf) +// -0x1p+129 (-inf) +template +std::istream& operator>>(std::istream& is, HexFloat& value) { + using HF = HexFloat; + using uint_type = typename HF::uint_type; + using int_type = typename HF::int_type; + + value.set_value(static_cast(0.f)); + + if (is.flags() & std::ios::skipws) { + // If the user wants to skip whitespace , then we should obey that. + while (std::isspace(is.peek())) { + is.get(); + } + } + + auto next_char = is.peek(); + bool negate_value = false; + + if (next_char != '-' && next_char != '0') { + return ParseNormalFloat(is, negate_value, value); + } + + if (next_char == '-') { + negate_value = true; + is.get(); + next_char = is.peek(); + } + + if (next_char == '0') { + is.get(); // We may have to unget this. + auto maybe_hex_start = is.peek(); + if (maybe_hex_start != 'x' && maybe_hex_start != 'X') { + is.unget(); + return ParseNormalFloat(is, negate_value, value); + } else { + is.get(); // Throw away the 'x'; + } + } else { + return ParseNormalFloat(is, negate_value, value); + } + + // This "looks" like a hex-float so treat it as one. + bool seen_p = false; + bool seen_dot = false; + uint_type fraction_index = 0; + + uint_type fraction = 0; + int_type exponent = HF::exponent_bias; + + // Strip off leading zeros so we don't have to special-case them later. + while ((next_char = is.peek()) == '0') { + is.get(); + } + + bool is_denorm = + true; // Assume denorm "representation" until we hear otherwise. + // NB: This does not mean the value is actually denorm, + // it just means that it was written 0. + bool bits_written = false; // Stays false until we write a bit. + while (!seen_p && !seen_dot) { + // Handle characters that are left of the fractional part. + if (next_char == '.') { + seen_dot = true; + } else if (next_char == 'p') { + seen_p = true; + } else if (::isxdigit(next_char)) { + // We know this is not denormalized since we have stripped all leading + // zeroes and we are not a ".". + is_denorm = false; + int number = get_nibble_from_character(next_char); + for (int i = 0; i < 4; ++i, number <<= 1) { + uint_type write_bit = (number & 0x8) ? 0x1 : 0x0; + if (bits_written) { + // If we are here the bits represented belong in the fractional + // part of the float, and we have to adjust the exponent accordingly. + fraction = static_cast( + fraction | + static_cast( + write_bit << (HF::top_bit_left_shift - fraction_index++))); + exponent = static_cast(exponent + 1); + } + bits_written |= write_bit != 0; + } + } else { + // We have not found our exponent yet, so we have to fail. + is.setstate(std::ios::failbit); + return is; + } + is.get(); + next_char = is.peek(); + } + bits_written = false; + while (seen_dot && !seen_p) { + // Handle only fractional parts now. + if (next_char == 'p') { + seen_p = true; + } else if (::isxdigit(next_char)) { + int number = get_nibble_from_character(next_char); + for (int i = 0; i < 4; ++i, number <<= 1) { + uint_type write_bit = (number & 0x8) ? 0x01 : 0x00; + bits_written |= write_bit != 0; + if (is_denorm && !bits_written) { + // Handle modifying the exponent here this way we can handle + // an arbitrary number of hex values without overflowing our + // integer. + exponent = static_cast(exponent - 1); + } else { + fraction = static_cast( + fraction | + static_cast( + write_bit << (HF::top_bit_left_shift - fraction_index++))); + } + } + } else { + // We still have not found our 'p' exponent yet, so this is not a valid + // hex-float. + is.setstate(std::ios::failbit); + return is; + } + is.get(); + next_char = is.peek(); + } + + bool seen_sign = false; + int8_t exponent_sign = 1; + int_type written_exponent = 0; + while (true) { + if ((next_char == '-' || next_char == '+')) { + if (seen_sign) { + is.setstate(std::ios::failbit); + return is; + } + seen_sign = true; + exponent_sign = (next_char == '-') ? -1 : 1; + } else if (::isdigit(next_char)) { + // Hex-floats express their exponent as decimal. + written_exponent = static_cast(written_exponent * 10); + written_exponent = + static_cast(written_exponent + (next_char - '0')); + } else { + break; + } + is.get(); + next_char = is.peek(); + } + + written_exponent = static_cast(written_exponent * exponent_sign); + exponent = static_cast(exponent + written_exponent); + + bool is_zero = is_denorm && (fraction == 0); + if (is_denorm && !is_zero) { + fraction = static_cast(fraction << 1); + exponent = static_cast(exponent - 1); + } else if (is_zero) { + exponent = 0; + } + + if (exponent <= 0 && !is_zero) { + fraction = static_cast(fraction >> 1); + fraction |= static_cast(1) << HF::top_bit_left_shift; + } + + fraction = (fraction >> HF::fraction_right_shift) & HF::fraction_encode_mask; + + const int_type max_exponent = + SetBits::get; + + // Handle actual denorm numbers + while (exponent < 0 && !is_zero) { + fraction = static_cast(fraction >> 1); + exponent = static_cast(exponent + 1); + + fraction &= HF::fraction_encode_mask; + if (fraction == 0) { + // We have underflowed our fraction. We should clamp to zero. + is_zero = true; + exponent = 0; + } + } + + // We have overflowed so we should be inf/-inf. + if (exponent > max_exponent) { + exponent = max_exponent; + fraction = 0; + } + + uint_type output_bits = static_cast( + static_cast(negate_value ? 1 : 0) << HF::top_bit_left_shift); + output_bits |= fraction; + + uint_type shifted_exponent = static_cast( + static_cast(exponent << HF::exponent_left_shift) & + HF::exponent_mask); + output_bits |= shifted_exponent; + + T output_float = spvutils::BitwiseCast(output_bits); + value.set_value(output_float); + + return is; +} + +// Writes a FloatProxy value to a stream. +// Zero and normal numbers are printed in the usual notation, but with +// enough digits to fully reproduce the value. Other values (subnormal, +// NaN, and infinity) are printed as a hex float. +template +std::ostream& operator<<(std::ostream& os, const FloatProxy& value) { + auto float_val = value.getAsFloat(); + switch (std::fpclassify(float_val)) { + case FP_ZERO: + case FP_NORMAL: { + auto saved_precision = os.precision(); + os.precision(std::numeric_limits::digits10); + os << float_val; + os.precision(saved_precision); + } break; + default: + os << HexFloat>(value); + break; + } + return os; +} + +template <> +inline std::ostream& operator<<(std::ostream& os, + const FloatProxy& value) { + os << HexFloat>(value); + return os; +} +} + +#endif // LIBSPIRV_UTIL_HEX_FLOAT_H_ diff --git a/android/arm64-v8a/include/glslang/glslang/SPIRV/spirv.hpp b/android/arm64-v8a/include/glslang/glslang/SPIRV/spirv.hpp new file mode 100644 index 00000000..dae36cf2 --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/SPIRV/spirv.hpp @@ -0,0 +1,2114 @@ +// Copyright (c) 2014-2020 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and/or associated documentation files (the "Materials"), +// to deal in the Materials without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Materials, and to permit persons to whom the +// Materials are furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +// IN THE MATERIALS. + +// This header is automatically generated by the same tool that creates +// the Binary Section of the SPIR-V specification. + +// Enumeration tokens for SPIR-V, in various styles: +// C, C++, C++11, JSON, Lua, Python, C#, D +// +// - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL +// - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL +// - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL +// - Lua will use tables, e.g.: spv.SourceLanguage.GLSL +// - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] +// - C# will use enum classes in the Specification class located in the "Spv" namespace, +// e.g.: Spv.Specification.SourceLanguage.GLSL +// - D will have tokens under the "spv" module, e.g: spv.SourceLanguage.GLSL +// +// Some tokens act like mask values, which can be OR'd together, +// while others are mutually exclusive. The mask-like ones have +// "Mask" in their name, and a parallel enum that has the shift +// amount (1 << x) for each corresponding enumerant. + +#ifndef spirv_HPP +#define spirv_HPP + +namespace spv { + +typedef unsigned int Id; + +#define SPV_VERSION 0x10500 +#define SPV_REVISION 3 + +static const unsigned int MagicNumber = 0x07230203; +static const unsigned int Version = 0x00010500; +static const unsigned int Revision = 3; +static const unsigned int OpCodeMask = 0xffff; +static const unsigned int WordCountShift = 16; + +enum SourceLanguage { + SourceLanguageUnknown = 0, + SourceLanguageESSL = 1, + SourceLanguageGLSL = 2, + SourceLanguageOpenCL_C = 3, + SourceLanguageOpenCL_CPP = 4, + SourceLanguageHLSL = 5, + SourceLanguageMax = 0x7fffffff, +}; + +enum ExecutionModel { + ExecutionModelVertex = 0, + ExecutionModelTessellationControl = 1, + ExecutionModelTessellationEvaluation = 2, + ExecutionModelGeometry = 3, + ExecutionModelFragment = 4, + ExecutionModelGLCompute = 5, + ExecutionModelKernel = 6, + ExecutionModelTaskNV = 5267, + ExecutionModelMeshNV = 5268, + ExecutionModelRayGenerationKHR = 5313, + ExecutionModelRayGenerationNV = 5313, + ExecutionModelIntersectionKHR = 5314, + ExecutionModelIntersectionNV = 5314, + ExecutionModelAnyHitKHR = 5315, + ExecutionModelAnyHitNV = 5315, + ExecutionModelClosestHitKHR = 5316, + ExecutionModelClosestHitNV = 5316, + ExecutionModelMissKHR = 5317, + ExecutionModelMissNV = 5317, + ExecutionModelCallableKHR = 5318, + ExecutionModelCallableNV = 5318, + ExecutionModelMax = 0x7fffffff, +}; + +enum AddressingModel { + AddressingModelLogical = 0, + AddressingModelPhysical32 = 1, + AddressingModelPhysical64 = 2, + AddressingModelPhysicalStorageBuffer64 = 5348, + AddressingModelPhysicalStorageBuffer64EXT = 5348, + AddressingModelMax = 0x7fffffff, +}; + +enum MemoryModel { + MemoryModelSimple = 0, + MemoryModelGLSL450 = 1, + MemoryModelOpenCL = 2, + MemoryModelVulkan = 3, + MemoryModelVulkanKHR = 3, + MemoryModelMax = 0x7fffffff, +}; + +enum ExecutionMode { + ExecutionModeInvocations = 0, + ExecutionModeSpacingEqual = 1, + ExecutionModeSpacingFractionalEven = 2, + ExecutionModeSpacingFractionalOdd = 3, + ExecutionModeVertexOrderCw = 4, + ExecutionModeVertexOrderCcw = 5, + ExecutionModePixelCenterInteger = 6, + ExecutionModeOriginUpperLeft = 7, + ExecutionModeOriginLowerLeft = 8, + ExecutionModeEarlyFragmentTests = 9, + ExecutionModePointMode = 10, + ExecutionModeXfb = 11, + ExecutionModeDepthReplacing = 12, + ExecutionModeDepthGreater = 14, + ExecutionModeDepthLess = 15, + ExecutionModeDepthUnchanged = 16, + ExecutionModeLocalSize = 17, + ExecutionModeLocalSizeHint = 18, + ExecutionModeInputPoints = 19, + ExecutionModeInputLines = 20, + ExecutionModeInputLinesAdjacency = 21, + ExecutionModeTriangles = 22, + ExecutionModeInputTrianglesAdjacency = 23, + ExecutionModeQuads = 24, + ExecutionModeIsolines = 25, + ExecutionModeOutputVertices = 26, + ExecutionModeOutputPoints = 27, + ExecutionModeOutputLineStrip = 28, + ExecutionModeOutputTriangleStrip = 29, + ExecutionModeVecTypeHint = 30, + ExecutionModeContractionOff = 31, + ExecutionModeInitializer = 33, + ExecutionModeFinalizer = 34, + ExecutionModeSubgroupSize = 35, + ExecutionModeSubgroupsPerWorkgroup = 36, + ExecutionModeSubgroupsPerWorkgroupId = 37, + ExecutionModeLocalSizeId = 38, + ExecutionModeLocalSizeHintId = 39, + ExecutionModePostDepthCoverage = 4446, + ExecutionModeDenormPreserve = 4459, + ExecutionModeDenormFlushToZero = 4460, + ExecutionModeSignedZeroInfNanPreserve = 4461, + ExecutionModeRoundingModeRTE = 4462, + ExecutionModeRoundingModeRTZ = 4463, + ExecutionModeStencilRefReplacingEXT = 5027, + ExecutionModeOutputLinesNV = 5269, + ExecutionModeOutputPrimitivesNV = 5270, + ExecutionModeDerivativeGroupQuadsNV = 5289, + ExecutionModeDerivativeGroupLinearNV = 5290, + ExecutionModeOutputTrianglesNV = 5298, + ExecutionModePixelInterlockOrderedEXT = 5366, + ExecutionModePixelInterlockUnorderedEXT = 5367, + ExecutionModeSampleInterlockOrderedEXT = 5368, + ExecutionModeSampleInterlockUnorderedEXT = 5369, + ExecutionModeShadingRateInterlockOrderedEXT = 5370, + ExecutionModeShadingRateInterlockUnorderedEXT = 5371, + ExecutionModeMax = 0x7fffffff, +}; + +enum StorageClass { + StorageClassUniformConstant = 0, + StorageClassInput = 1, + StorageClassUniform = 2, + StorageClassOutput = 3, + StorageClassWorkgroup = 4, + StorageClassCrossWorkgroup = 5, + StorageClassPrivate = 6, + StorageClassFunction = 7, + StorageClassGeneric = 8, + StorageClassPushConstant = 9, + StorageClassAtomicCounter = 10, + StorageClassImage = 11, + StorageClassStorageBuffer = 12, + StorageClassCallableDataKHR = 5328, + StorageClassCallableDataNV = 5328, + StorageClassIncomingCallableDataKHR = 5329, + StorageClassIncomingCallableDataNV = 5329, + StorageClassRayPayloadKHR = 5338, + StorageClassRayPayloadNV = 5338, + StorageClassHitAttributeKHR = 5339, + StorageClassHitAttributeNV = 5339, + StorageClassIncomingRayPayloadKHR = 5342, + StorageClassIncomingRayPayloadNV = 5342, + StorageClassShaderRecordBufferKHR = 5343, + StorageClassShaderRecordBufferNV = 5343, + StorageClassPhysicalStorageBuffer = 5349, + StorageClassPhysicalStorageBufferEXT = 5349, + StorageClassMax = 0x7fffffff, +}; + +enum Dim { + Dim1D = 0, + Dim2D = 1, + Dim3D = 2, + DimCube = 3, + DimRect = 4, + DimBuffer = 5, + DimSubpassData = 6, + DimMax = 0x7fffffff, +}; + +enum SamplerAddressingMode { + SamplerAddressingModeNone = 0, + SamplerAddressingModeClampToEdge = 1, + SamplerAddressingModeClamp = 2, + SamplerAddressingModeRepeat = 3, + SamplerAddressingModeRepeatMirrored = 4, + SamplerAddressingModeMax = 0x7fffffff, +}; + +enum SamplerFilterMode { + SamplerFilterModeNearest = 0, + SamplerFilterModeLinear = 1, + SamplerFilterModeMax = 0x7fffffff, +}; + +enum ImageFormat { + ImageFormatUnknown = 0, + ImageFormatRgba32f = 1, + ImageFormatRgba16f = 2, + ImageFormatR32f = 3, + ImageFormatRgba8 = 4, + ImageFormatRgba8Snorm = 5, + ImageFormatRg32f = 6, + ImageFormatRg16f = 7, + ImageFormatR11fG11fB10f = 8, + ImageFormatR16f = 9, + ImageFormatRgba16 = 10, + ImageFormatRgb10A2 = 11, + ImageFormatRg16 = 12, + ImageFormatRg8 = 13, + ImageFormatR16 = 14, + ImageFormatR8 = 15, + ImageFormatRgba16Snorm = 16, + ImageFormatRg16Snorm = 17, + ImageFormatRg8Snorm = 18, + ImageFormatR16Snorm = 19, + ImageFormatR8Snorm = 20, + ImageFormatRgba32i = 21, + ImageFormatRgba16i = 22, + ImageFormatRgba8i = 23, + ImageFormatR32i = 24, + ImageFormatRg32i = 25, + ImageFormatRg16i = 26, + ImageFormatRg8i = 27, + ImageFormatR16i = 28, + ImageFormatR8i = 29, + ImageFormatRgba32ui = 30, + ImageFormatRgba16ui = 31, + ImageFormatRgba8ui = 32, + ImageFormatR32ui = 33, + ImageFormatRgb10a2ui = 34, + ImageFormatRg32ui = 35, + ImageFormatRg16ui = 36, + ImageFormatRg8ui = 37, + ImageFormatR16ui = 38, + ImageFormatR8ui = 39, + ImageFormatMax = 0x7fffffff, +}; + +enum ImageChannelOrder { + ImageChannelOrderR = 0, + ImageChannelOrderA = 1, + ImageChannelOrderRG = 2, + ImageChannelOrderRA = 3, + ImageChannelOrderRGB = 4, + ImageChannelOrderRGBA = 5, + ImageChannelOrderBGRA = 6, + ImageChannelOrderARGB = 7, + ImageChannelOrderIntensity = 8, + ImageChannelOrderLuminance = 9, + ImageChannelOrderRx = 10, + ImageChannelOrderRGx = 11, + ImageChannelOrderRGBx = 12, + ImageChannelOrderDepth = 13, + ImageChannelOrderDepthStencil = 14, + ImageChannelOrdersRGB = 15, + ImageChannelOrdersRGBx = 16, + ImageChannelOrdersRGBA = 17, + ImageChannelOrdersBGRA = 18, + ImageChannelOrderABGR = 19, + ImageChannelOrderMax = 0x7fffffff, +}; + +enum ImageChannelDataType { + ImageChannelDataTypeSnormInt8 = 0, + ImageChannelDataTypeSnormInt16 = 1, + ImageChannelDataTypeUnormInt8 = 2, + ImageChannelDataTypeUnormInt16 = 3, + ImageChannelDataTypeUnormShort565 = 4, + ImageChannelDataTypeUnormShort555 = 5, + ImageChannelDataTypeUnormInt101010 = 6, + ImageChannelDataTypeSignedInt8 = 7, + ImageChannelDataTypeSignedInt16 = 8, + ImageChannelDataTypeSignedInt32 = 9, + ImageChannelDataTypeUnsignedInt8 = 10, + ImageChannelDataTypeUnsignedInt16 = 11, + ImageChannelDataTypeUnsignedInt32 = 12, + ImageChannelDataTypeHalfFloat = 13, + ImageChannelDataTypeFloat = 14, + ImageChannelDataTypeUnormInt24 = 15, + ImageChannelDataTypeUnormInt101010_2 = 16, + ImageChannelDataTypeMax = 0x7fffffff, +}; + +enum ImageOperandsShift { + ImageOperandsBiasShift = 0, + ImageOperandsLodShift = 1, + ImageOperandsGradShift = 2, + ImageOperandsConstOffsetShift = 3, + ImageOperandsOffsetShift = 4, + ImageOperandsConstOffsetsShift = 5, + ImageOperandsSampleShift = 6, + ImageOperandsMinLodShift = 7, + ImageOperandsMakeTexelAvailableShift = 8, + ImageOperandsMakeTexelAvailableKHRShift = 8, + ImageOperandsMakeTexelVisibleShift = 9, + ImageOperandsMakeTexelVisibleKHRShift = 9, + ImageOperandsNonPrivateTexelShift = 10, + ImageOperandsNonPrivateTexelKHRShift = 10, + ImageOperandsVolatileTexelShift = 11, + ImageOperandsVolatileTexelKHRShift = 11, + ImageOperandsSignExtendShift = 12, + ImageOperandsZeroExtendShift = 13, + ImageOperandsMax = 0x7fffffff, +}; + +enum ImageOperandsMask { + ImageOperandsMaskNone = 0, + ImageOperandsBiasMask = 0x00000001, + ImageOperandsLodMask = 0x00000002, + ImageOperandsGradMask = 0x00000004, + ImageOperandsConstOffsetMask = 0x00000008, + ImageOperandsOffsetMask = 0x00000010, + ImageOperandsConstOffsetsMask = 0x00000020, + ImageOperandsSampleMask = 0x00000040, + ImageOperandsMinLodMask = 0x00000080, + ImageOperandsMakeTexelAvailableMask = 0x00000100, + ImageOperandsMakeTexelAvailableKHRMask = 0x00000100, + ImageOperandsMakeTexelVisibleMask = 0x00000200, + ImageOperandsMakeTexelVisibleKHRMask = 0x00000200, + ImageOperandsNonPrivateTexelMask = 0x00000400, + ImageOperandsNonPrivateTexelKHRMask = 0x00000400, + ImageOperandsVolatileTexelMask = 0x00000800, + ImageOperandsVolatileTexelKHRMask = 0x00000800, + ImageOperandsSignExtendMask = 0x00001000, + ImageOperandsZeroExtendMask = 0x00002000, +}; + +enum FPFastMathModeShift { + FPFastMathModeNotNaNShift = 0, + FPFastMathModeNotInfShift = 1, + FPFastMathModeNSZShift = 2, + FPFastMathModeAllowRecipShift = 3, + FPFastMathModeFastShift = 4, + FPFastMathModeMax = 0x7fffffff, +}; + +enum FPFastMathModeMask { + FPFastMathModeMaskNone = 0, + FPFastMathModeNotNaNMask = 0x00000001, + FPFastMathModeNotInfMask = 0x00000002, + FPFastMathModeNSZMask = 0x00000004, + FPFastMathModeAllowRecipMask = 0x00000008, + FPFastMathModeFastMask = 0x00000010, +}; + +enum FPRoundingMode { + FPRoundingModeRTE = 0, + FPRoundingModeRTZ = 1, + FPRoundingModeRTP = 2, + FPRoundingModeRTN = 3, + FPRoundingModeMax = 0x7fffffff, +}; + +enum LinkageType { + LinkageTypeExport = 0, + LinkageTypeImport = 1, + LinkageTypeMax = 0x7fffffff, +}; + +enum AccessQualifier { + AccessQualifierReadOnly = 0, + AccessQualifierWriteOnly = 1, + AccessQualifierReadWrite = 2, + AccessQualifierMax = 0x7fffffff, +}; + +enum FunctionParameterAttribute { + FunctionParameterAttributeZext = 0, + FunctionParameterAttributeSext = 1, + FunctionParameterAttributeByVal = 2, + FunctionParameterAttributeSret = 3, + FunctionParameterAttributeNoAlias = 4, + FunctionParameterAttributeNoCapture = 5, + FunctionParameterAttributeNoWrite = 6, + FunctionParameterAttributeNoReadWrite = 7, + FunctionParameterAttributeMax = 0x7fffffff, +}; + +enum Decoration { + DecorationRelaxedPrecision = 0, + DecorationSpecId = 1, + DecorationBlock = 2, + DecorationBufferBlock = 3, + DecorationRowMajor = 4, + DecorationColMajor = 5, + DecorationArrayStride = 6, + DecorationMatrixStride = 7, + DecorationGLSLShared = 8, + DecorationGLSLPacked = 9, + DecorationCPacked = 10, + DecorationBuiltIn = 11, + DecorationNoPerspective = 13, + DecorationFlat = 14, + DecorationPatch = 15, + DecorationCentroid = 16, + DecorationSample = 17, + DecorationInvariant = 18, + DecorationRestrict = 19, + DecorationAliased = 20, + DecorationVolatile = 21, + DecorationConstant = 22, + DecorationCoherent = 23, + DecorationNonWritable = 24, + DecorationNonReadable = 25, + DecorationUniform = 26, + DecorationUniformId = 27, + DecorationSaturatedConversion = 28, + DecorationStream = 29, + DecorationLocation = 30, + DecorationComponent = 31, + DecorationIndex = 32, + DecorationBinding = 33, + DecorationDescriptorSet = 34, + DecorationOffset = 35, + DecorationXfbBuffer = 36, + DecorationXfbStride = 37, + DecorationFuncParamAttr = 38, + DecorationFPRoundingMode = 39, + DecorationFPFastMathMode = 40, + DecorationLinkageAttributes = 41, + DecorationNoContraction = 42, + DecorationInputAttachmentIndex = 43, + DecorationAlignment = 44, + DecorationMaxByteOffset = 45, + DecorationAlignmentId = 46, + DecorationMaxByteOffsetId = 47, + DecorationNoSignedWrap = 4469, + DecorationNoUnsignedWrap = 4470, + DecorationExplicitInterpAMD = 4999, + DecorationOverrideCoverageNV = 5248, + DecorationPassthroughNV = 5250, + DecorationViewportRelativeNV = 5252, + DecorationSecondaryViewportRelativeNV = 5256, + DecorationPerPrimitiveNV = 5271, + DecorationPerViewNV = 5272, + DecorationPerTaskNV = 5273, + DecorationPerVertexNV = 5285, + DecorationNonUniform = 5300, + DecorationNonUniformEXT = 5300, + DecorationRestrictPointer = 5355, + DecorationRestrictPointerEXT = 5355, + DecorationAliasedPointer = 5356, + DecorationAliasedPointerEXT = 5356, + DecorationCounterBuffer = 5634, + DecorationHlslCounterBufferGOOGLE = 5634, + DecorationHlslSemanticGOOGLE = 5635, + DecorationUserSemantic = 5635, + DecorationUserTypeGOOGLE = 5636, + DecorationMax = 0x7fffffff, +}; + +enum BuiltIn { + BuiltInPosition = 0, + BuiltInPointSize = 1, + BuiltInClipDistance = 3, + BuiltInCullDistance = 4, + BuiltInVertexId = 5, + BuiltInInstanceId = 6, + BuiltInPrimitiveId = 7, + BuiltInInvocationId = 8, + BuiltInLayer = 9, + BuiltInViewportIndex = 10, + BuiltInTessLevelOuter = 11, + BuiltInTessLevelInner = 12, + BuiltInTessCoord = 13, + BuiltInPatchVertices = 14, + BuiltInFragCoord = 15, + BuiltInPointCoord = 16, + BuiltInFrontFacing = 17, + BuiltInSampleId = 18, + BuiltInSamplePosition = 19, + BuiltInSampleMask = 20, + BuiltInFragDepth = 22, + BuiltInHelperInvocation = 23, + BuiltInNumWorkgroups = 24, + BuiltInWorkgroupSize = 25, + BuiltInWorkgroupId = 26, + BuiltInLocalInvocationId = 27, + BuiltInGlobalInvocationId = 28, + BuiltInLocalInvocationIndex = 29, + BuiltInWorkDim = 30, + BuiltInGlobalSize = 31, + BuiltInEnqueuedWorkgroupSize = 32, + BuiltInGlobalOffset = 33, + BuiltInGlobalLinearId = 34, + BuiltInSubgroupSize = 36, + BuiltInSubgroupMaxSize = 37, + BuiltInNumSubgroups = 38, + BuiltInNumEnqueuedSubgroups = 39, + BuiltInSubgroupId = 40, + BuiltInSubgroupLocalInvocationId = 41, + BuiltInVertexIndex = 42, + BuiltInInstanceIndex = 43, + BuiltInSubgroupEqMask = 4416, + BuiltInSubgroupEqMaskKHR = 4416, + BuiltInSubgroupGeMask = 4417, + BuiltInSubgroupGeMaskKHR = 4417, + BuiltInSubgroupGtMask = 4418, + BuiltInSubgroupGtMaskKHR = 4418, + BuiltInSubgroupLeMask = 4419, + BuiltInSubgroupLeMaskKHR = 4419, + BuiltInSubgroupLtMask = 4420, + BuiltInSubgroupLtMaskKHR = 4420, + BuiltInBaseVertex = 4424, + BuiltInBaseInstance = 4425, + BuiltInDrawIndex = 4426, + BuiltInDeviceIndex = 4438, + BuiltInViewIndex = 4440, + BuiltInBaryCoordNoPerspAMD = 4992, + BuiltInBaryCoordNoPerspCentroidAMD = 4993, + BuiltInBaryCoordNoPerspSampleAMD = 4994, + BuiltInBaryCoordSmoothAMD = 4995, + BuiltInBaryCoordSmoothCentroidAMD = 4996, + BuiltInBaryCoordSmoothSampleAMD = 4997, + BuiltInBaryCoordPullModelAMD = 4998, + BuiltInFragStencilRefEXT = 5014, + BuiltInViewportMaskNV = 5253, + BuiltInSecondaryPositionNV = 5257, + BuiltInSecondaryViewportMaskNV = 5258, + BuiltInPositionPerViewNV = 5261, + BuiltInViewportMaskPerViewNV = 5262, + BuiltInFullyCoveredEXT = 5264, + BuiltInTaskCountNV = 5274, + BuiltInPrimitiveCountNV = 5275, + BuiltInPrimitiveIndicesNV = 5276, + BuiltInClipDistancePerViewNV = 5277, + BuiltInCullDistancePerViewNV = 5278, + BuiltInLayerPerViewNV = 5279, + BuiltInMeshViewCountNV = 5280, + BuiltInMeshViewIndicesNV = 5281, + BuiltInBaryCoordNV = 5286, + BuiltInBaryCoordNoPerspNV = 5287, + BuiltInFragSizeEXT = 5292, + BuiltInFragmentSizeNV = 5292, + BuiltInFragInvocationCountEXT = 5293, + BuiltInInvocationsPerPixelNV = 5293, + BuiltInLaunchIdKHR = 5319, + BuiltInLaunchIdNV = 5319, + BuiltInLaunchSizeKHR = 5320, + BuiltInLaunchSizeNV = 5320, + BuiltInWorldRayOriginKHR = 5321, + BuiltInWorldRayOriginNV = 5321, + BuiltInWorldRayDirectionKHR = 5322, + BuiltInWorldRayDirectionNV = 5322, + BuiltInObjectRayOriginKHR = 5323, + BuiltInObjectRayOriginNV = 5323, + BuiltInObjectRayDirectionKHR = 5324, + BuiltInObjectRayDirectionNV = 5324, + BuiltInRayTminKHR = 5325, + BuiltInRayTminNV = 5325, + BuiltInRayTmaxKHR = 5326, + BuiltInRayTmaxNV = 5326, + BuiltInInstanceCustomIndexKHR = 5327, + BuiltInInstanceCustomIndexNV = 5327, + BuiltInObjectToWorldKHR = 5330, + BuiltInObjectToWorldNV = 5330, + BuiltInWorldToObjectKHR = 5331, + BuiltInWorldToObjectNV = 5331, + BuiltInHitTKHR = 5332, + BuiltInHitTNV = 5332, + BuiltInHitKindKHR = 5333, + BuiltInHitKindNV = 5333, + BuiltInIncomingRayFlagsKHR = 5351, + BuiltInIncomingRayFlagsNV = 5351, + BuiltInRayGeometryIndexKHR = 5352, + BuiltInWarpsPerSMNV = 5374, + BuiltInSMCountNV = 5375, + BuiltInWarpIDNV = 5376, + BuiltInSMIDNV = 5377, + BuiltInMax = 0x7fffffff, +}; + +enum SelectionControlShift { + SelectionControlFlattenShift = 0, + SelectionControlDontFlattenShift = 1, + SelectionControlMax = 0x7fffffff, +}; + +enum SelectionControlMask { + SelectionControlMaskNone = 0, + SelectionControlFlattenMask = 0x00000001, + SelectionControlDontFlattenMask = 0x00000002, +}; + +enum LoopControlShift { + LoopControlUnrollShift = 0, + LoopControlDontUnrollShift = 1, + LoopControlDependencyInfiniteShift = 2, + LoopControlDependencyLengthShift = 3, + LoopControlMinIterationsShift = 4, + LoopControlMaxIterationsShift = 5, + LoopControlIterationMultipleShift = 6, + LoopControlPeelCountShift = 7, + LoopControlPartialCountShift = 8, + LoopControlMax = 0x7fffffff, +}; + +enum LoopControlMask { + LoopControlMaskNone = 0, + LoopControlUnrollMask = 0x00000001, + LoopControlDontUnrollMask = 0x00000002, + LoopControlDependencyInfiniteMask = 0x00000004, + LoopControlDependencyLengthMask = 0x00000008, + LoopControlMinIterationsMask = 0x00000010, + LoopControlMaxIterationsMask = 0x00000020, + LoopControlIterationMultipleMask = 0x00000040, + LoopControlPeelCountMask = 0x00000080, + LoopControlPartialCountMask = 0x00000100, +}; + +enum FunctionControlShift { + FunctionControlInlineShift = 0, + FunctionControlDontInlineShift = 1, + FunctionControlPureShift = 2, + FunctionControlConstShift = 3, + FunctionControlMax = 0x7fffffff, +}; + +enum FunctionControlMask { + FunctionControlMaskNone = 0, + FunctionControlInlineMask = 0x00000001, + FunctionControlDontInlineMask = 0x00000002, + FunctionControlPureMask = 0x00000004, + FunctionControlConstMask = 0x00000008, +}; + +enum MemorySemanticsShift { + MemorySemanticsAcquireShift = 1, + MemorySemanticsReleaseShift = 2, + MemorySemanticsAcquireReleaseShift = 3, + MemorySemanticsSequentiallyConsistentShift = 4, + MemorySemanticsUniformMemoryShift = 6, + MemorySemanticsSubgroupMemoryShift = 7, + MemorySemanticsWorkgroupMemoryShift = 8, + MemorySemanticsCrossWorkgroupMemoryShift = 9, + MemorySemanticsAtomicCounterMemoryShift = 10, + MemorySemanticsImageMemoryShift = 11, + MemorySemanticsOutputMemoryShift = 12, + MemorySemanticsOutputMemoryKHRShift = 12, + MemorySemanticsMakeAvailableShift = 13, + MemorySemanticsMakeAvailableKHRShift = 13, + MemorySemanticsMakeVisibleShift = 14, + MemorySemanticsMakeVisibleKHRShift = 14, + MemorySemanticsVolatileShift = 15, + MemorySemanticsMax = 0x7fffffff, +}; + +enum MemorySemanticsMask { + MemorySemanticsMaskNone = 0, + MemorySemanticsAcquireMask = 0x00000002, + MemorySemanticsReleaseMask = 0x00000004, + MemorySemanticsAcquireReleaseMask = 0x00000008, + MemorySemanticsSequentiallyConsistentMask = 0x00000010, + MemorySemanticsUniformMemoryMask = 0x00000040, + MemorySemanticsSubgroupMemoryMask = 0x00000080, + MemorySemanticsWorkgroupMemoryMask = 0x00000100, + MemorySemanticsCrossWorkgroupMemoryMask = 0x00000200, + MemorySemanticsAtomicCounterMemoryMask = 0x00000400, + MemorySemanticsImageMemoryMask = 0x00000800, + MemorySemanticsOutputMemoryMask = 0x00001000, + MemorySemanticsOutputMemoryKHRMask = 0x00001000, + MemorySemanticsMakeAvailableMask = 0x00002000, + MemorySemanticsMakeAvailableKHRMask = 0x00002000, + MemorySemanticsMakeVisibleMask = 0x00004000, + MemorySemanticsMakeVisibleKHRMask = 0x00004000, + MemorySemanticsVolatileMask = 0x00008000, +}; + +enum MemoryAccessShift { + MemoryAccessVolatileShift = 0, + MemoryAccessAlignedShift = 1, + MemoryAccessNontemporalShift = 2, + MemoryAccessMakePointerAvailableShift = 3, + MemoryAccessMakePointerAvailableKHRShift = 3, + MemoryAccessMakePointerVisibleShift = 4, + MemoryAccessMakePointerVisibleKHRShift = 4, + MemoryAccessNonPrivatePointerShift = 5, + MemoryAccessNonPrivatePointerKHRShift = 5, + MemoryAccessMax = 0x7fffffff, +}; + +enum MemoryAccessMask { + MemoryAccessMaskNone = 0, + MemoryAccessVolatileMask = 0x00000001, + MemoryAccessAlignedMask = 0x00000002, + MemoryAccessNontemporalMask = 0x00000004, + MemoryAccessMakePointerAvailableMask = 0x00000008, + MemoryAccessMakePointerAvailableKHRMask = 0x00000008, + MemoryAccessMakePointerVisibleMask = 0x00000010, + MemoryAccessMakePointerVisibleKHRMask = 0x00000010, + MemoryAccessNonPrivatePointerMask = 0x00000020, + MemoryAccessNonPrivatePointerKHRMask = 0x00000020, +}; + +enum Scope { + ScopeCrossDevice = 0, + ScopeDevice = 1, + ScopeWorkgroup = 2, + ScopeSubgroup = 3, + ScopeInvocation = 4, + ScopeQueueFamily = 5, + ScopeQueueFamilyKHR = 5, + ScopeShaderCallKHR = 6, + ScopeMax = 0x7fffffff, +}; + +enum GroupOperation { + GroupOperationReduce = 0, + GroupOperationInclusiveScan = 1, + GroupOperationExclusiveScan = 2, + GroupOperationClusteredReduce = 3, + GroupOperationPartitionedReduceNV = 6, + GroupOperationPartitionedInclusiveScanNV = 7, + GroupOperationPartitionedExclusiveScanNV = 8, + GroupOperationMax = 0x7fffffff, +}; + +enum KernelEnqueueFlags { + KernelEnqueueFlagsNoWait = 0, + KernelEnqueueFlagsWaitKernel = 1, + KernelEnqueueFlagsWaitWorkGroup = 2, + KernelEnqueueFlagsMax = 0x7fffffff, +}; + +enum KernelProfilingInfoShift { + KernelProfilingInfoCmdExecTimeShift = 0, + KernelProfilingInfoMax = 0x7fffffff, +}; + +enum KernelProfilingInfoMask { + KernelProfilingInfoMaskNone = 0, + KernelProfilingInfoCmdExecTimeMask = 0x00000001, +}; + +enum Capability { + CapabilityMatrix = 0, + CapabilityShader = 1, + CapabilityGeometry = 2, + CapabilityTessellation = 3, + CapabilityAddresses = 4, + CapabilityLinkage = 5, + CapabilityKernel = 6, + CapabilityVector16 = 7, + CapabilityFloat16Buffer = 8, + CapabilityFloat16 = 9, + CapabilityFloat64 = 10, + CapabilityInt64 = 11, + CapabilityInt64Atomics = 12, + CapabilityImageBasic = 13, + CapabilityImageReadWrite = 14, + CapabilityImageMipmap = 15, + CapabilityPipes = 17, + CapabilityGroups = 18, + CapabilityDeviceEnqueue = 19, + CapabilityLiteralSampler = 20, + CapabilityAtomicStorage = 21, + CapabilityInt16 = 22, + CapabilityTessellationPointSize = 23, + CapabilityGeometryPointSize = 24, + CapabilityImageGatherExtended = 25, + CapabilityStorageImageMultisample = 27, + CapabilityUniformBufferArrayDynamicIndexing = 28, + CapabilitySampledImageArrayDynamicIndexing = 29, + CapabilityStorageBufferArrayDynamicIndexing = 30, + CapabilityStorageImageArrayDynamicIndexing = 31, + CapabilityClipDistance = 32, + CapabilityCullDistance = 33, + CapabilityImageCubeArray = 34, + CapabilitySampleRateShading = 35, + CapabilityImageRect = 36, + CapabilitySampledRect = 37, + CapabilityGenericPointer = 38, + CapabilityInt8 = 39, + CapabilityInputAttachment = 40, + CapabilitySparseResidency = 41, + CapabilityMinLod = 42, + CapabilitySampled1D = 43, + CapabilityImage1D = 44, + CapabilitySampledCubeArray = 45, + CapabilitySampledBuffer = 46, + CapabilityImageBuffer = 47, + CapabilityImageMSArray = 48, + CapabilityStorageImageExtendedFormats = 49, + CapabilityImageQuery = 50, + CapabilityDerivativeControl = 51, + CapabilityInterpolationFunction = 52, + CapabilityTransformFeedback = 53, + CapabilityGeometryStreams = 54, + CapabilityStorageImageReadWithoutFormat = 55, + CapabilityStorageImageWriteWithoutFormat = 56, + CapabilityMultiViewport = 57, + CapabilitySubgroupDispatch = 58, + CapabilityNamedBarrier = 59, + CapabilityPipeStorage = 60, + CapabilityGroupNonUniform = 61, + CapabilityGroupNonUniformVote = 62, + CapabilityGroupNonUniformArithmetic = 63, + CapabilityGroupNonUniformBallot = 64, + CapabilityGroupNonUniformShuffle = 65, + CapabilityGroupNonUniformShuffleRelative = 66, + CapabilityGroupNonUniformClustered = 67, + CapabilityGroupNonUniformQuad = 68, + CapabilityShaderLayer = 69, + CapabilityShaderViewportIndex = 70, + CapabilitySubgroupBallotKHR = 4423, + CapabilityDrawParameters = 4427, + CapabilitySubgroupVoteKHR = 4431, + CapabilityStorageBuffer16BitAccess = 4433, + CapabilityStorageUniformBufferBlock16 = 4433, + CapabilityStorageUniform16 = 4434, + CapabilityUniformAndStorageBuffer16BitAccess = 4434, + CapabilityStoragePushConstant16 = 4435, + CapabilityStorageInputOutput16 = 4436, + CapabilityDeviceGroup = 4437, + CapabilityMultiView = 4439, + CapabilityVariablePointersStorageBuffer = 4441, + CapabilityVariablePointers = 4442, + CapabilityAtomicStorageOps = 4445, + CapabilitySampleMaskPostDepthCoverage = 4447, + CapabilityStorageBuffer8BitAccess = 4448, + CapabilityUniformAndStorageBuffer8BitAccess = 4449, + CapabilityStoragePushConstant8 = 4450, + CapabilityDenormPreserve = 4464, + CapabilityDenormFlushToZero = 4465, + CapabilitySignedZeroInfNanPreserve = 4466, + CapabilityRoundingModeRTE = 4467, + CapabilityRoundingModeRTZ = 4468, + CapabilityRayQueryProvisionalKHR = 4471, + CapabilityRayTraversalPrimitiveCullingProvisionalKHR = 4478, + CapabilityFloat16ImageAMD = 5008, + CapabilityImageGatherBiasLodAMD = 5009, + CapabilityFragmentMaskAMD = 5010, + CapabilityStencilExportEXT = 5013, + CapabilityImageReadWriteLodAMD = 5015, + CapabilityShaderClockKHR = 5055, + CapabilitySampleMaskOverrideCoverageNV = 5249, + CapabilityGeometryShaderPassthroughNV = 5251, + CapabilityShaderViewportIndexLayerEXT = 5254, + CapabilityShaderViewportIndexLayerNV = 5254, + CapabilityShaderViewportMaskNV = 5255, + CapabilityShaderStereoViewNV = 5259, + CapabilityPerViewAttributesNV = 5260, + CapabilityFragmentFullyCoveredEXT = 5265, + CapabilityMeshShadingNV = 5266, + CapabilityImageFootprintNV = 5282, + CapabilityFragmentBarycentricNV = 5284, + CapabilityComputeDerivativeGroupQuadsNV = 5288, + CapabilityFragmentDensityEXT = 5291, + CapabilityShadingRateNV = 5291, + CapabilityGroupNonUniformPartitionedNV = 5297, + CapabilityShaderNonUniform = 5301, + CapabilityShaderNonUniformEXT = 5301, + CapabilityRuntimeDescriptorArray = 5302, + CapabilityRuntimeDescriptorArrayEXT = 5302, + CapabilityInputAttachmentArrayDynamicIndexing = 5303, + CapabilityInputAttachmentArrayDynamicIndexingEXT = 5303, + CapabilityUniformTexelBufferArrayDynamicIndexing = 5304, + CapabilityUniformTexelBufferArrayDynamicIndexingEXT = 5304, + CapabilityStorageTexelBufferArrayDynamicIndexing = 5305, + CapabilityStorageTexelBufferArrayDynamicIndexingEXT = 5305, + CapabilityUniformBufferArrayNonUniformIndexing = 5306, + CapabilityUniformBufferArrayNonUniformIndexingEXT = 5306, + CapabilitySampledImageArrayNonUniformIndexing = 5307, + CapabilitySampledImageArrayNonUniformIndexingEXT = 5307, + CapabilityStorageBufferArrayNonUniformIndexing = 5308, + CapabilityStorageBufferArrayNonUniformIndexingEXT = 5308, + CapabilityStorageImageArrayNonUniformIndexing = 5309, + CapabilityStorageImageArrayNonUniformIndexingEXT = 5309, + CapabilityInputAttachmentArrayNonUniformIndexing = 5310, + CapabilityInputAttachmentArrayNonUniformIndexingEXT = 5310, + CapabilityUniformTexelBufferArrayNonUniformIndexing = 5311, + CapabilityUniformTexelBufferArrayNonUniformIndexingEXT = 5311, + CapabilityStorageTexelBufferArrayNonUniformIndexing = 5312, + CapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312, + CapabilityRayTracingNV = 5340, + CapabilityVulkanMemoryModel = 5345, + CapabilityVulkanMemoryModelKHR = 5345, + CapabilityVulkanMemoryModelDeviceScope = 5346, + CapabilityVulkanMemoryModelDeviceScopeKHR = 5346, + CapabilityPhysicalStorageBufferAddresses = 5347, + CapabilityPhysicalStorageBufferAddressesEXT = 5347, + CapabilityComputeDerivativeGroupLinearNV = 5350, + CapabilityRayTracingProvisionalKHR = 5353, + CapabilityCooperativeMatrixNV = 5357, + CapabilityFragmentShaderSampleInterlockEXT = 5363, + CapabilityFragmentShaderShadingRateInterlockEXT = 5372, + CapabilityShaderSMBuiltinsNV = 5373, + CapabilityFragmentShaderPixelInterlockEXT = 5378, + CapabilityDemoteToHelperInvocationEXT = 5379, + CapabilitySubgroupShuffleINTEL = 5568, + CapabilitySubgroupBufferBlockIOINTEL = 5569, + CapabilitySubgroupImageBlockIOINTEL = 5570, + CapabilitySubgroupImageMediaBlockIOINTEL = 5579, + CapabilityIntegerFunctions2INTEL = 5584, + CapabilitySubgroupAvcMotionEstimationINTEL = 5696, + CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697, + CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698, + CapabilityMax = 0x7fffffff, +}; + +enum RayFlagsShift { + RayFlagsOpaqueKHRShift = 0, + RayFlagsNoOpaqueKHRShift = 1, + RayFlagsTerminateOnFirstHitKHRShift = 2, + RayFlagsSkipClosestHitShaderKHRShift = 3, + RayFlagsCullBackFacingTrianglesKHRShift = 4, + RayFlagsCullFrontFacingTrianglesKHRShift = 5, + RayFlagsCullOpaqueKHRShift = 6, + RayFlagsCullNoOpaqueKHRShift = 7, + RayFlagsSkipTrianglesKHRShift = 8, + RayFlagsSkipAABBsKHRShift = 9, + RayFlagsMax = 0x7fffffff, +}; + +enum RayFlagsMask { + RayFlagsMaskNone = 0, + RayFlagsOpaqueKHRMask = 0x00000001, + RayFlagsNoOpaqueKHRMask = 0x00000002, + RayFlagsTerminateOnFirstHitKHRMask = 0x00000004, + RayFlagsSkipClosestHitShaderKHRMask = 0x00000008, + RayFlagsCullBackFacingTrianglesKHRMask = 0x00000010, + RayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020, + RayFlagsCullOpaqueKHRMask = 0x00000040, + RayFlagsCullNoOpaqueKHRMask = 0x00000080, + RayFlagsSkipTrianglesKHRMask = 0x00000100, + RayFlagsSkipAABBsKHRMask = 0x00000200, +}; + +enum RayQueryIntersection { + RayQueryIntersectionRayQueryCandidateIntersectionKHR = 0, + RayQueryIntersectionRayQueryCommittedIntersectionKHR = 1, + RayQueryIntersectionMax = 0x7fffffff, +}; + +enum RayQueryCommittedIntersectionType { + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR = 0, + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR = 1, + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR = 2, + RayQueryCommittedIntersectionTypeMax = 0x7fffffff, +}; + +enum RayQueryCandidateIntersectionType { + RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR = 0, + RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR = 1, + RayQueryCandidateIntersectionTypeMax = 0x7fffffff, +}; + +enum Op { + OpNop = 0, + OpUndef = 1, + OpSourceContinued = 2, + OpSource = 3, + OpSourceExtension = 4, + OpName = 5, + OpMemberName = 6, + OpString = 7, + OpLine = 8, + OpExtension = 10, + OpExtInstImport = 11, + OpExtInst = 12, + OpMemoryModel = 14, + OpEntryPoint = 15, + OpExecutionMode = 16, + OpCapability = 17, + OpTypeVoid = 19, + OpTypeBool = 20, + OpTypeInt = 21, + OpTypeFloat = 22, + OpTypeVector = 23, + OpTypeMatrix = 24, + OpTypeImage = 25, + OpTypeSampler = 26, + OpTypeSampledImage = 27, + OpTypeArray = 28, + OpTypeRuntimeArray = 29, + OpTypeStruct = 30, + OpTypeOpaque = 31, + OpTypePointer = 32, + OpTypeFunction = 33, + OpTypeEvent = 34, + OpTypeDeviceEvent = 35, + OpTypeReserveId = 36, + OpTypeQueue = 37, + OpTypePipe = 38, + OpTypeForwardPointer = 39, + OpConstantTrue = 41, + OpConstantFalse = 42, + OpConstant = 43, + OpConstantComposite = 44, + OpConstantSampler = 45, + OpConstantNull = 46, + OpSpecConstantTrue = 48, + OpSpecConstantFalse = 49, + OpSpecConstant = 50, + OpSpecConstantComposite = 51, + OpSpecConstantOp = 52, + OpFunction = 54, + OpFunctionParameter = 55, + OpFunctionEnd = 56, + OpFunctionCall = 57, + OpVariable = 59, + OpImageTexelPointer = 60, + OpLoad = 61, + OpStore = 62, + OpCopyMemory = 63, + OpCopyMemorySized = 64, + OpAccessChain = 65, + OpInBoundsAccessChain = 66, + OpPtrAccessChain = 67, + OpArrayLength = 68, + OpGenericPtrMemSemantics = 69, + OpInBoundsPtrAccessChain = 70, + OpDecorate = 71, + OpMemberDecorate = 72, + OpDecorationGroup = 73, + OpGroupDecorate = 74, + OpGroupMemberDecorate = 75, + OpVectorExtractDynamic = 77, + OpVectorInsertDynamic = 78, + OpVectorShuffle = 79, + OpCompositeConstruct = 80, + OpCompositeExtract = 81, + OpCompositeInsert = 82, + OpCopyObject = 83, + OpTranspose = 84, + OpSampledImage = 86, + OpImageSampleImplicitLod = 87, + OpImageSampleExplicitLod = 88, + OpImageSampleDrefImplicitLod = 89, + OpImageSampleDrefExplicitLod = 90, + OpImageSampleProjImplicitLod = 91, + OpImageSampleProjExplicitLod = 92, + OpImageSampleProjDrefImplicitLod = 93, + OpImageSampleProjDrefExplicitLod = 94, + OpImageFetch = 95, + OpImageGather = 96, + OpImageDrefGather = 97, + OpImageRead = 98, + OpImageWrite = 99, + OpImage = 100, + OpImageQueryFormat = 101, + OpImageQueryOrder = 102, + OpImageQuerySizeLod = 103, + OpImageQuerySize = 104, + OpImageQueryLod = 105, + OpImageQueryLevels = 106, + OpImageQuerySamples = 107, + OpConvertFToU = 109, + OpConvertFToS = 110, + OpConvertSToF = 111, + OpConvertUToF = 112, + OpUConvert = 113, + OpSConvert = 114, + OpFConvert = 115, + OpQuantizeToF16 = 116, + OpConvertPtrToU = 117, + OpSatConvertSToU = 118, + OpSatConvertUToS = 119, + OpConvertUToPtr = 120, + OpPtrCastToGeneric = 121, + OpGenericCastToPtr = 122, + OpGenericCastToPtrExplicit = 123, + OpBitcast = 124, + OpSNegate = 126, + OpFNegate = 127, + OpIAdd = 128, + OpFAdd = 129, + OpISub = 130, + OpFSub = 131, + OpIMul = 132, + OpFMul = 133, + OpUDiv = 134, + OpSDiv = 135, + OpFDiv = 136, + OpUMod = 137, + OpSRem = 138, + OpSMod = 139, + OpFRem = 140, + OpFMod = 141, + OpVectorTimesScalar = 142, + OpMatrixTimesScalar = 143, + OpVectorTimesMatrix = 144, + OpMatrixTimesVector = 145, + OpMatrixTimesMatrix = 146, + OpOuterProduct = 147, + OpDot = 148, + OpIAddCarry = 149, + OpISubBorrow = 150, + OpUMulExtended = 151, + OpSMulExtended = 152, + OpAny = 154, + OpAll = 155, + OpIsNan = 156, + OpIsInf = 157, + OpIsFinite = 158, + OpIsNormal = 159, + OpSignBitSet = 160, + OpLessOrGreater = 161, + OpOrdered = 162, + OpUnordered = 163, + OpLogicalEqual = 164, + OpLogicalNotEqual = 165, + OpLogicalOr = 166, + OpLogicalAnd = 167, + OpLogicalNot = 168, + OpSelect = 169, + OpIEqual = 170, + OpINotEqual = 171, + OpUGreaterThan = 172, + OpSGreaterThan = 173, + OpUGreaterThanEqual = 174, + OpSGreaterThanEqual = 175, + OpULessThan = 176, + OpSLessThan = 177, + OpULessThanEqual = 178, + OpSLessThanEqual = 179, + OpFOrdEqual = 180, + OpFUnordEqual = 181, + OpFOrdNotEqual = 182, + OpFUnordNotEqual = 183, + OpFOrdLessThan = 184, + OpFUnordLessThan = 185, + OpFOrdGreaterThan = 186, + OpFUnordGreaterThan = 187, + OpFOrdLessThanEqual = 188, + OpFUnordLessThanEqual = 189, + OpFOrdGreaterThanEqual = 190, + OpFUnordGreaterThanEqual = 191, + OpShiftRightLogical = 194, + OpShiftRightArithmetic = 195, + OpShiftLeftLogical = 196, + OpBitwiseOr = 197, + OpBitwiseXor = 198, + OpBitwiseAnd = 199, + OpNot = 200, + OpBitFieldInsert = 201, + OpBitFieldSExtract = 202, + OpBitFieldUExtract = 203, + OpBitReverse = 204, + OpBitCount = 205, + OpDPdx = 207, + OpDPdy = 208, + OpFwidth = 209, + OpDPdxFine = 210, + OpDPdyFine = 211, + OpFwidthFine = 212, + OpDPdxCoarse = 213, + OpDPdyCoarse = 214, + OpFwidthCoarse = 215, + OpEmitVertex = 218, + OpEndPrimitive = 219, + OpEmitStreamVertex = 220, + OpEndStreamPrimitive = 221, + OpControlBarrier = 224, + OpMemoryBarrier = 225, + OpAtomicLoad = 227, + OpAtomicStore = 228, + OpAtomicExchange = 229, + OpAtomicCompareExchange = 230, + OpAtomicCompareExchangeWeak = 231, + OpAtomicIIncrement = 232, + OpAtomicIDecrement = 233, + OpAtomicIAdd = 234, + OpAtomicISub = 235, + OpAtomicSMin = 236, + OpAtomicUMin = 237, + OpAtomicSMax = 238, + OpAtomicUMax = 239, + OpAtomicAnd = 240, + OpAtomicOr = 241, + OpAtomicXor = 242, + OpPhi = 245, + OpLoopMerge = 246, + OpSelectionMerge = 247, + OpLabel = 248, + OpBranch = 249, + OpBranchConditional = 250, + OpSwitch = 251, + OpKill = 252, + OpReturn = 253, + OpReturnValue = 254, + OpUnreachable = 255, + OpLifetimeStart = 256, + OpLifetimeStop = 257, + OpGroupAsyncCopy = 259, + OpGroupWaitEvents = 260, + OpGroupAll = 261, + OpGroupAny = 262, + OpGroupBroadcast = 263, + OpGroupIAdd = 264, + OpGroupFAdd = 265, + OpGroupFMin = 266, + OpGroupUMin = 267, + OpGroupSMin = 268, + OpGroupFMax = 269, + OpGroupUMax = 270, + OpGroupSMax = 271, + OpReadPipe = 274, + OpWritePipe = 275, + OpReservedReadPipe = 276, + OpReservedWritePipe = 277, + OpReserveReadPipePackets = 278, + OpReserveWritePipePackets = 279, + OpCommitReadPipe = 280, + OpCommitWritePipe = 281, + OpIsValidReserveId = 282, + OpGetNumPipePackets = 283, + OpGetMaxPipePackets = 284, + OpGroupReserveReadPipePackets = 285, + OpGroupReserveWritePipePackets = 286, + OpGroupCommitReadPipe = 287, + OpGroupCommitWritePipe = 288, + OpEnqueueMarker = 291, + OpEnqueueKernel = 292, + OpGetKernelNDrangeSubGroupCount = 293, + OpGetKernelNDrangeMaxSubGroupSize = 294, + OpGetKernelWorkGroupSize = 295, + OpGetKernelPreferredWorkGroupSizeMultiple = 296, + OpRetainEvent = 297, + OpReleaseEvent = 298, + OpCreateUserEvent = 299, + OpIsValidEvent = 300, + OpSetUserEventStatus = 301, + OpCaptureEventProfilingInfo = 302, + OpGetDefaultQueue = 303, + OpBuildNDRange = 304, + OpImageSparseSampleImplicitLod = 305, + OpImageSparseSampleExplicitLod = 306, + OpImageSparseSampleDrefImplicitLod = 307, + OpImageSparseSampleDrefExplicitLod = 308, + OpImageSparseSampleProjImplicitLod = 309, + OpImageSparseSampleProjExplicitLod = 310, + OpImageSparseSampleProjDrefImplicitLod = 311, + OpImageSparseSampleProjDrefExplicitLod = 312, + OpImageSparseFetch = 313, + OpImageSparseGather = 314, + OpImageSparseDrefGather = 315, + OpImageSparseTexelsResident = 316, + OpNoLine = 317, + OpAtomicFlagTestAndSet = 318, + OpAtomicFlagClear = 319, + OpImageSparseRead = 320, + OpSizeOf = 321, + OpTypePipeStorage = 322, + OpConstantPipeStorage = 323, + OpCreatePipeFromPipeStorage = 324, + OpGetKernelLocalSizeForSubgroupCount = 325, + OpGetKernelMaxNumSubgroups = 326, + OpTypeNamedBarrier = 327, + OpNamedBarrierInitialize = 328, + OpMemoryNamedBarrier = 329, + OpModuleProcessed = 330, + OpExecutionModeId = 331, + OpDecorateId = 332, + OpGroupNonUniformElect = 333, + OpGroupNonUniformAll = 334, + OpGroupNonUniformAny = 335, + OpGroupNonUniformAllEqual = 336, + OpGroupNonUniformBroadcast = 337, + OpGroupNonUniformBroadcastFirst = 338, + OpGroupNonUniformBallot = 339, + OpGroupNonUniformInverseBallot = 340, + OpGroupNonUniformBallotBitExtract = 341, + OpGroupNonUniformBallotBitCount = 342, + OpGroupNonUniformBallotFindLSB = 343, + OpGroupNonUniformBallotFindMSB = 344, + OpGroupNonUniformShuffle = 345, + OpGroupNonUniformShuffleXor = 346, + OpGroupNonUniformShuffleUp = 347, + OpGroupNonUniformShuffleDown = 348, + OpGroupNonUniformIAdd = 349, + OpGroupNonUniformFAdd = 350, + OpGroupNonUniformIMul = 351, + OpGroupNonUniformFMul = 352, + OpGroupNonUniformSMin = 353, + OpGroupNonUniformUMin = 354, + OpGroupNonUniformFMin = 355, + OpGroupNonUniformSMax = 356, + OpGroupNonUniformUMax = 357, + OpGroupNonUniformFMax = 358, + OpGroupNonUniformBitwiseAnd = 359, + OpGroupNonUniformBitwiseOr = 360, + OpGroupNonUniformBitwiseXor = 361, + OpGroupNonUniformLogicalAnd = 362, + OpGroupNonUniformLogicalOr = 363, + OpGroupNonUniformLogicalXor = 364, + OpGroupNonUniformQuadBroadcast = 365, + OpGroupNonUniformQuadSwap = 366, + OpCopyLogical = 400, + OpPtrEqual = 401, + OpPtrNotEqual = 402, + OpPtrDiff = 403, + OpSubgroupBallotKHR = 4421, + OpSubgroupFirstInvocationKHR = 4422, + OpSubgroupAllKHR = 4428, + OpSubgroupAnyKHR = 4429, + OpSubgroupAllEqualKHR = 4430, + OpSubgroupReadInvocationKHR = 4432, + OpTypeRayQueryProvisionalKHR = 4472, + OpRayQueryInitializeKHR = 4473, + OpRayQueryTerminateKHR = 4474, + OpRayQueryGenerateIntersectionKHR = 4475, + OpRayQueryConfirmIntersectionKHR = 4476, + OpRayQueryProceedKHR = 4477, + OpRayQueryGetIntersectionTypeKHR = 4479, + OpGroupIAddNonUniformAMD = 5000, + OpGroupFAddNonUniformAMD = 5001, + OpGroupFMinNonUniformAMD = 5002, + OpGroupUMinNonUniformAMD = 5003, + OpGroupSMinNonUniformAMD = 5004, + OpGroupFMaxNonUniformAMD = 5005, + OpGroupUMaxNonUniformAMD = 5006, + OpGroupSMaxNonUniformAMD = 5007, + OpFragmentMaskFetchAMD = 5011, + OpFragmentFetchAMD = 5012, + OpReadClockKHR = 5056, + OpImageSampleFootprintNV = 5283, + OpGroupNonUniformPartitionNV = 5296, + OpWritePackedPrimitiveIndices4x8NV = 5299, + OpReportIntersectionKHR = 5334, + OpReportIntersectionNV = 5334, + OpIgnoreIntersectionKHR = 5335, + OpIgnoreIntersectionNV = 5335, + OpTerminateRayKHR = 5336, + OpTerminateRayNV = 5336, + OpTraceNV = 5337, + OpTraceRayKHR = 5337, + OpTypeAccelerationStructureKHR = 5341, + OpTypeAccelerationStructureNV = 5341, + OpExecuteCallableKHR = 5344, + OpExecuteCallableNV = 5344, + OpTypeCooperativeMatrixNV = 5358, + OpCooperativeMatrixLoadNV = 5359, + OpCooperativeMatrixStoreNV = 5360, + OpCooperativeMatrixMulAddNV = 5361, + OpCooperativeMatrixLengthNV = 5362, + OpBeginInvocationInterlockEXT = 5364, + OpEndInvocationInterlockEXT = 5365, + OpDemoteToHelperInvocationEXT = 5380, + OpIsHelperInvocationEXT = 5381, + OpSubgroupShuffleINTEL = 5571, + OpSubgroupShuffleDownINTEL = 5572, + OpSubgroupShuffleUpINTEL = 5573, + OpSubgroupShuffleXorINTEL = 5574, + OpSubgroupBlockReadINTEL = 5575, + OpSubgroupBlockWriteINTEL = 5576, + OpSubgroupImageBlockReadINTEL = 5577, + OpSubgroupImageBlockWriteINTEL = 5578, + OpSubgroupImageMediaBlockReadINTEL = 5580, + OpSubgroupImageMediaBlockWriteINTEL = 5581, + OpUCountLeadingZerosINTEL = 5585, + OpUCountTrailingZerosINTEL = 5586, + OpAbsISubINTEL = 5587, + OpAbsUSubINTEL = 5588, + OpIAddSatINTEL = 5589, + OpUAddSatINTEL = 5590, + OpIAverageINTEL = 5591, + OpUAverageINTEL = 5592, + OpIAverageRoundedINTEL = 5593, + OpUAverageRoundedINTEL = 5594, + OpISubSatINTEL = 5595, + OpUSubSatINTEL = 5596, + OpIMul32x16INTEL = 5597, + OpUMul32x16INTEL = 5598, + OpDecorateString = 5632, + OpDecorateStringGOOGLE = 5632, + OpMemberDecorateString = 5633, + OpMemberDecorateStringGOOGLE = 5633, + OpVmeImageINTEL = 5699, + OpTypeVmeImageINTEL = 5700, + OpTypeAvcImePayloadINTEL = 5701, + OpTypeAvcRefPayloadINTEL = 5702, + OpTypeAvcSicPayloadINTEL = 5703, + OpTypeAvcMcePayloadINTEL = 5704, + OpTypeAvcMceResultINTEL = 5705, + OpTypeAvcImeResultINTEL = 5706, + OpTypeAvcImeResultSingleReferenceStreamoutINTEL = 5707, + OpTypeAvcImeResultDualReferenceStreamoutINTEL = 5708, + OpTypeAvcImeSingleReferenceStreaminINTEL = 5709, + OpTypeAvcImeDualReferenceStreaminINTEL = 5710, + OpTypeAvcRefResultINTEL = 5711, + OpTypeAvcSicResultINTEL = 5712, + OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL = 5713, + OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL = 5714, + OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL = 5715, + OpSubgroupAvcMceSetInterShapePenaltyINTEL = 5716, + OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL = 5717, + OpSubgroupAvcMceSetInterDirectionPenaltyINTEL = 5718, + OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL = 5719, + OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL = 5720, + OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL = 5721, + OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL = 5722, + OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL = 5723, + OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL = 5724, + OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL = 5725, + OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL = 5726, + OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL = 5727, + OpSubgroupAvcMceSetAcOnlyHaarINTEL = 5728, + OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL = 5729, + OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL = 5730, + OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL = 5731, + OpSubgroupAvcMceConvertToImePayloadINTEL = 5732, + OpSubgroupAvcMceConvertToImeResultINTEL = 5733, + OpSubgroupAvcMceConvertToRefPayloadINTEL = 5734, + OpSubgroupAvcMceConvertToRefResultINTEL = 5735, + OpSubgroupAvcMceConvertToSicPayloadINTEL = 5736, + OpSubgroupAvcMceConvertToSicResultINTEL = 5737, + OpSubgroupAvcMceGetMotionVectorsINTEL = 5738, + OpSubgroupAvcMceGetInterDistortionsINTEL = 5739, + OpSubgroupAvcMceGetBestInterDistortionsINTEL = 5740, + OpSubgroupAvcMceGetInterMajorShapeINTEL = 5741, + OpSubgroupAvcMceGetInterMinorShapeINTEL = 5742, + OpSubgroupAvcMceGetInterDirectionsINTEL = 5743, + OpSubgroupAvcMceGetInterMotionVectorCountINTEL = 5744, + OpSubgroupAvcMceGetInterReferenceIdsINTEL = 5745, + OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL = 5746, + OpSubgroupAvcImeInitializeINTEL = 5747, + OpSubgroupAvcImeSetSingleReferenceINTEL = 5748, + OpSubgroupAvcImeSetDualReferenceINTEL = 5749, + OpSubgroupAvcImeRefWindowSizeINTEL = 5750, + OpSubgroupAvcImeAdjustRefOffsetINTEL = 5751, + OpSubgroupAvcImeConvertToMcePayloadINTEL = 5752, + OpSubgroupAvcImeSetMaxMotionVectorCountINTEL = 5753, + OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL = 5754, + OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL = 5755, + OpSubgroupAvcImeSetWeightedSadINTEL = 5756, + OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL = 5757, + OpSubgroupAvcImeEvaluateWithDualReferenceINTEL = 5758, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL = 5759, + OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL = 5760, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL = 5761, + OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL = 5762, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL = 5763, + OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL = 5764, + OpSubgroupAvcImeConvertToMceResultINTEL = 5765, + OpSubgroupAvcImeGetSingleReferenceStreaminINTEL = 5766, + OpSubgroupAvcImeGetDualReferenceStreaminINTEL = 5767, + OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL = 5768, + OpSubgroupAvcImeStripDualReferenceStreamoutINTEL = 5769, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL = 5770, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL = 5771, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL = 5772, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL = 5773, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL = 5774, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL = 5775, + OpSubgroupAvcImeGetBorderReachedINTEL = 5776, + OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL = 5777, + OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL = 5778, + OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL = 5779, + OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL = 5780, + OpSubgroupAvcFmeInitializeINTEL = 5781, + OpSubgroupAvcBmeInitializeINTEL = 5782, + OpSubgroupAvcRefConvertToMcePayloadINTEL = 5783, + OpSubgroupAvcRefSetBidirectionalMixDisableINTEL = 5784, + OpSubgroupAvcRefSetBilinearFilterEnableINTEL = 5785, + OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL = 5786, + OpSubgroupAvcRefEvaluateWithDualReferenceINTEL = 5787, + OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL = 5788, + OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL = 5789, + OpSubgroupAvcRefConvertToMceResultINTEL = 5790, + OpSubgroupAvcSicInitializeINTEL = 5791, + OpSubgroupAvcSicConfigureSkcINTEL = 5792, + OpSubgroupAvcSicConfigureIpeLumaINTEL = 5793, + OpSubgroupAvcSicConfigureIpeLumaChromaINTEL = 5794, + OpSubgroupAvcSicGetMotionVectorMaskINTEL = 5795, + OpSubgroupAvcSicConvertToMcePayloadINTEL = 5796, + OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL = 5797, + OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL = 5798, + OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL = 5799, + OpSubgroupAvcSicSetBilinearFilterEnableINTEL = 5800, + OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL = 5801, + OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL = 5802, + OpSubgroupAvcSicEvaluateIpeINTEL = 5803, + OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL = 5804, + OpSubgroupAvcSicEvaluateWithDualReferenceINTEL = 5805, + OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL = 5806, + OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL = 5807, + OpSubgroupAvcSicConvertToMceResultINTEL = 5808, + OpSubgroupAvcSicGetIpeLumaShapeINTEL = 5809, + OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL = 5810, + OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL = 5811, + OpSubgroupAvcSicGetPackedIpeLumaModesINTEL = 5812, + OpSubgroupAvcSicGetIpeChromaModeINTEL = 5813, + OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, + OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, + OpSubgroupAvcSicGetInterRawSadsINTEL = 5816, + OpRayQueryGetRayTMinKHR = 6016, + OpRayQueryGetRayFlagsKHR = 6017, + OpRayQueryGetIntersectionTKHR = 6018, + OpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019, + OpRayQueryGetIntersectionInstanceIdKHR = 6020, + OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021, + OpRayQueryGetIntersectionGeometryIndexKHR = 6022, + OpRayQueryGetIntersectionPrimitiveIndexKHR = 6023, + OpRayQueryGetIntersectionBarycentricsKHR = 6024, + OpRayQueryGetIntersectionFrontFaceKHR = 6025, + OpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026, + OpRayQueryGetIntersectionObjectRayDirectionKHR = 6027, + OpRayQueryGetIntersectionObjectRayOriginKHR = 6028, + OpRayQueryGetWorldRayDirectionKHR = 6029, + OpRayQueryGetWorldRayOriginKHR = 6030, + OpRayQueryGetIntersectionObjectToWorldKHR = 6031, + OpRayQueryGetIntersectionWorldToObjectKHR = 6032, + OpMax = 0x7fffffff, +}; + +#ifdef SPV_ENABLE_UTILITY_CODE +inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) { + *hasResult = *hasResultType = false; + switch (opcode) { + default: /* unknown opcode */ break; + case OpNop: *hasResult = false; *hasResultType = false; break; + case OpUndef: *hasResult = true; *hasResultType = true; break; + case OpSourceContinued: *hasResult = false; *hasResultType = false; break; + case OpSource: *hasResult = false; *hasResultType = false; break; + case OpSourceExtension: *hasResult = false; *hasResultType = false; break; + case OpName: *hasResult = false; *hasResultType = false; break; + case OpMemberName: *hasResult = false; *hasResultType = false; break; + case OpString: *hasResult = true; *hasResultType = false; break; + case OpLine: *hasResult = false; *hasResultType = false; break; + case OpExtension: *hasResult = false; *hasResultType = false; break; + case OpExtInstImport: *hasResult = true; *hasResultType = false; break; + case OpExtInst: *hasResult = true; *hasResultType = true; break; + case OpMemoryModel: *hasResult = false; *hasResultType = false; break; + case OpEntryPoint: *hasResult = false; *hasResultType = false; break; + case OpExecutionMode: *hasResult = false; *hasResultType = false; break; + case OpCapability: *hasResult = false; *hasResultType = false; break; + case OpTypeVoid: *hasResult = true; *hasResultType = false; break; + case OpTypeBool: *hasResult = true; *hasResultType = false; break; + case OpTypeInt: *hasResult = true; *hasResultType = false; break; + case OpTypeFloat: *hasResult = true; *hasResultType = false; break; + case OpTypeVector: *hasResult = true; *hasResultType = false; break; + case OpTypeMatrix: *hasResult = true; *hasResultType = false; break; + case OpTypeImage: *hasResult = true; *hasResultType = false; break; + case OpTypeSampler: *hasResult = true; *hasResultType = false; break; + case OpTypeSampledImage: *hasResult = true; *hasResultType = false; break; + case OpTypeArray: *hasResult = true; *hasResultType = false; break; + case OpTypeRuntimeArray: *hasResult = true; *hasResultType = false; break; + case OpTypeStruct: *hasResult = true; *hasResultType = false; break; + case OpTypeOpaque: *hasResult = true; *hasResultType = false; break; + case OpTypePointer: *hasResult = true; *hasResultType = false; break; + case OpTypeFunction: *hasResult = true; *hasResultType = false; break; + case OpTypeEvent: *hasResult = true; *hasResultType = false; break; + case OpTypeDeviceEvent: *hasResult = true; *hasResultType = false; break; + case OpTypeReserveId: *hasResult = true; *hasResultType = false; break; + case OpTypeQueue: *hasResult = true; *hasResultType = false; break; + case OpTypePipe: *hasResult = true; *hasResultType = false; break; + case OpTypeForwardPointer: *hasResult = false; *hasResultType = false; break; + case OpConstantTrue: *hasResult = true; *hasResultType = true; break; + case OpConstantFalse: *hasResult = true; *hasResultType = true; break; + case OpConstant: *hasResult = true; *hasResultType = true; break; + case OpConstantComposite: *hasResult = true; *hasResultType = true; break; + case OpConstantSampler: *hasResult = true; *hasResultType = true; break; + case OpConstantNull: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantTrue: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantFalse: *hasResult = true; *hasResultType = true; break; + case OpSpecConstant: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantComposite: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantOp: *hasResult = true; *hasResultType = true; break; + case OpFunction: *hasResult = true; *hasResultType = true; break; + case OpFunctionParameter: *hasResult = true; *hasResultType = true; break; + case OpFunctionEnd: *hasResult = false; *hasResultType = false; break; + case OpFunctionCall: *hasResult = true; *hasResultType = true; break; + case OpVariable: *hasResult = true; *hasResultType = true; break; + case OpImageTexelPointer: *hasResult = true; *hasResultType = true; break; + case OpLoad: *hasResult = true; *hasResultType = true; break; + case OpStore: *hasResult = false; *hasResultType = false; break; + case OpCopyMemory: *hasResult = false; *hasResultType = false; break; + case OpCopyMemorySized: *hasResult = false; *hasResultType = false; break; + case OpAccessChain: *hasResult = true; *hasResultType = true; break; + case OpInBoundsAccessChain: *hasResult = true; *hasResultType = true; break; + case OpPtrAccessChain: *hasResult = true; *hasResultType = true; break; + case OpArrayLength: *hasResult = true; *hasResultType = true; break; + case OpGenericPtrMemSemantics: *hasResult = true; *hasResultType = true; break; + case OpInBoundsPtrAccessChain: *hasResult = true; *hasResultType = true; break; + case OpDecorate: *hasResult = false; *hasResultType = false; break; + case OpMemberDecorate: *hasResult = false; *hasResultType = false; break; + case OpDecorationGroup: *hasResult = true; *hasResultType = false; break; + case OpGroupDecorate: *hasResult = false; *hasResultType = false; break; + case OpGroupMemberDecorate: *hasResult = false; *hasResultType = false; break; + case OpVectorExtractDynamic: *hasResult = true; *hasResultType = true; break; + case OpVectorInsertDynamic: *hasResult = true; *hasResultType = true; break; + case OpVectorShuffle: *hasResult = true; *hasResultType = true; break; + case OpCompositeConstruct: *hasResult = true; *hasResultType = true; break; + case OpCompositeExtract: *hasResult = true; *hasResultType = true; break; + case OpCompositeInsert: *hasResult = true; *hasResultType = true; break; + case OpCopyObject: *hasResult = true; *hasResultType = true; break; + case OpTranspose: *hasResult = true; *hasResultType = true; break; + case OpSampledImage: *hasResult = true; *hasResultType = true; break; + case OpImageSampleImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageFetch: *hasResult = true; *hasResultType = true; break; + case OpImageGather: *hasResult = true; *hasResultType = true; break; + case OpImageDrefGather: *hasResult = true; *hasResultType = true; break; + case OpImageRead: *hasResult = true; *hasResultType = true; break; + case OpImageWrite: *hasResult = false; *hasResultType = false; break; + case OpImage: *hasResult = true; *hasResultType = true; break; + case OpImageQueryFormat: *hasResult = true; *hasResultType = true; break; + case OpImageQueryOrder: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySizeLod: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySize: *hasResult = true; *hasResultType = true; break; + case OpImageQueryLod: *hasResult = true; *hasResultType = true; break; + case OpImageQueryLevels: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySamples: *hasResult = true; *hasResultType = true; break; + case OpConvertFToU: *hasResult = true; *hasResultType = true; break; + case OpConvertFToS: *hasResult = true; *hasResultType = true; break; + case OpConvertSToF: *hasResult = true; *hasResultType = true; break; + case OpConvertUToF: *hasResult = true; *hasResultType = true; break; + case OpUConvert: *hasResult = true; *hasResultType = true; break; + case OpSConvert: *hasResult = true; *hasResultType = true; break; + case OpFConvert: *hasResult = true; *hasResultType = true; break; + case OpQuantizeToF16: *hasResult = true; *hasResultType = true; break; + case OpConvertPtrToU: *hasResult = true; *hasResultType = true; break; + case OpSatConvertSToU: *hasResult = true; *hasResultType = true; break; + case OpSatConvertUToS: *hasResult = true; *hasResultType = true; break; + case OpConvertUToPtr: *hasResult = true; *hasResultType = true; break; + case OpPtrCastToGeneric: *hasResult = true; *hasResultType = true; break; + case OpGenericCastToPtr: *hasResult = true; *hasResultType = true; break; + case OpGenericCastToPtrExplicit: *hasResult = true; *hasResultType = true; break; + case OpBitcast: *hasResult = true; *hasResultType = true; break; + case OpSNegate: *hasResult = true; *hasResultType = true; break; + case OpFNegate: *hasResult = true; *hasResultType = true; break; + case OpIAdd: *hasResult = true; *hasResultType = true; break; + case OpFAdd: *hasResult = true; *hasResultType = true; break; + case OpISub: *hasResult = true; *hasResultType = true; break; + case OpFSub: *hasResult = true; *hasResultType = true; break; + case OpIMul: *hasResult = true; *hasResultType = true; break; + case OpFMul: *hasResult = true; *hasResultType = true; break; + case OpUDiv: *hasResult = true; *hasResultType = true; break; + case OpSDiv: *hasResult = true; *hasResultType = true; break; + case OpFDiv: *hasResult = true; *hasResultType = true; break; + case OpUMod: *hasResult = true; *hasResultType = true; break; + case OpSRem: *hasResult = true; *hasResultType = true; break; + case OpSMod: *hasResult = true; *hasResultType = true; break; + case OpFRem: *hasResult = true; *hasResultType = true; break; + case OpFMod: *hasResult = true; *hasResultType = true; break; + case OpVectorTimesScalar: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesScalar: *hasResult = true; *hasResultType = true; break; + case OpVectorTimesMatrix: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesVector: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesMatrix: *hasResult = true; *hasResultType = true; break; + case OpOuterProduct: *hasResult = true; *hasResultType = true; break; + case OpDot: *hasResult = true; *hasResultType = true; break; + case OpIAddCarry: *hasResult = true; *hasResultType = true; break; + case OpISubBorrow: *hasResult = true; *hasResultType = true; break; + case OpUMulExtended: *hasResult = true; *hasResultType = true; break; + case OpSMulExtended: *hasResult = true; *hasResultType = true; break; + case OpAny: *hasResult = true; *hasResultType = true; break; + case OpAll: *hasResult = true; *hasResultType = true; break; + case OpIsNan: *hasResult = true; *hasResultType = true; break; + case OpIsInf: *hasResult = true; *hasResultType = true; break; + case OpIsFinite: *hasResult = true; *hasResultType = true; break; + case OpIsNormal: *hasResult = true; *hasResultType = true; break; + case OpSignBitSet: *hasResult = true; *hasResultType = true; break; + case OpLessOrGreater: *hasResult = true; *hasResultType = true; break; + case OpOrdered: *hasResult = true; *hasResultType = true; break; + case OpUnordered: *hasResult = true; *hasResultType = true; break; + case OpLogicalEqual: *hasResult = true; *hasResultType = true; break; + case OpLogicalNotEqual: *hasResult = true; *hasResultType = true; break; + case OpLogicalOr: *hasResult = true; *hasResultType = true; break; + case OpLogicalAnd: *hasResult = true; *hasResultType = true; break; + case OpLogicalNot: *hasResult = true; *hasResultType = true; break; + case OpSelect: *hasResult = true; *hasResultType = true; break; + case OpIEqual: *hasResult = true; *hasResultType = true; break; + case OpINotEqual: *hasResult = true; *hasResultType = true; break; + case OpUGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpSGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpUGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpSGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpULessThan: *hasResult = true; *hasResultType = true; break; + case OpSLessThan: *hasResult = true; *hasResultType = true; break; + case OpULessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpSLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdNotEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordNotEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdLessThan: *hasResult = true; *hasResultType = true; break; + case OpFUnordLessThan: *hasResult = true; *hasResultType = true; break; + case OpFOrdGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpFUnordGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpFOrdLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpShiftRightLogical: *hasResult = true; *hasResultType = true; break; + case OpShiftRightArithmetic: *hasResult = true; *hasResultType = true; break; + case OpShiftLeftLogical: *hasResult = true; *hasResultType = true; break; + case OpBitwiseOr: *hasResult = true; *hasResultType = true; break; + case OpBitwiseXor: *hasResult = true; *hasResultType = true; break; + case OpBitwiseAnd: *hasResult = true; *hasResultType = true; break; + case OpNot: *hasResult = true; *hasResultType = true; break; + case OpBitFieldInsert: *hasResult = true; *hasResultType = true; break; + case OpBitFieldSExtract: *hasResult = true; *hasResultType = true; break; + case OpBitFieldUExtract: *hasResult = true; *hasResultType = true; break; + case OpBitReverse: *hasResult = true; *hasResultType = true; break; + case OpBitCount: *hasResult = true; *hasResultType = true; break; + case OpDPdx: *hasResult = true; *hasResultType = true; break; + case OpDPdy: *hasResult = true; *hasResultType = true; break; + case OpFwidth: *hasResult = true; *hasResultType = true; break; + case OpDPdxFine: *hasResult = true; *hasResultType = true; break; + case OpDPdyFine: *hasResult = true; *hasResultType = true; break; + case OpFwidthFine: *hasResult = true; *hasResultType = true; break; + case OpDPdxCoarse: *hasResult = true; *hasResultType = true; break; + case OpDPdyCoarse: *hasResult = true; *hasResultType = true; break; + case OpFwidthCoarse: *hasResult = true; *hasResultType = true; break; + case OpEmitVertex: *hasResult = false; *hasResultType = false; break; + case OpEndPrimitive: *hasResult = false; *hasResultType = false; break; + case OpEmitStreamVertex: *hasResult = false; *hasResultType = false; break; + case OpEndStreamPrimitive: *hasResult = false; *hasResultType = false; break; + case OpControlBarrier: *hasResult = false; *hasResultType = false; break; + case OpMemoryBarrier: *hasResult = false; *hasResultType = false; break; + case OpAtomicLoad: *hasResult = true; *hasResultType = true; break; + case OpAtomicStore: *hasResult = false; *hasResultType = false; break; + case OpAtomicExchange: *hasResult = true; *hasResultType = true; break; + case OpAtomicCompareExchange: *hasResult = true; *hasResultType = true; break; + case OpAtomicCompareExchangeWeak: *hasResult = true; *hasResultType = true; break; + case OpAtomicIIncrement: *hasResult = true; *hasResultType = true; break; + case OpAtomicIDecrement: *hasResult = true; *hasResultType = true; break; + case OpAtomicIAdd: *hasResult = true; *hasResultType = true; break; + case OpAtomicISub: *hasResult = true; *hasResultType = true; break; + case OpAtomicSMin: *hasResult = true; *hasResultType = true; break; + case OpAtomicUMin: *hasResult = true; *hasResultType = true; break; + case OpAtomicSMax: *hasResult = true; *hasResultType = true; break; + case OpAtomicUMax: *hasResult = true; *hasResultType = true; break; + case OpAtomicAnd: *hasResult = true; *hasResultType = true; break; + case OpAtomicOr: *hasResult = true; *hasResultType = true; break; + case OpAtomicXor: *hasResult = true; *hasResultType = true; break; + case OpPhi: *hasResult = true; *hasResultType = true; break; + case OpLoopMerge: *hasResult = false; *hasResultType = false; break; + case OpSelectionMerge: *hasResult = false; *hasResultType = false; break; + case OpLabel: *hasResult = true; *hasResultType = false; break; + case OpBranch: *hasResult = false; *hasResultType = false; break; + case OpBranchConditional: *hasResult = false; *hasResultType = false; break; + case OpSwitch: *hasResult = false; *hasResultType = false; break; + case OpKill: *hasResult = false; *hasResultType = false; break; + case OpReturn: *hasResult = false; *hasResultType = false; break; + case OpReturnValue: *hasResult = false; *hasResultType = false; break; + case OpUnreachable: *hasResult = false; *hasResultType = false; break; + case OpLifetimeStart: *hasResult = false; *hasResultType = false; break; + case OpLifetimeStop: *hasResult = false; *hasResultType = false; break; + case OpGroupAsyncCopy: *hasResult = true; *hasResultType = true; break; + case OpGroupWaitEvents: *hasResult = false; *hasResultType = false; break; + case OpGroupAll: *hasResult = true; *hasResultType = true; break; + case OpGroupAny: *hasResult = true; *hasResultType = true; break; + case OpGroupBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupIAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupFAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupFMin: *hasResult = true; *hasResultType = true; break; + case OpGroupUMin: *hasResult = true; *hasResultType = true; break; + case OpGroupSMin: *hasResult = true; *hasResultType = true; break; + case OpGroupFMax: *hasResult = true; *hasResultType = true; break; + case OpGroupUMax: *hasResult = true; *hasResultType = true; break; + case OpGroupSMax: *hasResult = true; *hasResultType = true; break; + case OpReadPipe: *hasResult = true; *hasResultType = true; break; + case OpWritePipe: *hasResult = true; *hasResultType = true; break; + case OpReservedReadPipe: *hasResult = true; *hasResultType = true; break; + case OpReservedWritePipe: *hasResult = true; *hasResultType = true; break; + case OpReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; + case OpReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; + case OpCommitReadPipe: *hasResult = false; *hasResultType = false; break; + case OpCommitWritePipe: *hasResult = false; *hasResultType = false; break; + case OpIsValidReserveId: *hasResult = true; *hasResultType = true; break; + case OpGetNumPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGetMaxPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupCommitReadPipe: *hasResult = false; *hasResultType = false; break; + case OpGroupCommitWritePipe: *hasResult = false; *hasResultType = false; break; + case OpEnqueueMarker: *hasResult = true; *hasResultType = true; break; + case OpEnqueueKernel: *hasResult = true; *hasResultType = true; break; + case OpGetKernelNDrangeSubGroupCount: *hasResult = true; *hasResultType = true; break; + case OpGetKernelNDrangeMaxSubGroupSize: *hasResult = true; *hasResultType = true; break; + case OpGetKernelWorkGroupSize: *hasResult = true; *hasResultType = true; break; + case OpGetKernelPreferredWorkGroupSizeMultiple: *hasResult = true; *hasResultType = true; break; + case OpRetainEvent: *hasResult = false; *hasResultType = false; break; + case OpReleaseEvent: *hasResult = false; *hasResultType = false; break; + case OpCreateUserEvent: *hasResult = true; *hasResultType = true; break; + case OpIsValidEvent: *hasResult = true; *hasResultType = true; break; + case OpSetUserEventStatus: *hasResult = false; *hasResultType = false; break; + case OpCaptureEventProfilingInfo: *hasResult = false; *hasResultType = false; break; + case OpGetDefaultQueue: *hasResult = true; *hasResultType = true; break; + case OpBuildNDRange: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseFetch: *hasResult = true; *hasResultType = true; break; + case OpImageSparseGather: *hasResult = true; *hasResultType = true; break; + case OpImageSparseDrefGather: *hasResult = true; *hasResultType = true; break; + case OpImageSparseTexelsResident: *hasResult = true; *hasResultType = true; break; + case OpNoLine: *hasResult = false; *hasResultType = false; break; + case OpAtomicFlagTestAndSet: *hasResult = true; *hasResultType = true; break; + case OpAtomicFlagClear: *hasResult = false; *hasResultType = false; break; + case OpImageSparseRead: *hasResult = true; *hasResultType = true; break; + case OpSizeOf: *hasResult = true; *hasResultType = true; break; + case OpTypePipeStorage: *hasResult = true; *hasResultType = false; break; + case OpConstantPipeStorage: *hasResult = true; *hasResultType = true; break; + case OpCreatePipeFromPipeStorage: *hasResult = true; *hasResultType = true; break; + case OpGetKernelLocalSizeForSubgroupCount: *hasResult = true; *hasResultType = true; break; + case OpGetKernelMaxNumSubgroups: *hasResult = true; *hasResultType = true; break; + case OpTypeNamedBarrier: *hasResult = true; *hasResultType = false; break; + case OpNamedBarrierInitialize: *hasResult = true; *hasResultType = true; break; + case OpMemoryNamedBarrier: *hasResult = false; *hasResultType = false; break; + case OpModuleProcessed: *hasResult = false; *hasResultType = false; break; + case OpExecutionModeId: *hasResult = false; *hasResultType = false; break; + case OpDecorateId: *hasResult = false; *hasResultType = false; break; + case OpGroupNonUniformElect: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAll: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAny: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAllEqual: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBroadcastFirst: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallot: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformInverseBallot: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotBitExtract: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotBitCount: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotFindLSB: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotFindMSB: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffle: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleUp: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleDown: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformIAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformIMul: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMul: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformSMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformUMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformSMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformUMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseAnd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseOr: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalAnd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalOr: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformQuadBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformQuadSwap: *hasResult = true; *hasResultType = true; break; + case OpCopyLogical: *hasResult = true; *hasResultType = true; break; + case OpPtrEqual: *hasResult = true; *hasResultType = true; break; + case OpPtrNotEqual: *hasResult = true; *hasResultType = true; break; + case OpPtrDiff: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break; + case OpTypeRayQueryProvisionalKHR: *hasResult = true; *hasResultType = false; break; + case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break; + case OpGroupIAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupUMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupSMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupUMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupSMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpFragmentMaskFetchAMD: *hasResult = true; *hasResultType = true; break; + case OpFragmentFetchAMD: *hasResult = true; *hasResultType = true; break; + case OpReadClockKHR: *hasResult = true; *hasResultType = true; break; + case OpImageSampleFootprintNV: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformPartitionNV: *hasResult = true; *hasResultType = true; break; + case OpWritePackedPrimitiveIndices4x8NV: *hasResult = false; *hasResultType = false; break; + case OpReportIntersectionNV: *hasResult = true; *hasResultType = true; break; + case OpIgnoreIntersectionNV: *hasResult = false; *hasResultType = false; break; + case OpTerminateRayNV: *hasResult = false; *hasResultType = false; break; + case OpTraceNV: *hasResult = false; *hasResultType = false; break; + case OpTypeAccelerationStructureNV: *hasResult = true; *hasResultType = false; break; + case OpExecuteCallableNV: *hasResult = false; *hasResultType = false; break; + case OpTypeCooperativeMatrixNV: *hasResult = true; *hasResultType = false; break; + case OpCooperativeMatrixLoadNV: *hasResult = true; *hasResultType = true; break; + case OpCooperativeMatrixStoreNV: *hasResult = false; *hasResultType = false; break; + case OpCooperativeMatrixMulAddNV: *hasResult = true; *hasResultType = true; break; + case OpCooperativeMatrixLengthNV: *hasResult = true; *hasResultType = true; break; + case OpBeginInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; + case OpEndInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; + case OpDemoteToHelperInvocationEXT: *hasResult = false; *hasResultType = false; break; + case OpIsHelperInvocationEXT: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleDownINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleUpINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleXorINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpSubgroupImageBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupImageBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpSubgroupImageMediaBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupImageMediaBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpUCountLeadingZerosINTEL: *hasResult = true; *hasResultType = true; break; + case OpUCountTrailingZerosINTEL: *hasResult = true; *hasResultType = true; break; + case OpAbsISubINTEL: *hasResult = true; *hasResultType = true; break; + case OpAbsUSubINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAddSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAddSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAverageINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAverageINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; + case OpISubSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break; + case OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break; + case OpDecorateString: *hasResult = false; *hasResultType = false; break; + case OpMemberDecorateString: *hasResult = false; *hasResultType = false; break; + case OpVmeImageINTEL: *hasResult = true; *hasResultType = true; break; + case OpTypeVmeImageINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImePayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcRefPayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcSicPayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcMcePayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcMceResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcRefResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcSicResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetAcOnlyHaarINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToImePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToImeResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToRefPayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToRefResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToSicPayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToSicResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetBestInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMajorShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMinorShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterDirectionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeRefWindowSizeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeAdjustRefOffsetINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetMaxMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetWeightedSadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeStripDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetBorderReachedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcFmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcBmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefSetBidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureSkcINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureIpeLumaINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureIpeLumaChromaINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetMotionVectorMaskINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateIpeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetIpeLumaShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedIpeLumaModesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetIpeChromaModeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetRayTMinKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetRayFlagsKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionTKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceCustomIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceIdKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionGeometryIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionPrimitiveIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionBarycentricsKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionFrontFaceKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetWorldRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetWorldRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break; + } +} +#endif /* SPV_ENABLE_UTILITY_CODE */ + +// Overload operator| for mask bit combining + +inline ImageOperandsMask operator|(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) | unsigned(b)); } +inline FPFastMathModeMask operator|(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) | unsigned(b)); } +inline SelectionControlMask operator|(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) | unsigned(b)); } +inline LoopControlMask operator|(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) | unsigned(b)); } +inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) | unsigned(b)); } +inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); } +inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); } +inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); } +inline RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); } + +} // end namespace spv + +#endif // #ifndef spirv_HPP + diff --git a/android/arm64-v8a/include/glslang/glslang/SPIRV/spvIR.h b/android/arm64-v8a/include/glslang/glslang/SPIRV/spvIR.h new file mode 100644 index 00000000..6523035e --- /dev/null +++ b/android/arm64-v8a/include/glslang/glslang/SPIRV/spvIR.h @@ -0,0 +1,485 @@ +// +// Copyright (C) 2014 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// SPIRV-IR +// +// Simple in-memory representation (IR) of SPIRV. Just for holding +// Each function's CFG of blocks. Has this hierarchy: +// - Module, which is a list of +// - Function, which is a list of +// - Block, which is a list of +// - Instruction +// + +#pragma once +#ifndef spvIR_H +#define spvIR_H + +#include "spirv.hpp" + +#include +#include +#include +#include +#include +#include + +namespace spv { + +class Block; +class Function; +class Module; + +const Id NoResult = 0; +const Id NoType = 0; + +const Decoration NoPrecision = DecorationMax; + +#ifdef __GNUC__ +# define POTENTIALLY_UNUSED __attribute__((unused)) +#else +# define POTENTIALLY_UNUSED +#endif + +POTENTIALLY_UNUSED +const MemorySemanticsMask MemorySemanticsAllMemory = + (MemorySemanticsMask)(MemorySemanticsUniformMemoryMask | + MemorySemanticsWorkgroupMemoryMask | + MemorySemanticsAtomicCounterMemoryMask | + MemorySemanticsImageMemoryMask); + +struct IdImmediate { + bool isId; // true if word is an Id, false if word is an immediate + unsigned word; + IdImmediate(bool i, unsigned w) : isId(i), word(w) {} +}; + +// +// SPIR-V IR instruction. +// + +class Instruction { +public: + Instruction(Id resultId, Id typeId, Op opCode) : resultId(resultId), typeId(typeId), opCode(opCode), block(nullptr) { } + explicit Instruction(Op opCode) : resultId(NoResult), typeId(NoType), opCode(opCode), block(nullptr) { } + virtual ~Instruction() {} + void addIdOperand(Id id) { + operands.push_back(id); + idOperand.push_back(true); + } + void addImmediateOperand(unsigned int immediate) { + operands.push_back(immediate); + idOperand.push_back(false); + } + void setImmediateOperand(unsigned idx, unsigned int immediate) { + assert(!idOperand[idx]); + operands[idx] = immediate; + } + + void addStringOperand(const char* str) + { + unsigned int word; + char* wordString = (char*)&word; + char* wordPtr = wordString; + int charCount = 0; + char c; + do { + c = *(str++); + *(wordPtr++) = c; + ++charCount; + if (charCount == 4) { + addImmediateOperand(word); + wordPtr = wordString; + charCount = 0; + } + } while (c != 0); + + // deal with partial last word + if (charCount > 0) { + // pad with 0s + for (; charCount < 4; ++charCount) + *(wordPtr++) = 0; + addImmediateOperand(word); + } + } + bool isIdOperand(int op) const { return idOperand[op]; } + void setBlock(Block* b) { block = b; } + Block* getBlock() const { return block; } + Op getOpCode() const { return opCode; } + int getNumOperands() const + { + assert(operands.size() == idOperand.size()); + return (int)operands.size(); + } + Id getResultId() const { return resultId; } + Id getTypeId() const { return typeId; } + Id getIdOperand(int op) const { + assert(idOperand[op]); + return operands[op]; + } + unsigned int getImmediateOperand(int op) const { + assert(!idOperand[op]); + return operands[op]; + } + + // Write out the binary form. + void dump(std::vector& out) const + { + // Compute the wordCount + unsigned int wordCount = 1; + if (typeId) + ++wordCount; + if (resultId) + ++wordCount; + wordCount += (unsigned int)operands.size(); + + // Write out the beginning of the instruction + out.push_back(((wordCount) << WordCountShift) | opCode); + if (typeId) + out.push_back(typeId); + if (resultId) + out.push_back(resultId); + + // Write out the operands + for (int op = 0; op < (int)operands.size(); ++op) + out.push_back(operands[op]); + } + +protected: + Instruction(const Instruction&); + Id resultId; + Id typeId; + Op opCode; + std::vector operands; // operands, both and immediates (both are unsigned int) + std::vector idOperand; // true for operands that are , false for immediates + Block* block; +}; + +// +// SPIR-V IR block. +// + +class Block { +public: + Block(Id id, Function& parent); + virtual ~Block() + { + } + + Id getId() { return instructions.front()->getResultId(); } + + Function& getParent() const { return parent; } + void addInstruction(std::unique_ptr inst); + void addPredecessor(Block* pred) { predecessors.push_back(pred); pred->successors.push_back(this);} + void addLocalVariable(std::unique_ptr inst) { localVariables.push_back(std::move(inst)); } + const std::vector& getPredecessors() const { return predecessors; } + const std::vector& getSuccessors() const { return successors; } + const std::vector >& getInstructions() const { + return instructions; + } + const std::vector >& getLocalVariables() const { return localVariables; } + void setUnreachable() { unreachable = true; } + bool isUnreachable() const { return unreachable; } + // Returns the block's merge instruction, if one exists (otherwise null). + const Instruction* getMergeInstruction() const { + if (instructions.size() < 2) return nullptr; + const Instruction* nextToLast = (instructions.cend() - 2)->get(); + switch (nextToLast->getOpCode()) { + case OpSelectionMerge: + case OpLoopMerge: + return nextToLast; + default: + return nullptr; + } + return nullptr; + } + + // Change this block into a canonical dead merge block. Delete instructions + // as necessary. A canonical dead merge block has only an OpLabel and an + // OpUnreachable. + void rewriteAsCanonicalUnreachableMerge() { + assert(localVariables.empty()); + // Delete all instructions except for the label. + assert(instructions.size() > 0); + instructions.resize(1); + successors.clear(); + addInstruction(std::unique_ptr(new Instruction(OpUnreachable))); + } + // Change this block into a canonical dead continue target branching to the + // given header ID. Delete instructions as necessary. A canonical dead continue + // target has only an OpLabel and an unconditional branch back to the corresponding + // header. + void rewriteAsCanonicalUnreachableContinue(Block* header) { + assert(localVariables.empty()); + // Delete all instructions except for the label. + assert(instructions.size() > 0); + instructions.resize(1); + successors.clear(); + // Add OpBranch back to the header. + assert(header != nullptr); + Instruction* branch = new Instruction(OpBranch); + branch->addIdOperand(header->getId()); + addInstruction(std::unique_ptr(branch)); + successors.push_back(header); + } + + bool isTerminated() const + { + switch (instructions.back()->getOpCode()) { + case OpBranch: + case OpBranchConditional: + case OpSwitch: + case OpKill: + case OpReturn: + case OpReturnValue: + case OpUnreachable: + return true; + default: + return false; + } + } + + void dump(std::vector& out) const + { + instructions[0]->dump(out); + for (int i = 0; i < (int)localVariables.size(); ++i) + localVariables[i]->dump(out); + for (int i = 1; i < (int)instructions.size(); ++i) + instructions[i]->dump(out); + } + +protected: + Block(const Block&); + Block& operator=(Block&); + + // To enforce keeping parent and ownership in sync: + friend Function; + + std::vector > instructions; + std::vector predecessors, successors; + std::vector > localVariables; + Function& parent; + + // track whether this block is known to be uncreachable (not necessarily + // true for all unreachable blocks, but should be set at least + // for the extraneous ones introduced by the builder). + bool unreachable; +}; + +// The different reasons for reaching a block in the inReadableOrder traversal. +enum ReachReason { + // Reachable from the entry block via transfers of control, i.e. branches. + ReachViaControlFlow = 0, + // A continue target that is not reachable via control flow. + ReachDeadContinue, + // A merge block that is not reachable via control flow. + ReachDeadMerge +}; + +// Traverses the control-flow graph rooted at root in an order suited for +// readable code generation. Invokes callback at every node in the traversal +// order. The callback arguments are: +// - the block, +// - the reason we reached the block, +// - if the reason was that block is an unreachable continue or unreachable merge block +// then the last parameter is the corresponding header block. +void inReadableOrder(Block* root, std::function callback); + +// +// SPIR-V IR Function. +// + +class Function { +public: + Function(Id id, Id resultType, Id functionType, Id firstParam, Module& parent); + virtual ~Function() + { + for (int i = 0; i < (int)parameterInstructions.size(); ++i) + delete parameterInstructions[i]; + + for (int i = 0; i < (int)blocks.size(); ++i) + delete blocks[i]; + } + Id getId() const { return functionInstruction.getResultId(); } + Id getParamId(int p) const { return parameterInstructions[p]->getResultId(); } + Id getParamType(int p) const { return parameterInstructions[p]->getTypeId(); } + + void addBlock(Block* block) { blocks.push_back(block); } + void removeBlock(Block* block) + { + auto found = find(blocks.begin(), blocks.end(), block); + assert(found != blocks.end()); + blocks.erase(found); + delete block; + } + + Module& getParent() const { return parent; } + Block* getEntryBlock() const { return blocks.front(); } + Block* getLastBlock() const { return blocks.back(); } + const std::vector& getBlocks() const { return blocks; } + void addLocalVariable(std::unique_ptr inst); + Id getReturnType() const { return functionInstruction.getTypeId(); } + + void setImplicitThis() { implicitThis = true; } + bool hasImplicitThis() const { return implicitThis; } + + void dump(std::vector& out) const + { + // OpFunction + functionInstruction.dump(out); + + // OpFunctionParameter + for (int p = 0; p < (int)parameterInstructions.size(); ++p) + parameterInstructions[p]->dump(out); + + // Blocks + inReadableOrder(blocks[0], [&out](const Block* b, ReachReason, Block*) { b->dump(out); }); + Instruction end(0, 0, OpFunctionEnd); + end.dump(out); + } + +protected: + Function(const Function&); + Function& operator=(Function&); + + Module& parent; + Instruction functionInstruction; + std::vector parameterInstructions; + std::vector blocks; + bool implicitThis; // true if this is a member function expecting to be passed a 'this' as the first argument +}; + +// +// SPIR-V IR Module. +// + +class Module { +public: + Module() {} + virtual ~Module() + { + // TODO delete things + } + + void addFunction(Function *fun) { functions.push_back(fun); } + + void mapInstruction(Instruction *instruction) + { + spv::Id resultId = instruction->getResultId(); + // map the instruction's result id + if (resultId >= idToInstruction.size()) + idToInstruction.resize(resultId + 16); + idToInstruction[resultId] = instruction; + } + + Instruction* getInstruction(Id id) const { return idToInstruction[id]; } + const std::vector& getFunctions() const { return functions; } + spv::Id getTypeId(Id resultId) const { + return idToInstruction[resultId] == nullptr ? NoType : idToInstruction[resultId]->getTypeId(); + } + StorageClass getStorageClass(Id typeId) const + { + assert(idToInstruction[typeId]->getOpCode() == spv::OpTypePointer); + return (StorageClass)idToInstruction[typeId]->getImmediateOperand(0); + } + + void dump(std::vector& out) const + { + for (int f = 0; f < (int)functions.size(); ++f) + functions[f]->dump(out); + } + +protected: + Module(const Module&); + std::vector functions; + + // map from result id to instruction having that result id + std::vector idToInstruction; + + // map from a result id to its type id +}; + +// +// Implementation (it's here due to circular type definitions). +// + +// Add both +// - the OpFunction instruction +// - all the OpFunctionParameter instructions +__inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, Module& parent) + : parent(parent), functionInstruction(id, resultType, OpFunction), implicitThis(false) +{ + // OpFunction + functionInstruction.addImmediateOperand(FunctionControlMaskNone); + functionInstruction.addIdOperand(functionType); + parent.mapInstruction(&functionInstruction); + parent.addFunction(this); + + // OpFunctionParameter + Instruction* typeInst = parent.getInstruction(functionType); + int numParams = typeInst->getNumOperands() - 1; + for (int p = 0; p < numParams; ++p) { + Instruction* param = new Instruction(firstParamId + p, typeInst->getIdOperand(p + 1), OpFunctionParameter); + parent.mapInstruction(param); + parameterInstructions.push_back(param); + } +} + +__inline void Function::addLocalVariable(std::unique_ptr inst) +{ + Instruction* raw_instruction = inst.get(); + blocks[0]->addLocalVariable(std::move(inst)); + parent.mapInstruction(raw_instruction); +} + +__inline Block::Block(Id id, Function& parent) : parent(parent), unreachable(false) +{ + instructions.push_back(std::unique_ptr(new Instruction(id, NoType, OpLabel))); + instructions.back()->setBlock(this); + parent.getParent().mapInstruction(instructions.back().get()); +} + +__inline void Block::addInstruction(std::unique_ptr inst) +{ + Instruction* raw_instruction = inst.get(); + instructions.push_back(std::move(inst)); + raw_instruction->setBlock(this); + if (raw_instruction->getResultId()) + parent.getParent().mapInstruction(raw_instruction); +} + +} // end spv namespace + +#endif // spvIR_H diff --git a/android/armeabi-v7a/glslang/libOGLCompiler.a b/android/armeabi-v7a/glslang/libOGLCompiler.a new file mode 100644 index 0000000000000000000000000000000000000000..cfe632daca0bb9854df7a45a0bda1c538a9b6f3e GIT binary patch literal 24996 zcmeI4d3+RAw#QF(I*~OHmIO%9sDL1nodggOkevVl#08ho>F$swo$lD(Nk9>lMO1JH z7eE2`eODB9TxQ;Ld^&F98)qD6Tp8EV(Lu)<9eL+>ZdG;lA?mz8-u(6I1NFVXd(S<0 zty{OdD|P7jKqA;Qp<8Kj=21R+%$SZkJsr_IGI#Q6;r~gK(MLPY?UUh(~K46 zCJQ`A0@28s;hC{ec==Q+)y>Ro^Z}}(!iieaE$wVdG+GjDZ7qqHcI#H^bc1c^?YGfo zF<__`f?v+K~;TcocK^7utq;+_7Qxbqz@>tkyox1ZZvcK#C|A`Ba+ zzlqlKn3%LWx9qhUeK{!>O2i|f;^Ct!D$2^LDvBEd$#AGR9xF~%R#jJy859xnjTUsMgHkeXdTYA7n`eT_J+9J`A-O1V$*(Fe? zD+$e8Sbu!&LRnS3i`fq@JjqmuLg8REwW2jVJk}PCwx$vz$PUz}sJ=cHYA&a?STeFS z#$z0br6|ek7ALiYTY{}CfR=cBn3AakB#&MK;TQzs0-OPoi5xAhBtAHWgOXwxj7Ou; z%Nr9dT=i-gHzgJY#)e~ohG@7x(m3;^+J^F}Q>WIoN0y1NrUVR8$PX9>BT@yngHf_I z#`ZNFY;8z1cj`G7l;>~D8GA#WQP9)+I9Sz5b z#~>7GY(yUime=!rVrh)S_6SG^*Vl6=j^Rif$)ZZ6AIye(=>G6ql#dD)-@uj!POb1)E%#)H(D2#0wBOPIG; z!axJ&X&@C|9!Zg$>Zc;OG@J^@+9|mrnc@aDB*WPJ(HTjZ)r%_w4aw!iCyL5R&h?8c zx!uc`6Q89ENIHO8xZN>6r{Wz!>cA}KPU{G!;w=pvn?!VyH3wL6RqD@Ziv*kNr81si zeSLD;%-X3Wr~3Nla3U6t)}!CqovY(=m6~&7YdpzmjlpO<8K%a@Xj`(0`0{ROYXsWC z#?}N6Co>rg#5g);>!d>y-|pDe*S81iqmd+v#9bj3iMcUOO1tf>J!xlly|z1U8@YdZ zK=_>GDzqWY=Ons4NTSLqzZUT3ncvYZp&ErJZ`(wwUB8)Db2^%zVD=xT>iZ9$&i$ z8$0ZI=tQ);N$p7|E@>Nanlm(Z0272SGJ%;`P&`H*tU4m0Fb0&P5EJA*gi&(sh0G<` zXuzwF#71q{(#K22*+8MFl5yKbdX1 zl#sD0?@QFx$pF!}{|n3lPNt@6I`X$t7oi$Bx#MjI}$ z1`_3UA>NkWjp?i1s-@kT6ZAH`6_Xd$RMHeIdqh0SA|`^cHZ4Q=)NE?4(0(K*bN`FAC@| zua!g}-rqvShVaLB8fwOaLwQ9!I!r#x*BB-&5%vl8{HdPD6{m^(-&c|?VQByNIP+nR z%r*f|ukXoTE&do!vTq+bfu!!?n!InQ^FK<{ZJSCc*4gg4$~Ya~>1SeMKZVsb|+QB~U%C87J6!qF`G} zu>C^8b+-t1{6etv9l@@@32x}e9h}$W#zO=*9VxhZwBXi>g4<>bZa+bAM?i2_RB(5P z;GQ*tdoL2)f3@I&8w3yDEqLfr!R}uO9(hBs=P!cCz6E-Qq(wc$IXuRBJsbN7nkEaD zH4B>83Zk0@v6}>~4-3wCMUePRknGhHUfPZnbW9bjSSmPcjbPv|rxN5H8>X6`?)q-s|3bsE4^oc$rXn9o-lRoRy`n{+#`tc;r>ysENNY)5a zCkonPg7)=-j$MM~j|f)0BslYX!C3?I;ALf%;OyfCtKx#y=LpW(COG##!J20UYkw

<+=@j|i^#55eZ&2)2A6xO$)9nr^&`<@MP* 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 literal 0 HcmV?d00001 diff --git a/android/armeabi-v7a/glslang/libOSDependent.a b/android/armeabi-v7a/glslang/libOSDependent.a new file mode 100644 index 0000000000000000000000000000000000000000..2ce93b8d3fe425256995e9b801dd1bdeef90a335 GIT binary patch literal 16274 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 literal 0 HcmV?d00001 diff --git a/android/armeabi-v7a/glslang/libglslang.a b/android/armeabi-v7a/glslang/libglslang.a new file mode 100644 index 0000000000000000000000000000000000000000..7875f944d8ab45ca3daea64a2d1e9f93698c4d8a GIT binary patch literal 2240838 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 *D>{fbBs~#oAL#$EAG%Uorag9m06ri$Bn21O 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⁣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%0DZ?SOHZF^)_Ev7WY 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

FRDw7e0L*&rH9>D+IsVUb|4fCIN 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 CcVk`v literal 0 HcmV?d00001 diff --git a/android/armeabi-v7a/include/SPIRV/GLSL.ext.AMD.h b/android/armeabi-v7a/include/SPIRV/GLSL.ext.AMD.h new file mode 100644 index 00000000..009d2f1c --- /dev/null +++ b/android/armeabi-v7a/include/SPIRV/GLSL.ext.AMD.h @@ -0,0 +1,108 @@ +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextAMD_H +#define GLSLextAMD_H + +static const int GLSLextAMDVersion = 100; +static const int GLSLextAMDRevision = 7; + +// SPV_AMD_shader_ballot +static const char* const E_SPV_AMD_shader_ballot = "SPV_AMD_shader_ballot"; + +enum ShaderBallotAMD { + ShaderBallotBadAMD = 0, // Don't use + + SwizzleInvocationsAMD = 1, + SwizzleInvocationsMaskedAMD = 2, + WriteInvocationAMD = 3, + MbcntAMD = 4, + + ShaderBallotCountAMD +}; + +// SPV_AMD_shader_trinary_minmax +static const char* const E_SPV_AMD_shader_trinary_minmax = "SPV_AMD_shader_trinary_minmax"; + +enum ShaderTrinaryMinMaxAMD { + ShaderTrinaryMinMaxBadAMD = 0, // Don't use + + FMin3AMD = 1, + UMin3AMD = 2, + SMin3AMD = 3, + FMax3AMD = 4, + UMax3AMD = 5, + SMax3AMD = 6, + FMid3AMD = 7, + UMid3AMD = 8, + SMid3AMD = 9, + + ShaderTrinaryMinMaxCountAMD +}; + +// SPV_AMD_shader_explicit_vertex_parameter +static const char* const E_SPV_AMD_shader_explicit_vertex_parameter = "SPV_AMD_shader_explicit_vertex_parameter"; + +enum ShaderExplicitVertexParameterAMD { + ShaderExplicitVertexParameterBadAMD = 0, // Don't use + + InterpolateAtVertexAMD = 1, + + ShaderExplicitVertexParameterCountAMD +}; + +// SPV_AMD_gcn_shader +static const char* const E_SPV_AMD_gcn_shader = "SPV_AMD_gcn_shader"; + +enum GcnShaderAMD { + GcnShaderBadAMD = 0, // Don't use + + CubeFaceIndexAMD = 1, + CubeFaceCoordAMD = 2, + TimeAMD = 3, + + GcnShaderCountAMD +}; + +// SPV_AMD_gpu_shader_half_float +static const char* const E_SPV_AMD_gpu_shader_half_float = "SPV_AMD_gpu_shader_half_float"; + +// SPV_AMD_texture_gather_bias_lod +static const char* const E_SPV_AMD_texture_gather_bias_lod = "SPV_AMD_texture_gather_bias_lod"; + +// SPV_AMD_gpu_shader_int16 +static const char* const E_SPV_AMD_gpu_shader_int16 = "SPV_AMD_gpu_shader_int16"; + +// SPV_AMD_shader_image_load_store_lod +static const char* const E_SPV_AMD_shader_image_load_store_lod = "SPV_AMD_shader_image_load_store_lod"; + +// SPV_AMD_shader_fragment_mask +static const char* const E_SPV_AMD_shader_fragment_mask = "SPV_AMD_shader_fragment_mask"; + +// SPV_AMD_gpu_shader_half_float_fetch +static const char* const E_SPV_AMD_gpu_shader_half_float_fetch = "SPV_AMD_gpu_shader_half_float_fetch"; + +#endif // #ifndef GLSLextAMD_H diff --git a/android/armeabi-v7a/include/SPIRV/GLSL.ext.EXT.h b/android/armeabi-v7a/include/SPIRV/GLSL.ext.EXT.h new file mode 100644 index 00000000..40164b61 --- /dev/null +++ b/android/armeabi-v7a/include/SPIRV/GLSL.ext.EXT.h @@ -0,0 +1,39 @@ +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextEXT_H +#define GLSLextEXT_H + +static const int GLSLextEXTVersion = 100; +static const int GLSLextEXTRevision = 2; + +static const char* const E_SPV_EXT_shader_stencil_export = "SPV_EXT_shader_stencil_export"; +static const char* const E_SPV_EXT_shader_viewport_index_layer = "SPV_EXT_shader_viewport_index_layer"; +static const char* const E_SPV_EXT_fragment_fully_covered = "SPV_EXT_fragment_fully_covered"; +static const char* const E_SPV_EXT_fragment_invocation_density = "SPV_EXT_fragment_invocation_density"; +static const char* const E_SPV_EXT_demote_to_helper_invocation = "SPV_EXT_demote_to_helper_invocation"; + +#endif // #ifndef GLSLextEXT_H diff --git a/android/armeabi-v7a/include/SPIRV/GLSL.ext.KHR.h b/android/armeabi-v7a/include/SPIRV/GLSL.ext.KHR.h new file mode 100644 index 00000000..d783a8f2 --- /dev/null +++ b/android/armeabi-v7a/include/SPIRV/GLSL.ext.KHR.h @@ -0,0 +1,51 @@ +/* +** Copyright (c) 2014-2020 The Khronos Group Inc. +** Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextKHR_H +#define GLSLextKHR_H + +static const int GLSLextKHRVersion = 100; +static const int GLSLextKHRRevision = 2; + +static const char* const E_SPV_KHR_shader_ballot = "SPV_KHR_shader_ballot"; +static const char* const E_SPV_KHR_subgroup_vote = "SPV_KHR_subgroup_vote"; +static const char* const E_SPV_KHR_device_group = "SPV_KHR_device_group"; +static const char* const E_SPV_KHR_multiview = "SPV_KHR_multiview"; +static const char* const E_SPV_KHR_shader_draw_parameters = "SPV_KHR_shader_draw_parameters"; +static const char* const E_SPV_KHR_16bit_storage = "SPV_KHR_16bit_storage"; +static const char* const E_SPV_KHR_8bit_storage = "SPV_KHR_8bit_storage"; +static const char* const E_SPV_KHR_storage_buffer_storage_class = "SPV_KHR_storage_buffer_storage_class"; +static const char* const E_SPV_KHR_post_depth_coverage = "SPV_KHR_post_depth_coverage"; +static const char* const E_SPV_KHR_vulkan_memory_model = "SPV_KHR_vulkan_memory_model"; +static const char* const E_SPV_EXT_physical_storage_buffer = "SPV_EXT_physical_storage_buffer"; +static const char* const E_SPV_KHR_physical_storage_buffer = "SPV_KHR_physical_storage_buffer"; +static const char* const E_SPV_EXT_fragment_shader_interlock = "SPV_EXT_fragment_shader_interlock"; +static const char* const E_SPV_KHR_shader_clock = "SPV_KHR_shader_clock"; +static const char* const E_SPV_KHR_non_semantic_info = "SPV_KHR_non_semantic_info"; +static const char* const E_SPV_KHR_ray_tracing = "SPV_KHR_ray_tracing"; +static const char* const E_SPV_KHR_ray_query = "SPV_KHR_ray_query"; +#endif // #ifndef GLSLextKHR_H diff --git a/android/armeabi-v7a/include/SPIRV/GLSL.ext.NV.h b/android/armeabi-v7a/include/SPIRV/GLSL.ext.NV.h new file mode 100644 index 00000000..50146da1 --- /dev/null +++ b/android/armeabi-v7a/include/SPIRV/GLSL.ext.NV.h @@ -0,0 +1,81 @@ +/* +** Copyright (c) 2014-2017 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextNV_H +#define GLSLextNV_H + +enum BuiltIn; +enum Decoration; +enum Op; +enum Capability; + +static const int GLSLextNVVersion = 100; +static const int GLSLextNVRevision = 11; + +//SPV_NV_sample_mask_override_coverage +const char* const E_SPV_NV_sample_mask_override_coverage = "SPV_NV_sample_mask_override_coverage"; + +//SPV_NV_geometry_shader_passthrough +const char* const E_SPV_NV_geometry_shader_passthrough = "SPV_NV_geometry_shader_passthrough"; + +//SPV_NV_viewport_array2 +const char* const E_SPV_NV_viewport_array2 = "SPV_NV_viewport_array2"; +const char* const E_ARB_shader_viewport_layer_array = "SPV_ARB_shader_viewport_layer_array"; + +//SPV_NV_stereo_view_rendering +const char* const E_SPV_NV_stereo_view_rendering = "SPV_NV_stereo_view_rendering"; + +//SPV_NVX_multiview_per_view_attributes +const char* const E_SPV_NVX_multiview_per_view_attributes = "SPV_NVX_multiview_per_view_attributes"; + +//SPV_NV_shader_subgroup_partitioned +const char* const E_SPV_NV_shader_subgroup_partitioned = "SPV_NV_shader_subgroup_partitioned"; + +//SPV_NV_fragment_shader_barycentric +const char* const E_SPV_NV_fragment_shader_barycentric = "SPV_NV_fragment_shader_barycentric"; + +//SPV_NV_compute_shader_derivatives +const char* const E_SPV_NV_compute_shader_derivatives = "SPV_NV_compute_shader_derivatives"; + +//SPV_NV_shader_image_footprint +const char* const E_SPV_NV_shader_image_footprint = "SPV_NV_shader_image_footprint"; + +//SPV_NV_mesh_shader +const char* const E_SPV_NV_mesh_shader = "SPV_NV_mesh_shader"; + +//SPV_NV_raytracing +const char* const E_SPV_NV_ray_tracing = "SPV_NV_ray_tracing"; + +//SPV_NV_shading_rate +const char* const E_SPV_NV_shading_rate = "SPV_NV_shading_rate"; + +//SPV_NV_cooperative_matrix +const char* const E_SPV_NV_cooperative_matrix = "SPV_NV_cooperative_matrix"; + +//SPV_NV_shader_sm_builtins +const char* const E_SPV_NV_shader_sm_builtins = "SPV_NV_shader_sm_builtins"; + +#endif // #ifndef GLSLextNV_H diff --git a/android/armeabi-v7a/include/SPIRV/GLSL.std.450.h b/android/armeabi-v7a/include/SPIRV/GLSL.std.450.h new file mode 100644 index 00000000..df31092b --- /dev/null +++ b/android/armeabi-v7a/include/SPIRV/GLSL.std.450.h @@ -0,0 +1,131 @@ +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLstd450_H +#define GLSLstd450_H + +static const int GLSLstd450Version = 100; +static const int GLSLstd450Revision = 1; + +enum GLSLstd450 { + GLSLstd450Bad = 0, // Don't use + + GLSLstd450Round = 1, + GLSLstd450RoundEven = 2, + GLSLstd450Trunc = 3, + GLSLstd450FAbs = 4, + GLSLstd450SAbs = 5, + GLSLstd450FSign = 6, + GLSLstd450SSign = 7, + GLSLstd450Floor = 8, + GLSLstd450Ceil = 9, + GLSLstd450Fract = 10, + + GLSLstd450Radians = 11, + GLSLstd450Degrees = 12, + GLSLstd450Sin = 13, + GLSLstd450Cos = 14, + GLSLstd450Tan = 15, + GLSLstd450Asin = 16, + GLSLstd450Acos = 17, + GLSLstd450Atan = 18, + GLSLstd450Sinh = 19, + GLSLstd450Cosh = 20, + GLSLstd450Tanh = 21, + GLSLstd450Asinh = 22, + GLSLstd450Acosh = 23, + GLSLstd450Atanh = 24, + GLSLstd450Atan2 = 25, + + GLSLstd450Pow = 26, + GLSLstd450Exp = 27, + GLSLstd450Log = 28, + GLSLstd450Exp2 = 29, + GLSLstd450Log2 = 30, + GLSLstd450Sqrt = 31, + GLSLstd450InverseSqrt = 32, + + GLSLstd450Determinant = 33, + GLSLstd450MatrixInverse = 34, + + GLSLstd450Modf = 35, // second operand needs an OpVariable to write to + GLSLstd450ModfStruct = 36, // no OpVariable operand + GLSLstd450FMin = 37, + GLSLstd450UMin = 38, + GLSLstd450SMin = 39, + GLSLstd450FMax = 40, + GLSLstd450UMax = 41, + GLSLstd450SMax = 42, + GLSLstd450FClamp = 43, + GLSLstd450UClamp = 44, + GLSLstd450SClamp = 45, + GLSLstd450FMix = 46, + GLSLstd450IMix = 47, // Reserved + GLSLstd450Step = 48, + GLSLstd450SmoothStep = 49, + + GLSLstd450Fma = 50, + GLSLstd450Frexp = 51, // second operand needs an OpVariable to write to + GLSLstd450FrexpStruct = 52, // no OpVariable operand + GLSLstd450Ldexp = 53, + + GLSLstd450PackSnorm4x8 = 54, + GLSLstd450PackUnorm4x8 = 55, + GLSLstd450PackSnorm2x16 = 56, + GLSLstd450PackUnorm2x16 = 57, + GLSLstd450PackHalf2x16 = 58, + GLSLstd450PackDouble2x32 = 59, + GLSLstd450UnpackSnorm2x16 = 60, + GLSLstd450UnpackUnorm2x16 = 61, + GLSLstd450UnpackHalf2x16 = 62, + GLSLstd450UnpackSnorm4x8 = 63, + GLSLstd450UnpackUnorm4x8 = 64, + GLSLstd450UnpackDouble2x32 = 65, + + GLSLstd450Length = 66, + GLSLstd450Distance = 67, + GLSLstd450Cross = 68, + GLSLstd450Normalize = 69, + GLSLstd450FaceForward = 70, + GLSLstd450Reflect = 71, + GLSLstd450Refract = 72, + + GLSLstd450FindILsb = 73, + GLSLstd450FindSMsb = 74, + GLSLstd450FindUMsb = 75, + + GLSLstd450InterpolateAtCentroid = 76, + GLSLstd450InterpolateAtSample = 77, + GLSLstd450InterpolateAtOffset = 78, + + GLSLstd450NMin = 79, + GLSLstd450NMax = 80, + GLSLstd450NClamp = 81, + + GLSLstd450Count +}; + +#endif // #ifndef GLSLstd450_H diff --git a/android/armeabi-v7a/include/SPIRV/GlslangToSpv.h b/android/armeabi-v7a/include/SPIRV/GlslangToSpv.h new file mode 100644 index 00000000..3907be43 --- /dev/null +++ b/android/armeabi-v7a/include/SPIRV/GlslangToSpv.h @@ -0,0 +1,61 @@ +// +// Copyright (C) 2014 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#pragma once + +#if defined(_MSC_VER) && _MSC_VER >= 1900 + #pragma warning(disable : 4464) // relative include path contains '..' +#endif + +#include "SpvTools.h" +#include "glslang/Include/intermediate.h" + +#include +#include + +#include "Logger.h" + +namespace glslang { + +void GetSpirvVersion(std::string&); +int GetSpirvGeneratorVersion(); +void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, + SpvOptions* options = nullptr); +void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger* logger, SpvOptions* options = nullptr); +void OutputSpvBin(const std::vector& spirv, const char* baseName); +void OutputSpvHex(const std::vector& spirv, const char* baseName, const char* varName); + +} diff --git a/android/armeabi-v7a/include/SPIRV/Logger.h b/android/armeabi-v7a/include/SPIRV/Logger.h new file mode 100644 index 00000000..411367c0 --- /dev/null +++ b/android/armeabi-v7a/include/SPIRV/Logger.h @@ -0,0 +1,83 @@ +// +// Copyright (C) 2016 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef GLSLANG_SPIRV_LOGGER_H +#define GLSLANG_SPIRV_LOGGER_H + +#include +#include + +namespace spv { + +// A class for holding all SPIR-V build status messages, including +// missing/TBD functionalities, warnings, and errors. +class SpvBuildLogger { +public: + SpvBuildLogger() {} + +#ifdef GLSLANG_WEB + void tbdFunctionality(const std::string& f) { } + void missingFunctionality(const std::string& f) { } + void warning(const std::string& w) { } + void error(const std::string& e) { errors.push_back(e); } + std::string getAllMessages() { return ""; } +#else + + // Registers a TBD functionality. + void tbdFunctionality(const std::string& f); + // Registers a missing functionality. + void missingFunctionality(const std::string& f); + + // Logs a warning. + void warning(const std::string& w) { warnings.push_back(w); } + // Logs an error. + void error(const std::string& e) { errors.push_back(e); } + + // Returns all messages accumulated in the order of: + // TBD functionalities, missing functionalities, warnings, errors. + std::string getAllMessages() const; +#endif + +private: + SpvBuildLogger(const SpvBuildLogger&); + + std::vector tbdFeatures; + std::vector missingFeatures; + std::vector warnings; + std::vector errors; +}; + +} // end spv namespace + +#endif // GLSLANG_SPIRV_LOGGER_H diff --git a/android/armeabi-v7a/include/SPIRV/NonSemanticDebugPrintf.h b/android/armeabi-v7a/include/SPIRV/NonSemanticDebugPrintf.h new file mode 100644 index 00000000..83796d75 --- /dev/null +++ b/android/armeabi-v7a/include/SPIRV/NonSemanticDebugPrintf.h @@ -0,0 +1,50 @@ +// Copyright (c) 2020 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and/or associated documentation files (the +// "Materials"), to deal in the Materials without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Materials, and to +// permit persons to whom the Materials are furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS +// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS +// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT +// https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +// + +#ifndef SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ +#define SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + NonSemanticDebugPrintfRevision = 1, + NonSemanticDebugPrintfRevision_BitWidthPadding = 0x7fffffff +}; + +enum NonSemanticDebugPrintfInstructions { + NonSemanticDebugPrintfDebugPrintf = 1, + NonSemanticDebugPrintfInstructionsMax = 0x7fffffff +}; + + +#ifdef __cplusplus +} +#endif + +#endif // SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ diff --git a/android/armeabi-v7a/include/SPIRV/SPVRemapper.h b/android/armeabi-v7a/include/SPIRV/SPVRemapper.h new file mode 100644 index 00000000..d6b9c346 --- /dev/null +++ b/android/armeabi-v7a/include/SPIRV/SPVRemapper.h @@ -0,0 +1,304 @@ +// +// Copyright (C) 2015 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef SPIRVREMAPPER_H +#define SPIRVREMAPPER_H + +#include +#include +#include +#include + +namespace spv { + +// MSVC defines __cplusplus as an older value, even when it supports almost all of 11. +// We handle that here by making our own symbol. +#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1700) +# define use_cpp11 1 +#endif + +class spirvbin_base_t +{ +public: + enum Options { + NONE = 0, + STRIP = (1<<0), + MAP_TYPES = (1<<1), + MAP_NAMES = (1<<2), + MAP_FUNCS = (1<<3), + DCE_FUNCS = (1<<4), + DCE_VARS = (1<<5), + DCE_TYPES = (1<<6), + OPT_LOADSTORE = (1<<7), + OPT_FWD_LS = (1<<8), // EXPERIMENTAL: PRODUCES INVALID SCHEMA-0 SPIRV + MAP_ALL = (MAP_TYPES | MAP_NAMES | MAP_FUNCS), + DCE_ALL = (DCE_FUNCS | DCE_VARS | DCE_TYPES), + OPT_ALL = (OPT_LOADSTORE), + + ALL_BUT_STRIP = (MAP_ALL | DCE_ALL | OPT_ALL), + DO_EVERYTHING = (STRIP | ALL_BUT_STRIP) + }; +}; + +} // namespace SPV + +#if !defined (use_cpp11) +#include +#include + +namespace spv { +class spirvbin_t : public spirvbin_base_t +{ +public: + spirvbin_t(int /*verbose = 0*/) { } + + void remap(std::vector& /*spv*/, unsigned int /*opts = 0*/) + { + printf("Tool not compiled for C++11, which is required for SPIR-V remapping.\n"); + exit(5); + } +}; + +} // namespace SPV + +#else // defined (use_cpp11) + +#include +#include +#include +#include +#include +#include +#include + +#include "spirv.hpp" +#include "spvIR.h" + +namespace spv { + +// class to hold SPIR-V binary data for remapping, DCE, and debug stripping +class spirvbin_t : public spirvbin_base_t +{ +public: + spirvbin_t(int verbose = 0) : entryPoint(spv::NoResult), largestNewId(0), verbose(verbose), errorLatch(false) + { } + + virtual ~spirvbin_t() { } + + // remap on an existing binary in memory + void remap(std::vector& spv, std::uint32_t opts = DO_EVERYTHING); + + // Type for error/log handler functions + typedef std::function errorfn_t; + typedef std::function logfn_t; + + // Register error/log handling functions (can be lambda fn / functor / etc) + static void registerErrorHandler(errorfn_t handler) { errorHandler = handler; } + static void registerLogHandler(logfn_t handler) { logHandler = handler; } + +protected: + // This can be overridden to provide other message behavior if needed + virtual void msg(int minVerbosity, int indent, const std::string& txt) const; + +private: + // Local to global, or global to local ID map + typedef std::unordered_map idmap_t; + typedef std::unordered_set idset_t; + typedef std::unordered_map blockmap_t; + + void remap(std::uint32_t opts = DO_EVERYTHING); + + // Map of names to IDs + typedef std::unordered_map namemap_t; + + typedef std::uint32_t spirword_t; + + typedef std::pair range_t; + typedef std::function idfn_t; + typedef std::function instfn_t; + + // Special Values for ID map: + static const spv::Id unmapped; // unchanged from default value + static const spv::Id unused; // unused ID + static const int header_size; // SPIR header = 5 words + + class id_iterator_t; + + // For mapping type entries between different shaders + typedef std::vector typeentry_t; + typedef std::map globaltypes_t; + + // A set that preserves position order, and a reverse map + typedef std::set posmap_t; + typedef std::unordered_map posmap_rev_t; + + // Maps and ID to the size of its base type, if known. + typedef std::unordered_map typesize_map_t; + + // handle error + void error(const std::string& txt) const { errorLatch = true; errorHandler(txt); } + + bool isConstOp(spv::Op opCode) const; + bool isTypeOp(spv::Op opCode) const; + bool isStripOp(spv::Op opCode) const; + bool isFlowCtrl(spv::Op opCode) const; + range_t literalRange(spv::Op opCode) const; + range_t typeRange(spv::Op opCode) const; + range_t constRange(spv::Op opCode) const; + unsigned typeSizeInWords(spv::Id id) const; + unsigned idTypeSizeInWords(spv::Id id) const; + + spv::Id& asId(unsigned word) { return spv[word]; } + const spv::Id& asId(unsigned word) const { return spv[word]; } + spv::Op asOpCode(unsigned word) const { return opOpCode(spv[word]); } + std::uint32_t asOpCodeHash(unsigned word); + spv::Decoration asDecoration(unsigned word) const { return spv::Decoration(spv[word]); } + unsigned asWordCount(unsigned word) const { return opWordCount(spv[word]); } + spv::Id asTypeConstId(unsigned word) const { return asId(word + (isTypeOp(asOpCode(word)) ? 1 : 2)); } + unsigned idPos(spv::Id id) const; + + static unsigned opWordCount(spirword_t data) { return data >> spv::WordCountShift; } + static spv::Op opOpCode(spirword_t data) { return spv::Op(data & spv::OpCodeMask); } + + // Header access & set methods + spirword_t magic() const { return spv[0]; } // return magic number + spirword_t bound() const { return spv[3]; } // return Id bound from header + spirword_t bound(spirword_t b) { return spv[3] = b; } + spirword_t genmagic() const { return spv[2]; } // generator magic + spirword_t genmagic(spirword_t m) { return spv[2] = m; } + spirword_t schemaNum() const { return spv[4]; } // schema number from header + + // Mapping fns: get + spv::Id localId(spv::Id id) const { return idMapL[id]; } + + // Mapping fns: set + inline spv::Id localId(spv::Id id, spv::Id newId); + void countIds(spv::Id id); + + // Return next unused new local ID. + // NOTE: boost::dynamic_bitset would be more efficient due to find_next(), + // which std::vector doens't have. + inline spv::Id nextUnusedId(spv::Id id); + + void buildLocalMaps(); + std::string literalString(unsigned word) const; // Return literal as a std::string + int literalStringWords(const std::string& str) const { return (int(str.size())+4)/4; } + + bool isNewIdMapped(spv::Id newId) const { return isMapped(newId); } + bool isOldIdUnmapped(spv::Id oldId) const { return localId(oldId) == unmapped; } + bool isOldIdUnused(spv::Id oldId) const { return localId(oldId) == unused; } + bool isOldIdMapped(spv::Id oldId) const { return !isOldIdUnused(oldId) && !isOldIdUnmapped(oldId); } + bool isFunction(spv::Id oldId) const { return fnPos.find(oldId) != fnPos.end(); } + + // bool matchType(const globaltypes_t& globalTypes, spv::Id lt, spv::Id gt) const; + // spv::Id findType(const globaltypes_t& globalTypes, spv::Id lt) const; + std::uint32_t hashType(unsigned typeStart) const; + + spirvbin_t& process(instfn_t, idfn_t, unsigned begin = 0, unsigned end = 0); + int processInstruction(unsigned word, instfn_t, idfn_t); + + void validate() const; + void mapTypeConst(); + void mapFnBodies(); + void optLoadStore(); + void dceFuncs(); + void dceVars(); + void dceTypes(); + void mapNames(); + void foldIds(); // fold IDs to smallest space + void forwardLoadStores(); // load store forwarding (EXPERIMENTAL) + void offsetIds(); // create relative offset IDs + + void applyMap(); // remap per local name map + void mapRemainder(); // map any IDs we haven't touched yet + void stripDebug(); // strip all debug info + void stripDeadRefs(); // strips debug info for now-dead references after DCE + void strip(); // remove debug symbols + + std::vector spv; // SPIR words + + namemap_t nameMap; // ID names from OpName + + // Since we want to also do binary ops, we can't use std::vector. we could use + // boost::dynamic_bitset, but we're trying to avoid a boost dependency. + typedef std::uint64_t bits_t; + std::vector mapped; // which new IDs have been mapped + static const int mBits = sizeof(bits_t) * 4; + + bool isMapped(spv::Id id) const { return id < maxMappedId() && ((mapped[id/mBits] & (1LL<<(id%mBits))) != 0); } + void setMapped(spv::Id id) { resizeMapped(id); mapped[id/mBits] |= (1LL<<(id%mBits)); } + void resizeMapped(spv::Id id) { if (id >= maxMappedId()) mapped.resize(id/mBits+1, 0); } + size_t maxMappedId() const { return mapped.size() * mBits; } + + // Add a strip range for a given instruction starting at 'start' + // Note: avoiding brace initializers to please older versions os MSVC. + void stripInst(unsigned start) { stripRange.push_back(range_t(start, start + asWordCount(start))); } + + // Function start and end. use unordered_map because we'll have + // many fewer functions than IDs. + std::unordered_map fnPos; + + // Which functions are called, anywhere in the module, with a call count + std::unordered_map fnCalls; + + posmap_t typeConstPos; // word positions that define types & consts (ordered) + posmap_rev_t idPosR; // reverse map from IDs to positions + typesize_map_t idTypeSizeMap; // maps each ID to its type size, if known. + + std::vector idMapL; // ID {M}ap from {L}ocal to {G}lobal IDs + + spv::Id entryPoint; // module entry point + spv::Id largestNewId; // biggest new ID we have mapped anything to + + // Sections of the binary to strip, given as [begin,end) + std::vector stripRange; + + // processing options: + std::uint32_t options; + int verbose; // verbosity level + + // Error latch: this is set if the error handler is ever executed. It would be better to + // use a try/catch block and throw, but that's not desired for certain environments, so + // this is the alternative. + mutable bool errorLatch; + + static errorfn_t errorHandler; + static logfn_t logHandler; +}; + +} // namespace SPV + +#endif // defined (use_cpp11) +#endif // SPIRVREMAPPER_H diff --git a/android/armeabi-v7a/include/SPIRV/SpvBuilder.h b/android/armeabi-v7a/include/SPIRV/SpvBuilder.h new file mode 100644 index 00000000..71b90d60 --- /dev/null +++ b/android/armeabi-v7a/include/SPIRV/SpvBuilder.h @@ -0,0 +1,838 @@ +// +// Copyright (C) 2014-2015 LunarG, Inc. +// Copyright (C) 2015-2020 Google, Inc. +// Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// "Builder" is an interface to fully build SPIR-V IR. Allocate one of +// these to build (a thread safe) internal SPIR-V representation (IR), +// and then dump it as a binary stream according to the SPIR-V specification. +// +// A Builder has a 1:1 relationship with a SPIR-V module. +// + +#pragma once +#ifndef SpvBuilder_H +#define SpvBuilder_H + +#include "Logger.h" +#include "spirv.hpp" +#include "spvIR.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace spv { + +typedef enum { + Spv_1_0 = (1 << 16), + Spv_1_1 = (1 << 16) | (1 << 8), + Spv_1_2 = (1 << 16) | (2 << 8), + Spv_1_3 = (1 << 16) | (3 << 8), + Spv_1_4 = (1 << 16) | (4 << 8), + Spv_1_5 = (1 << 16) | (5 << 8), +} SpvVersion; + +class Builder { +public: + Builder(unsigned int spvVersion, unsigned int userNumber, SpvBuildLogger* logger); + virtual ~Builder(); + + static const int maxMatrixSize = 4; + + unsigned int getSpvVersion() const { return spvVersion; } + + void setSource(spv::SourceLanguage lang, int version) + { + source = lang; + sourceVersion = version; + } + spv::Id getStringId(const std::string& str) + { + auto sItr = stringIds.find(str); + if (sItr != stringIds.end()) + return sItr->second; + spv::Id strId = getUniqueId(); + Instruction* fileString = new Instruction(strId, NoType, OpString); + const char* file_c_str = str.c_str(); + fileString->addStringOperand(file_c_str); + strings.push_back(std::unique_ptr(fileString)); + module.mapInstruction(fileString); + stringIds[file_c_str] = strId; + return strId; + } + void setSourceFile(const std::string& file) + { + sourceFileStringId = getStringId(file); + } + void setSourceText(const std::string& text) { sourceText = text; } + void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); } + void addModuleProcessed(const std::string& p) { moduleProcesses.push_back(p.c_str()); } + void setEmitOpLines() { emitOpLines = true; } + void addExtension(const char* ext) { extensions.insert(ext); } + void removeExtension(const char* ext) + { + extensions.erase(ext); + } + void addIncorporatedExtension(const char* ext, SpvVersion incorporatedVersion) + { + if (getSpvVersion() < static_cast(incorporatedVersion)) + addExtension(ext); + } + void promoteIncorporatedExtension(const char* baseExt, const char* promoExt, SpvVersion incorporatedVersion) + { + removeExtension(baseExt); + addIncorporatedExtension(promoExt, incorporatedVersion); + } + void addInclude(const std::string& name, const std::string& text) + { + spv::Id incId = getStringId(name); + includeFiles[incId] = &text; + } + Id import(const char*); + void setMemoryModel(spv::AddressingModel addr, spv::MemoryModel mem) + { + addressModel = addr; + memoryModel = mem; + } + + void addCapability(spv::Capability cap) { capabilities.insert(cap); } + + // To get a new for anything needing a new one. + Id getUniqueId() { return ++uniqueId; } + + // To get a set of new s, e.g., for a set of function parameters + Id getUniqueIds(int numIds) + { + Id id = uniqueId + 1; + uniqueId += numIds; + return id; + } + + // Generate OpLine for non-filename-based #line directives (ie no filename + // seen yet): Log the current line, and if different than the last one, + // issue a new OpLine using the new line and current source file name. + void setLine(int line); + + // If filename null, generate OpLine for non-filename-based line directives, + // else do filename-based: Log the current line and file, and if different + // than the last one, issue a new OpLine using the new line and file + // name. + void setLine(int line, const char* filename); + // Low-level OpLine. See setLine() for a layered helper. + void addLine(Id fileName, int line, int column); + + // For creating new types (will return old type if the requested one was already made). + Id makeVoidType(); + Id makeBoolType(); + Id makePointer(StorageClass, Id pointee); + Id makeForwardPointer(StorageClass); + Id makePointerFromForwardPointer(StorageClass, Id forwardPointerType, Id pointee); + Id makeIntegerType(int width, bool hasSign); // generic + Id makeIntType(int width) { return makeIntegerType(width, true); } + Id makeUintType(int width) { return makeIntegerType(width, false); } + Id makeFloatType(int width); + Id makeStructType(const std::vector& members, const char*); + Id makeStructResultType(Id type0, Id type1); + Id makeVectorType(Id component, int size); + Id makeMatrixType(Id component, int cols, int rows); + Id makeArrayType(Id element, Id sizeId, int stride); // 0 stride means no stride decoration + Id makeRuntimeArray(Id element); + Id makeFunctionType(Id returnType, const std::vector& paramTypes); + Id makeImageType(Id sampledType, Dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format); + Id makeSamplerType(); + Id makeSampledImageType(Id imageType); + Id makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols); + + // accelerationStructureNV type + Id makeAccelerationStructureType(); + // rayQueryEXT type + Id makeRayQueryType(); + + // For querying about types. + Id getTypeId(Id resultId) const { return module.getTypeId(resultId); } + Id getDerefTypeId(Id resultId) const; + Op getOpCode(Id id) const { return module.getInstruction(id)->getOpCode(); } + Op getTypeClass(Id typeId) const { return getOpCode(typeId); } + Op getMostBasicTypeClass(Id typeId) const; + int getNumComponents(Id resultId) const { return getNumTypeComponents(getTypeId(resultId)); } + int getNumTypeConstituents(Id typeId) const; + int getNumTypeComponents(Id typeId) const { return getNumTypeConstituents(typeId); } + Id getScalarTypeId(Id typeId) const; + Id getContainedTypeId(Id typeId) const; + Id getContainedTypeId(Id typeId, int) const; + StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); } + ImageFormat getImageTypeFormat(Id typeId) const + { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); } + + bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); } + bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); } + bool isVector(Id resultId) const { return isVectorType(getTypeId(resultId)); } + bool isMatrix(Id resultId) const { return isMatrixType(getTypeId(resultId)); } + bool isCooperativeMatrix(Id resultId)const { return isCooperativeMatrixType(getTypeId(resultId)); } + bool isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); } + bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); } + + bool isBoolType(Id typeId) + { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); } + bool isIntType(Id typeId) const + { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; } + bool isUintType(Id typeId) const + { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; } + bool isFloatType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat; } + bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; } + bool isScalarType(Id typeId) const + { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt || + getTypeClass(typeId) == OpTypeBool; } + bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; } + bool isMatrixType(Id typeId) const { return getTypeClass(typeId) == OpTypeMatrix; } + bool isStructType(Id typeId) const { return getTypeClass(typeId) == OpTypeStruct; } + bool isArrayType(Id typeId) const { return getTypeClass(typeId) == OpTypeArray; } +#ifdef GLSLANG_WEB + bool isCooperativeMatrixType(Id typeId)const { return false; } +#else + bool isCooperativeMatrixType(Id typeId)const { return getTypeClass(typeId) == OpTypeCooperativeMatrixNV; } +#endif + bool isAggregateType(Id typeId) const + { return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); } + bool isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; } + bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; } + bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; } + bool containsType(Id typeId, Op typeOp, unsigned int width) const; + bool containsPhysicalStorageBufferOrArray(Id typeId) const; + + bool isConstantOpCode(Op opcode) const; + bool isSpecConstantOpCode(Op opcode) const; + bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); } + bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; } + bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); } + unsigned int getConstantScalar(Id resultId) const + { return module.getInstruction(resultId)->getImmediateOperand(0); } + StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); } + + int getScalarTypeWidth(Id typeId) const + { + Id scalarTypeId = getScalarTypeId(typeId); + assert(getTypeClass(scalarTypeId) == OpTypeInt || getTypeClass(scalarTypeId) == OpTypeFloat); + return module.getInstruction(scalarTypeId)->getImmediateOperand(0); + } + + int getTypeNumColumns(Id typeId) const + { + assert(isMatrixType(typeId)); + return getNumTypeConstituents(typeId); + } + int getNumColumns(Id resultId) const { return getTypeNumColumns(getTypeId(resultId)); } + int getTypeNumRows(Id typeId) const + { + assert(isMatrixType(typeId)); + return getNumTypeComponents(getContainedTypeId(typeId)); + } + int getNumRows(Id resultId) const { return getTypeNumRows(getTypeId(resultId)); } + + Dim getTypeDimensionality(Id typeId) const + { + assert(isImageType(typeId)); + return (Dim)module.getInstruction(typeId)->getImmediateOperand(1); + } + Id getImageType(Id resultId) const + { + Id typeId = getTypeId(resultId); + assert(isImageType(typeId) || isSampledImageType(typeId)); + return isSampledImageType(typeId) ? module.getInstruction(typeId)->getIdOperand(0) : typeId; + } + bool isArrayedImageType(Id typeId) const + { + assert(isImageType(typeId)); + return module.getInstruction(typeId)->getImmediateOperand(3) != 0; + } + + // For making new constants (will return old constant if the requested one was already made). + Id makeBoolConstant(bool b, bool specConstant = false); + Id makeInt8Constant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); } + Id makeUint8Constant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(8), u, specConstant); } + Id makeInt16Constant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(16), (unsigned)i, specConstant); } + Id makeUint16Constant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(16), u, specConstant); } + Id makeIntConstant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); } + Id makeUintConstant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(32), u, specConstant); } + Id makeInt64Constant(long long i, bool specConstant = false) + { return makeInt64Constant(makeIntType(64), (unsigned long long)i, specConstant); } + Id makeUint64Constant(unsigned long long u, bool specConstant = false) + { return makeInt64Constant(makeUintType(64), u, specConstant); } + Id makeFloatConstant(float f, bool specConstant = false); + Id makeDoubleConstant(double d, bool specConstant = false); + Id makeFloat16Constant(float f16, bool specConstant = false); + Id makeFpConstant(Id type, double d, bool specConstant = false); + + // Turn the array of constants into a proper spv constant of the requested type. + Id makeCompositeConstant(Id type, const std::vector& comps, bool specConst = false); + + // Methods for adding information outside the CFG. + Instruction* addEntryPoint(ExecutionModel, Function*, const char* name); + void addExecutionMode(Function*, ExecutionMode mode, int value1 = -1, int value2 = -1, int value3 = -1); + void addName(Id, const char* name); + void addMemberName(Id, int member, const char* name); + void addDecoration(Id, Decoration, int num = -1); + void addDecoration(Id, Decoration, const char*); + void addDecorationId(Id id, Decoration, Id idDecoration); + void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1); + void addMemberDecoration(Id, unsigned int member, Decoration, const char*); + + // At the end of what block do the next create*() instructions go? + void setBuildPoint(Block* bp) { buildPoint = bp; } + Block* getBuildPoint() const { return buildPoint; } + + // Make the entry-point function. The returned pointer is only valid + // for the lifetime of this builder. + Function* makeEntryPoint(const char*); + + // Make a shader-style function, and create its entry block if entry is non-zero. + // Return the function, pass back the entry. + // The returned pointer is only valid for the lifetime of this builder. + Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, + const std::vector& paramTypes, const std::vector>& precisions, Block **entry = 0); + + // Create a return. An 'implicit' return is one not appearing in the source + // code. In the case of an implicit return, no post-return block is inserted. + void makeReturn(bool implicit, Id retVal = 0); + + // Generate all the code needed to finish up a function. + void leaveFunction(); + + // Create a discard. + void makeDiscard(); + + // Create a global or function local or IO variable. + Id createVariable(StorageClass, Id type, const char* name = 0, Id initializer = NoResult); + + // Create an intermediate with an undefined value. + Id createUndefined(Id type); + + // Store into an Id and return the l-value + void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + + // Load from an Id and return it + Id createLoad(Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + + // Create an OpAccessChain instruction + Id createAccessChain(StorageClass, Id base, const std::vector& offsets); + + // Create an OpArrayLength instruction + Id createArrayLength(Id base, unsigned int member); + + // Create an OpCooperativeMatrixLengthNV instruction + Id createCooperativeMatrixLength(Id type); + + // Create an OpCompositeExtract instruction + Id createCompositeExtract(Id composite, Id typeId, unsigned index); + Id createCompositeExtract(Id composite, Id typeId, const std::vector& indexes); + Id createCompositeInsert(Id object, Id composite, Id typeId, unsigned index); + Id createCompositeInsert(Id object, Id composite, Id typeId, const std::vector& indexes); + + Id createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex); + Id createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex); + + void createNoResultOp(Op); + void createNoResultOp(Op, Id operand); + void createNoResultOp(Op, const std::vector& operands); + void createNoResultOp(Op, const std::vector& operands); + void createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask); + void createMemoryBarrier(unsigned executionScope, unsigned memorySemantics); + Id createUnaryOp(Op, Id typeId, Id operand); + Id createBinOp(Op, Id typeId, Id operand1, Id operand2); + Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3); + Id createOp(Op, Id typeId, const std::vector& operands); + Id createOp(Op, Id typeId, const std::vector& operands); + Id createFunctionCall(spv::Function*, const std::vector&); + Id createSpecConstantOp(Op, Id typeId, const std::vector& operands, const std::vector& literals); + + // Take an rvalue (source) and a set of channels to extract from it to + // make a new rvalue, which is returned. + Id createRvalueSwizzle(Decoration precision, Id typeId, Id source, const std::vector& channels); + + // Take a copy of an lvalue (target) and a source of components, and set the + // source components into the lvalue where the 'channels' say to put them. + // An updated version of the target is returned. + // (No true lvalue or stores are used.) + Id createLvalueSwizzle(Id typeId, Id target, Id source, const std::vector& channels); + + // If both the id and precision are valid, the id + // gets tagged with the requested precision. + // The passed in id is always the returned id, to simplify use patterns. + Id setPrecision(Id id, Decoration precision) + { + if (precision != NoPrecision && id != NoResult) + addDecoration(id, precision); + + return id; + } + + // Can smear a scalar to a vector for the following forms: + // - promoteScalar(scalar, vector) // smear scalar to width of vector + // - promoteScalar(vector, scalar) // smear scalar to width of vector + // - promoteScalar(pointer, scalar) // smear scalar to width of what pointer points to + // - promoteScalar(scalar, scalar) // do nothing + // Other forms are not allowed. + // + // Generally, the type of 'scalar' does not need to be the same type as the components in 'vector'. + // The type of the created vector is a vector of components of the same type as the scalar. + // + // Note: One of the arguments will change, with the result coming back that way rather than + // through the return value. + void promoteScalar(Decoration precision, Id& left, Id& right); + + // Make a value by smearing the scalar to fill the type. + // vectorType should be the correct type for making a vector of scalarVal. + // (No conversions are done.) + Id smearScalar(Decoration precision, Id scalarVal, Id vectorType); + + // Create a call to a built-in function. + Id createBuiltinCall(Id resultType, Id builtins, int entryPoint, const std::vector& args); + + // List of parameters used to create a texture operation + struct TextureParameters { + Id sampler; + Id coords; + Id bias; + Id lod; + Id Dref; + Id offset; + Id offsets; + Id gradX; + Id gradY; + Id sample; + Id component; + Id texelOut; + Id lodClamp; + Id granularity; + Id coarse; + bool nonprivate; + bool volatil; + }; + + // Select the correct texture operation based on all inputs, and emit the correct instruction + Id createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, + bool noImplicit, const TextureParameters&, ImageOperandsMask); + + // Emit the OpTextureQuery* instruction that was passed in. + // Figure out the right return value and type, and return it. + Id createTextureQueryCall(Op, const TextureParameters&, bool isUnsignedResult); + + Id createSamplePositionCall(Decoration precision, Id, Id); + + Id createBitFieldExtractCall(Decoration precision, Id, Id, Id, bool isSigned); + Id createBitFieldInsertCall(Decoration precision, Id, Id, Id, Id); + + // Reduction comparison for composites: For equal and not-equal resulting in a scalar. + Id createCompositeCompare(Decoration precision, Id, Id, bool /* true if for equal, false if for not-equal */); + + // OpCompositeConstruct + Id createCompositeConstruct(Id typeId, const std::vector& constituents); + + // vector or scalar constructor + Id createConstructor(Decoration precision, const std::vector& sources, Id resultTypeId); + + // matrix constructor + Id createMatrixConstructor(Decoration precision, const std::vector& sources, Id constructee); + + // Helper to use for building nested control flow with if-then-else. + class If { + public: + If(Id condition, unsigned int ctrl, Builder& builder); + ~If() {} + + void makeBeginElse(); + void makeEndIf(); + + private: + If(const If&); + If& operator=(If&); + + Builder& builder; + Id condition; + unsigned int control; + Function* function; + Block* headerBlock; + Block* thenBlock; + Block* elseBlock; + Block* mergeBlock; + }; + + // Make a switch statement. A switch has 'numSegments' of pieces of code, not containing + // any case/default labels, all separated by one or more case/default labels. Each possible + // case value v is a jump to the caseValues[v] segment. The defaultSegment is also in this + // number space. How to compute the value is given by 'condition', as in switch(condition). + // + // The SPIR-V Builder will maintain the stack of post-switch merge blocks for nested switches. + // + // Use a defaultSegment < 0 if there is no default segment (to branch to post switch). + // + // Returns the right set of basic blocks to start each code segment with, so that the caller's + // recursion stack can hold the memory for it. + // + void makeSwitch(Id condition, unsigned int control, int numSegments, const std::vector& caseValues, + const std::vector& valueToSegment, int defaultSegment, std::vector& segmentBB); + + // Add a branch to the innermost switch's merge block. + void addSwitchBreak(); + + // Move to the next code segment, passing in the return argument in makeSwitch() + void nextSwitchSegment(std::vector& segmentBB, int segment); + + // Finish off the innermost switch. + void endSwitch(std::vector& segmentBB); + + struct LoopBlocks { + LoopBlocks(Block& head, Block& body, Block& merge, Block& continue_target) : + head(head), body(body), merge(merge), continue_target(continue_target) { } + Block &head, &body, &merge, &continue_target; + private: + LoopBlocks(); + LoopBlocks& operator=(const LoopBlocks&) = delete; + }; + + // Start a new loop and prepare the builder to generate code for it. Until + // closeLoop() is called for this loop, createLoopContinue() and + // createLoopExit() will target its corresponding blocks. + LoopBlocks& makeNewLoop(); + + // Create a new block in the function containing the build point. Memory is + // owned by the function object. + Block& makeNewBlock(); + + // Add a branch to the continue_target of the current (innermost) loop. + void createLoopContinue(); + + // Add an exit (e.g. "break") from the innermost loop that we're currently + // in. + void createLoopExit(); + + // Close the innermost loop that you're in + void closeLoop(); + + // + // Access chain design for an R-Value vs. L-Value: + // + // There is a single access chain the builder is building at + // any particular time. Such a chain can be used to either to a load or + // a store, when desired. + // + // Expressions can be r-values, l-values, or both, or only r-values: + // a[b.c].d = .... // l-value + // ... = a[b.c].d; // r-value, that also looks like an l-value + // ++a[b.c].d; // r-value and l-value + // (x + y)[2]; // r-value only, can't possibly be l-value + // + // Computing an r-value means generating code. Hence, + // r-values should only be computed when they are needed, not speculatively. + // + // Computing an l-value means saving away information for later use in the compiler, + // no code is generated until the l-value is later dereferenced. It is okay + // to speculatively generate an l-value, just not okay to speculatively dereference it. + // + // The base of the access chain (the left-most variable or expression + // from which everything is based) can be set either as an l-value + // or as an r-value. Most efficient would be to set an l-value if one + // is available. If an expression was evaluated, the resulting r-value + // can be set as the chain base. + // + // The users of this single access chain can save and restore if they + // want to nest or manage multiple chains. + // + + struct AccessChain { + Id base; // for l-values, pointer to the base object, for r-values, the base object + std::vector indexChain; + Id instr; // cache the instruction that generates this access chain + std::vector swizzle; // each std::vector element selects the next GLSL component number + Id component; // a dynamic component index, can coexist with a swizzle, + // done after the swizzle, NoResult if not present + Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied; + // NoType unless a swizzle or component is present + bool isRValue; // true if 'base' is an r-value, otherwise, base is an l-value + unsigned int alignment; // bitwise OR of alignment values passed in. Accumulates worst alignment. + // Only tracks base and (optional) component selection alignment. + + // Accumulate whether anything in the chain of structures has coherent decorations. + struct CoherentFlags { + CoherentFlags() { clear(); } +#ifdef GLSLANG_WEB + void clear() { } + bool isVolatile() const { return false; } + CoherentFlags operator |=(const CoherentFlags &other) { return *this; } +#else + bool isVolatile() const { return volatil; } + bool anyCoherent() const { + return coherent || devicecoherent || queuefamilycoherent || workgroupcoherent || + subgroupcoherent || shadercallcoherent; + } + + unsigned coherent : 1; + unsigned devicecoherent : 1; + unsigned queuefamilycoherent : 1; + unsigned workgroupcoherent : 1; + unsigned subgroupcoherent : 1; + unsigned shadercallcoherent : 1; + unsigned nonprivate : 1; + unsigned volatil : 1; + unsigned isImage : 1; + + void clear() { + coherent = 0; + devicecoherent = 0; + queuefamilycoherent = 0; + workgroupcoherent = 0; + subgroupcoherent = 0; + shadercallcoherent = 0; + nonprivate = 0; + volatil = 0; + isImage = 0; + } + + CoherentFlags operator |=(const CoherentFlags &other) { + coherent |= other.coherent; + devicecoherent |= other.devicecoherent; + queuefamilycoherent |= other.queuefamilycoherent; + workgroupcoherent |= other.workgroupcoherent; + subgroupcoherent |= other.subgroupcoherent; + shadercallcoherent |= other.shadercallcoherent; + nonprivate |= other.nonprivate; + volatil |= other.volatil; + isImage |= other.isImage; + return *this; + } +#endif + }; + CoherentFlags coherentFlags; + }; + + // + // the SPIR-V builder maintains a single active chain that + // the following methods operate on + // + + // for external save and restore + AccessChain getAccessChain() { return accessChain; } + void setAccessChain(AccessChain newChain) { accessChain = newChain; } + + // clear accessChain + void clearAccessChain(); + + // set new base as an l-value base + void setAccessChainLValue(Id lValue) + { + assert(isPointer(lValue)); + accessChain.base = lValue; + } + + // set new base value as an r-value + void setAccessChainRValue(Id rValue) + { + accessChain.isRValue = true; + accessChain.base = rValue; + } + + // push offset onto the end of the chain + void accessChainPush(Id offset, AccessChain::CoherentFlags coherentFlags, unsigned int alignment) + { + accessChain.indexChain.push_back(offset); + accessChain.coherentFlags |= coherentFlags; + accessChain.alignment |= alignment; + } + + // push new swizzle onto the end of any existing swizzle, merging into a single swizzle + void accessChainPushSwizzle(std::vector& swizzle, Id preSwizzleBaseType, + AccessChain::CoherentFlags coherentFlags, unsigned int alignment); + + // push a dynamic component selection onto the access chain, only applicable with a + // non-trivial swizzle or no swizzle + void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, + unsigned int alignment) + { + if (accessChain.swizzle.size() != 1) { + accessChain.component = component; + if (accessChain.preSwizzleBaseType == NoType) + accessChain.preSwizzleBaseType = preSwizzleBaseType; + } + accessChain.coherentFlags |= coherentFlags; + accessChain.alignment |= alignment; + } + + // use accessChain and swizzle to store value + void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + + // use accessChain and swizzle to load an r-value + Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType, + spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, + unsigned int alignment = 0); + + // Return whether or not the access chain can be represented in SPIR-V + // as an l-value. + // E.g., a[3].yx cannot be, while a[3].y and a[3].y[x] can be. + bool isSpvLvalue() const { return accessChain.swizzle.size() <= 1; } + + // get the direct pointer for an l-value + Id accessChainGetLValue(); + + // Get the inferred SPIR-V type of the result of the current access chain, + // based on the type of the base and the chain of dereferences. + Id accessChainGetInferredType(); + + // Add capabilities, extensions, remove unneeded decorations, etc., + // based on the resulting SPIR-V. + void postProcess(); + + // Prune unreachable blocks in the CFG and remove unneeded decorations. + void postProcessCFG(); + +#ifndef GLSLANG_WEB + // Add capabilities, extensions based on instructions in the module. + void postProcessFeatures(); + // Hook to visit each instruction in a block in a function + void postProcess(Instruction&); + // Hook to visit each non-32-bit sized float/int operation in a block. + void postProcessType(const Instruction&, spv::Id typeId); +#endif + + void dump(std::vector&) const; + + void createBranch(Block* block); + void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock); + void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, + const std::vector& operands); + + // Sets to generate opcode for specialization constants. + void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; } + // Sets to generate opcode for non-specialization constants (normal mode). + void setToNormalCodeGenMode() { generatingOpCodeForSpecConst = false; } + // Check if the builder is generating code for spec constants. + bool isInSpecConstCodeGenMode() { return generatingOpCodeForSpecConst; } + + protected: + Id makeIntConstant(Id typeId, unsigned value, bool specConstant); + Id makeInt64Constant(Id typeId, unsigned long long value, bool specConstant); + Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value); + Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2); + Id findCompositeConstant(Op typeClass, Id typeId, const std::vector& comps); + Id findStructConstant(Id typeId, const std::vector& comps); + Id collapseAccessChain(); + void remapDynamicSwizzle(); + void transferAccessChainSwizzle(bool dynamic); + void simplifyAccessChainSwizzle(); + void createAndSetNoPredecessorBlock(const char*); + void createSelectionMerge(Block* mergeBlock, unsigned int control); + void dumpSourceInstructions(std::vector&) const; + void dumpSourceInstructions(const spv::Id fileId, const std::string& text, std::vector&) const; + void dumpInstructions(std::vector&, const std::vector >&) const; + void dumpModuleProcesses(std::vector&) const; + spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) + const; + + unsigned int spvVersion; // the version of SPIR-V to emit in the header + SourceLanguage source; + int sourceVersion; + spv::Id sourceFileStringId; + std::string sourceText; + int currentLine; + const char* currentFile; + bool emitOpLines; + std::set extensions; + std::vector sourceExtensions; + std::vector moduleProcesses; + AddressingModel addressModel; + MemoryModel memoryModel; + std::set capabilities; + int builderNumber; + Module module; + Block* buildPoint; + Id uniqueId; + Function* entryPointFunction; + bool generatingOpCodeForSpecConst; + AccessChain accessChain; + + // special blocks of instructions for output + std::vector > strings; + std::vector > imports; + std::vector > entryPoints; + std::vector > executionModes; + std::vector > names; + std::vector > decorations; + std::vector > constantsTypesGlobals; + std::vector > externals; + std::vector > functions; + + // not output, internally used for quick & dirty canonical (unique) creation + + // map type opcodes to constant inst. + std::unordered_map> groupedConstants; + // map struct-id to constant instructions + std::unordered_map> groupedStructConstants; + // map type opcodes to type instructions + std::unordered_map> groupedTypes; + + // stack of switches + std::stack switchMerges; + + // Our loop stack. + std::stack loops; + + // map from strings to their string ids + std::unordered_map stringIds; + + // map from include file name ids to their contents + std::map includeFiles; + + // The stream for outputting warnings and errors. + SpvBuildLogger* logger; +}; // end Builder class + +}; // end spv namespace + +#endif // SpvBuilder_H diff --git a/android/armeabi-v7a/include/SPIRV/SpvTools.h b/android/armeabi-v7a/include/SPIRV/SpvTools.h new file mode 100644 index 00000000..59c914da --- /dev/null +++ b/android/armeabi-v7a/include/SPIRV/SpvTools.h @@ -0,0 +1,82 @@ +// +// Copyright (C) 2014-2016 LunarG, Inc. +// Copyright (C) 2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Call into SPIRV-Tools to disassemble, validate, and optimize. +// + +#pragma once +#ifndef GLSLANG_SPV_TOOLS_H +#define GLSLANG_SPV_TOOLS_H + +#ifdef ENABLE_OPT +#include +#include +#endif + +#include "glslang/MachineIndependent/localintermediate.h" +#include "Logger.h" + +namespace glslang { + +struct SpvOptions { + SpvOptions() : generateDebugInfo(false), disableOptimizer(true), + optimizeSize(false), disassemble(false), validate(false) { } + bool generateDebugInfo; + bool disableOptimizer; + bool optimizeSize; + bool disassemble; + bool validate; +}; + +#ifdef ENABLE_OPT + +// Use the SPIRV-Tools disassembler to print SPIR-V. +void SpirvToolsDisassemble(std::ostream& out, const std::vector& spirv); + +// Apply the SPIRV-Tools validator to generated SPIR-V. +void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger*, bool prelegalization); + +// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of +// legalizing HLSL SPIR-V. +void SpirvToolsLegalize(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger*, const SpvOptions*); + +#endif + +} // end namespace glslang + +#endif // GLSLANG_SPV_TOOLS_H diff --git a/android/armeabi-v7a/include/SPIRV/bitutils.h b/android/armeabi-v7a/include/SPIRV/bitutils.h new file mode 100644 index 00000000..22e44cec --- /dev/null +++ b/android/armeabi-v7a/include/SPIRV/bitutils.h @@ -0,0 +1,81 @@ +// Copyright (c) 2015-2016 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef LIBSPIRV_UTIL_BITUTILS_H_ +#define LIBSPIRV_UTIL_BITUTILS_H_ + +#include +#include + +namespace spvutils { + +// Performs a bitwise copy of source to the destination type Dest. +template +Dest BitwiseCast(Src source) { + Dest dest; + static_assert(sizeof(source) == sizeof(dest), + "BitwiseCast: Source and destination must have the same size"); + std::memcpy(static_cast(&dest), &source, sizeof(dest)); + return dest; +} + +// SetBits returns an integer of type with bits set +// for position through , counting from the least +// significant bit. In particular when Num == 0, no positions are set to 1. +// A static assert will be triggered if First + Num > sizeof(T) * 8, that is, +// a bit that will not fit in the underlying type is set. +template +struct SetBits { + static_assert(First < sizeof(T) * 8, + "Tried to set a bit that is shifted too far."); + const static T get = (T(1) << First) | SetBits::get; +}; + +template +struct SetBits { + const static T get = T(0); +}; + +// This is all compile-time so we can put our tests right here. +static_assert(SetBits::get == uint32_t(0x00000000), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x00000001), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x80000000), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x00000006), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0xc0000000), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x7FFFFFFF), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0xFFFFFFFF), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0xFFFF0000), + "SetBits failed"); + +static_assert(SetBits::get == uint64_t(0x0000000000000001LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0x8000000000000000LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0xc000000000000000LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0x0000000080000000LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0x00000000FFFF0000LL), + "SetBits failed"); + +} // namespace spvutils + +#endif // LIBSPIRV_UTIL_BITUTILS_H_ diff --git a/android/armeabi-v7a/include/SPIRV/disassemble.h b/android/armeabi-v7a/include/SPIRV/disassemble.h new file mode 100644 index 00000000..b6a46357 --- /dev/null +++ b/android/armeabi-v7a/include/SPIRV/disassemble.h @@ -0,0 +1,53 @@ +// +// Copyright (C) 2014-2015 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Disassembler for SPIR-V. +// + +#pragma once +#ifndef disassembler_H +#define disassembler_H + +#include +#include + +namespace spv { + + // disassemble with glslang custom disassembler + void Disassemble(std::ostream& out, const std::vector&); + +} // end namespace spv + +#endif // disassembler_H diff --git a/android/armeabi-v7a/include/SPIRV/doc.h b/android/armeabi-v7a/include/SPIRV/doc.h new file mode 100644 index 00000000..293256a2 --- /dev/null +++ b/android/armeabi-v7a/include/SPIRV/doc.h @@ -0,0 +1,258 @@ +// +// Copyright (C) 2014-2015 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Parameterize the SPIR-V enumerants. +// + +#pragma once + +#include "spirv.hpp" + +#include + +namespace spv { + +// Fill in all the parameters +void Parameterize(); + +// Return the English names of all the enums. +const char* SourceString(int); +const char* AddressingString(int); +const char* MemoryString(int); +const char* ExecutionModelString(int); +const char* ExecutionModeString(int); +const char* StorageClassString(int); +const char* DecorationString(int); +const char* BuiltInString(int); +const char* DimensionString(int); +const char* SelectControlString(int); +const char* LoopControlString(int); +const char* FunctionControlString(int); +const char* SamplerAddressingModeString(int); +const char* SamplerFilterModeString(int); +const char* ImageFormatString(int); +const char* ImageChannelOrderString(int); +const char* ImageChannelTypeString(int); +const char* ImageChannelDataTypeString(int type); +const char* ImageOperandsString(int format); +const char* ImageOperands(int); +const char* FPFastMathString(int); +const char* FPRoundingModeString(int); +const char* LinkageTypeString(int); +const char* FuncParamAttrString(int); +const char* AccessQualifierString(int); +const char* MemorySemanticsString(int); +const char* MemoryAccessString(int); +const char* ExecutionScopeString(int); +const char* GroupOperationString(int); +const char* KernelEnqueueFlagsString(int); +const char* KernelProfilingInfoString(int); +const char* CapabilityString(int); +const char* OpcodeString(int); +const char* ScopeString(int mem); + +// For grouping opcodes into subsections +enum OpcodeClass { + OpClassMisc, + OpClassDebug, + OpClassAnnotate, + OpClassExtension, + OpClassMode, + OpClassType, + OpClassConstant, + OpClassMemory, + OpClassFunction, + OpClassImage, + OpClassConvert, + OpClassComposite, + OpClassArithmetic, + OpClassBit, + OpClassRelationalLogical, + OpClassDerivative, + OpClassFlowControl, + OpClassAtomic, + OpClassPrimitive, + OpClassBarrier, + OpClassGroup, + OpClassDeviceSideEnqueue, + OpClassPipe, + + OpClassCount, + OpClassMissing // all instructions start out as missing +}; + +// For parameterizing operands. +enum OperandClass { + OperandNone, + OperandId, + OperandVariableIds, + OperandOptionalLiteral, + OperandOptionalLiteralString, + OperandVariableLiterals, + OperandVariableIdLiteral, + OperandVariableLiteralId, + OperandLiteralNumber, + OperandLiteralString, + OperandSource, + OperandExecutionModel, + OperandAddressing, + OperandMemory, + OperandExecutionMode, + OperandStorage, + OperandDimensionality, + OperandSamplerAddressingMode, + OperandSamplerFilterMode, + OperandSamplerImageFormat, + OperandImageChannelOrder, + OperandImageChannelDataType, + OperandImageOperands, + OperandFPFastMath, + OperandFPRoundingMode, + OperandLinkageType, + OperandAccessQualifier, + OperandFuncParamAttr, + OperandDecoration, + OperandBuiltIn, + OperandSelect, + OperandLoop, + OperandFunction, + OperandMemorySemantics, + OperandMemoryAccess, + OperandScope, + OperandGroupOperation, + OperandKernelEnqueueFlags, + OperandKernelProfilingInfo, + OperandCapability, + + OperandOpcode, + + OperandCount +}; + +// Any specific enum can have a set of capabilities that allow it: +typedef std::vector EnumCaps; + +// Parameterize a set of operands with their OperandClass(es) and descriptions. +class OperandParameters { +public: + OperandParameters() { } + void push(OperandClass oc, const char* d, bool opt = false) + { + opClass.push_back(oc); + desc.push_back(d); + optional.push_back(opt); + } + void setOptional(); + OperandClass getClass(int op) const { return opClass[op]; } + const char* getDesc(int op) const { return desc[op]; } + bool isOptional(int op) const { return optional[op]; } + int getNum() const { return (int)opClass.size(); } + +protected: + std::vector opClass; + std::vector desc; + std::vector optional; +}; + +// Parameterize an enumerant +class EnumParameters { +public: + EnumParameters() : desc(0) { } + const char* desc; +}; + +// Parameterize a set of enumerants that form an enum +class EnumDefinition : public EnumParameters { +public: + EnumDefinition() : + ceiling(0), bitmask(false), getName(0), enumParams(0), operandParams(0) { } + void set(int ceil, const char* (*name)(int), EnumParameters* ep, bool mask = false) + { + ceiling = ceil; + getName = name; + bitmask = mask; + enumParams = ep; + } + void setOperands(OperandParameters* op) { operandParams = op; } + int ceiling; // ceiling of enumerants + bool bitmask; // true if these enumerants combine into a bitmask + const char* (*getName)(int); // a function that returns the name for each enumerant value (or shift) + EnumParameters* enumParams; // parameters for each individual enumerant + OperandParameters* operandParams; // sets of operands +}; + +// Parameterize an instruction's logical format, including its known set of operands, +// per OperandParameters above. +class InstructionParameters { +public: + InstructionParameters() : + opDesc("TBD"), + opClass(OpClassMissing), + typePresent(true), // most normal, only exceptions have to be spelled out + resultPresent(true) // most normal, only exceptions have to be spelled out + { } + + void setResultAndType(bool r, bool t) + { + resultPresent = r; + typePresent = t; + } + + bool hasResult() const { return resultPresent != 0; } + bool hasType() const { return typePresent != 0; } + + const char* opDesc; + OpcodeClass opClass; + OperandParameters operands; + +protected: + int typePresent : 1; + int resultPresent : 1; +}; + +// The set of objects that hold all the instruction/operand +// parameterization information. +extern InstructionParameters InstructionDesc[]; + +// These hold definitions of the enumerants used for operands +extern EnumDefinition OperandClassParams[]; + +const char* GetOperandDesc(OperandClass operand); +void PrintImmediateRow(int imm, const char* name, const EnumParameters* enumParams, bool caps, bool hex = false); +const char* AccessQualifierString(int attr); + +void PrintOperands(const OperandParameters& operands, int reservedOperands); + +} // end namespace spv diff --git a/android/armeabi-v7a/include/SPIRV/hex_float.h b/android/armeabi-v7a/include/SPIRV/hex_float.h new file mode 100644 index 00000000..8be8e9f7 --- /dev/null +++ b/android/armeabi-v7a/include/SPIRV/hex_float.h @@ -0,0 +1,1078 @@ +// Copyright (c) 2015-2016 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef LIBSPIRV_UTIL_HEX_FLOAT_H_ +#define LIBSPIRV_UTIL_HEX_FLOAT_H_ + +#include +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) && _MSC_VER < 1800 +namespace std { +bool isnan(double f) +{ + return ::_isnan(f) != 0; +} +bool isinf(double f) +{ + return ::_finite(f) == 0; +} +} +#endif + +#include "bitutils.h" + +namespace spvutils { + +class Float16 { + public: + Float16(uint16_t v) : val(v) {} + Float16() {} + static bool isNan(const Float16& val) { + return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) != 0); + } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(const Float16& val) { + return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) == 0); + } + Float16(const Float16& other) { val = other.val; } + uint16_t get_value() const { return val; } + + // Returns the maximum normal value. + static Float16 max() { return Float16(0x7bff); } + // Returns the lowest normal value. + static Float16 lowest() { return Float16(0xfbff); } + + private: + uint16_t val; +}; + +// To specialize this type, you must override uint_type to define +// an unsigned integer that can fit your floating point type. +// You must also add a isNan function that returns true if +// a value is Nan. +template +struct FloatProxyTraits { + typedef void uint_type; +}; + +template <> +struct FloatProxyTraits { + typedef uint32_t uint_type; + static bool isNan(float f) { return std::isnan(f); } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(float f) { return std::isinf(f); } + // Returns the maximum normal value. + static float max() { return std::numeric_limits::max(); } + // Returns the lowest normal value. + static float lowest() { return std::numeric_limits::lowest(); } +}; + +template <> +struct FloatProxyTraits { + typedef uint64_t uint_type; + static bool isNan(double f) { return std::isnan(f); } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(double f) { return std::isinf(f); } + // Returns the maximum normal value. + static double max() { return std::numeric_limits::max(); } + // Returns the lowest normal value. + static double lowest() { return std::numeric_limits::lowest(); } +}; + +template <> +struct FloatProxyTraits { + typedef uint16_t uint_type; + static bool isNan(Float16 f) { return Float16::isNan(f); } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(Float16 f) { return Float16::isInfinity(f); } + // Returns the maximum normal value. + static Float16 max() { return Float16::max(); } + // Returns the lowest normal value. + static Float16 lowest() { return Float16::lowest(); } +}; + +// Since copying a floating point number (especially if it is NaN) +// does not guarantee that bits are preserved, this class lets us +// store the type and use it as a float when necessary. +template +class FloatProxy { + public: + typedef typename FloatProxyTraits::uint_type uint_type; + + // Since this is to act similar to the normal floats, + // do not initialize the data by default. + FloatProxy() {} + + // Intentionally non-explicit. This is a proxy type so + // implicit conversions allow us to use it more transparently. + FloatProxy(T val) { data_ = BitwiseCast(val); } + + // Intentionally non-explicit. This is a proxy type so + // implicit conversions allow us to use it more transparently. + FloatProxy(uint_type val) { data_ = val; } + + // This is helpful to have and is guaranteed not to stomp bits. + FloatProxy operator-() const { + return static_cast(data_ ^ + (uint_type(0x1) << (sizeof(T) * 8 - 1))); + } + + // Returns the data as a floating point value. + T getAsFloat() const { return BitwiseCast(data_); } + + // Returns the raw data. + uint_type data() const { return data_; } + + // Returns true if the value represents any type of NaN. + bool isNan() { return FloatProxyTraits::isNan(getAsFloat()); } + // Returns true if the value represents any type of infinity. + bool isInfinity() { return FloatProxyTraits::isInfinity(getAsFloat()); } + + // Returns the maximum normal value. + static FloatProxy max() { + return FloatProxy(FloatProxyTraits::max()); + } + // Returns the lowest normal value. + static FloatProxy lowest() { + return FloatProxy(FloatProxyTraits::lowest()); + } + + private: + uint_type data_; +}; + +template +bool operator==(const FloatProxy& first, const FloatProxy& second) { + return first.data() == second.data(); +} + +// Reads a FloatProxy value as a normal float from a stream. +template +std::istream& operator>>(std::istream& is, FloatProxy& value) { + T float_val; + is >> float_val; + value = FloatProxy(float_val); + return is; +} + +// This is an example traits. It is not meant to be used in practice, but will +// be the default for any non-specialized type. +template +struct HexFloatTraits { + // Integer type that can store this hex-float. + typedef void uint_type; + // Signed integer type that can store this hex-float. + typedef void int_type; + // The numerical type that this HexFloat represents. + typedef void underlying_type; + // The type needed to construct the underlying type. + typedef void native_type; + // The number of bits that are actually relevant in the uint_type. + // This allows us to deal with, for example, 24-bit values in a 32-bit + // integer. + static const uint32_t num_used_bits = 0; + // Number of bits that represent the exponent. + static const uint32_t num_exponent_bits = 0; + // Number of bits that represent the fractional part. + static const uint32_t num_fraction_bits = 0; + // The bias of the exponent. (How much we need to subtract from the stored + // value to get the correct value.) + static const uint32_t exponent_bias = 0; +}; + +// Traits for IEEE float. +// 1 sign bit, 8 exponent bits, 23 fractional bits. +template <> +struct HexFloatTraits> { + typedef uint32_t uint_type; + typedef int32_t int_type; + typedef FloatProxy underlying_type; + typedef float native_type; + static const uint_type num_used_bits = 32; + static const uint_type num_exponent_bits = 8; + static const uint_type num_fraction_bits = 23; + static const uint_type exponent_bias = 127; +}; + +// Traits for IEEE double. +// 1 sign bit, 11 exponent bits, 52 fractional bits. +template <> +struct HexFloatTraits> { + typedef uint64_t uint_type; + typedef int64_t int_type; + typedef FloatProxy underlying_type; + typedef double native_type; + static const uint_type num_used_bits = 64; + static const uint_type num_exponent_bits = 11; + static const uint_type num_fraction_bits = 52; + static const uint_type exponent_bias = 1023; +}; + +// Traits for IEEE half. +// 1 sign bit, 5 exponent bits, 10 fractional bits. +template <> +struct HexFloatTraits> { + typedef uint16_t uint_type; + typedef int16_t int_type; + typedef uint16_t underlying_type; + typedef uint16_t native_type; + static const uint_type num_used_bits = 16; + static const uint_type num_exponent_bits = 5; + static const uint_type num_fraction_bits = 10; + static const uint_type exponent_bias = 15; +}; + +enum round_direction { + kRoundToZero, + kRoundToNearestEven, + kRoundToPositiveInfinity, + kRoundToNegativeInfinity +}; + +// Template class that houses a floating pointer number. +// It exposes a number of constants based on the provided traits to +// assist in interpreting the bits of the value. +template > +class HexFloat { + public: + typedef typename Traits::uint_type uint_type; + typedef typename Traits::int_type int_type; + typedef typename Traits::underlying_type underlying_type; + typedef typename Traits::native_type native_type; + + explicit HexFloat(T f) : value_(f) {} + + T value() const { return value_; } + void set_value(T f) { value_ = f; } + + // These are all written like this because it is convenient to have + // compile-time constants for all of these values. + + // Pass-through values to save typing. + static const uint32_t num_used_bits = Traits::num_used_bits; + static const uint32_t exponent_bias = Traits::exponent_bias; + static const uint32_t num_exponent_bits = Traits::num_exponent_bits; + static const uint32_t num_fraction_bits = Traits::num_fraction_bits; + + // Number of bits to shift left to set the highest relevant bit. + static const uint32_t top_bit_left_shift = num_used_bits - 1; + // How many nibbles (hex characters) the fractional part takes up. + static const uint32_t fraction_nibbles = (num_fraction_bits + 3) / 4; + // If the fractional part does not fit evenly into a hex character (4-bits) + // then we have to left-shift to get rid of leading 0s. This is the amount + // we have to shift (might be 0). + static const uint32_t num_overflow_bits = + fraction_nibbles * 4 - num_fraction_bits; + + // The representation of the fraction, not the actual bits. This + // includes the leading bit that is usually implicit. + static const uint_type fraction_represent_mask = + spvutils::SetBits::get; + + // The topmost bit in the nibble-aligned fraction. + static const uint_type fraction_top_bit = + uint_type(1) << (num_fraction_bits + num_overflow_bits - 1); + + // The least significant bit in the exponent, which is also the bit + // immediately to the left of the significand. + static const uint_type first_exponent_bit = uint_type(1) + << (num_fraction_bits); + + // The mask for the encoded fraction. It does not include the + // implicit bit. + static const uint_type fraction_encode_mask = + spvutils::SetBits::get; + + // The bit that is used as a sign. + static const uint_type sign_mask = uint_type(1) << top_bit_left_shift; + + // The bits that represent the exponent. + static const uint_type exponent_mask = + spvutils::SetBits::get; + + // How far left the exponent is shifted. + static const uint32_t exponent_left_shift = num_fraction_bits; + + // How far from the right edge the fraction is shifted. + static const uint32_t fraction_right_shift = + static_cast(sizeof(uint_type) * 8) - num_fraction_bits; + + // The maximum representable unbiased exponent. + static const int_type max_exponent = + (exponent_mask >> num_fraction_bits) - exponent_bias; + // The minimum representable exponent for normalized numbers. + static const int_type min_exponent = -static_cast(exponent_bias); + + // Returns the bits associated with the value. + uint_type getBits() const { return spvutils::BitwiseCast(value_); } + + // Returns the bits associated with the value, without the leading sign bit. + uint_type getUnsignedBits() const { + return static_cast(spvutils::BitwiseCast(value_) & + ~sign_mask); + } + + // Returns the bits associated with the exponent, shifted to start at the + // lsb of the type. + const uint_type getExponentBits() const { + return static_cast((getBits() & exponent_mask) >> + num_fraction_bits); + } + + // Returns the exponent in unbiased form. This is the exponent in the + // human-friendly form. + const int_type getUnbiasedExponent() const { + return static_cast(getExponentBits() - exponent_bias); + } + + // Returns just the significand bits from the value. + const uint_type getSignificandBits() const { + return getBits() & fraction_encode_mask; + } + + // If the number was normalized, returns the unbiased exponent. + // If the number was denormal, normalize the exponent first. + const int_type getUnbiasedNormalizedExponent() const { + if ((getBits() & ~sign_mask) == 0) { // special case if everything is 0 + return 0; + } + int_type exp = getUnbiasedExponent(); + if (exp == min_exponent) { // We are in denorm land. + uint_type significand_bits = getSignificandBits(); + while ((significand_bits & (first_exponent_bit >> 1)) == 0) { + significand_bits = static_cast(significand_bits << 1); + exp = static_cast(exp - 1); + } + significand_bits &= fraction_encode_mask; + } + return exp; + } + + // Returns the signficand after it has been normalized. + const uint_type getNormalizedSignificand() const { + int_type unbiased_exponent = getUnbiasedNormalizedExponent(); + uint_type significand = getSignificandBits(); + for (int_type i = unbiased_exponent; i <= min_exponent; ++i) { + significand = static_cast(significand << 1); + } + significand &= fraction_encode_mask; + return significand; + } + + // Returns true if this number represents a negative value. + bool isNegative() const { return (getBits() & sign_mask) != 0; } + + // Sets this HexFloat from the individual components. + // Note this assumes EVERY significand is normalized, and has an implicit + // leading one. This means that the only way that this method will set 0, + // is if you set a number so denormalized that it underflows. + // Do not use this method with raw bits extracted from a subnormal number, + // since subnormals do not have an implicit leading 1 in the significand. + // The significand is also expected to be in the + // lowest-most num_fraction_bits of the uint_type. + // The exponent is expected to be unbiased, meaning an exponent of + // 0 actually means 0. + // If underflow_round_up is set, then on underflow, if a number is non-0 + // and would underflow, we round up to the smallest denorm. + void setFromSignUnbiasedExponentAndNormalizedSignificand( + bool negative, int_type exponent, uint_type significand, + bool round_denorm_up) { + bool significand_is_zero = significand == 0; + + if (exponent <= min_exponent) { + // If this was denormalized, then we have to shift the bit on, meaning + // the significand is not zero. + significand_is_zero = false; + significand |= first_exponent_bit; + significand = static_cast(significand >> 1); + } + + while (exponent < min_exponent) { + significand = static_cast(significand >> 1); + ++exponent; + } + + if (exponent == min_exponent) { + if (significand == 0 && !significand_is_zero && round_denorm_up) { + significand = static_cast(0x1); + } + } + + uint_type new_value = 0; + if (negative) { + new_value = static_cast(new_value | sign_mask); + } + exponent = static_cast(exponent + exponent_bias); + assert(exponent >= 0); + + // put it all together + exponent = static_cast((exponent << exponent_left_shift) & + exponent_mask); + significand = static_cast(significand & fraction_encode_mask); + new_value = static_cast(new_value | (exponent | significand)); + value_ = BitwiseCast(new_value); + } + + // Increments the significand of this number by the given amount. + // If this would spill the significand into the implicit bit, + // carry is set to true and the significand is shifted to fit into + // the correct location, otherwise carry is set to false. + // All significands and to_increment are assumed to be within the bounds + // for a valid significand. + static uint_type incrementSignificand(uint_type significand, + uint_type to_increment, bool* carry) { + significand = static_cast(significand + to_increment); + *carry = false; + if (significand & first_exponent_bit) { + *carry = true; + // The implicit 1-bit will have carried, so we should zero-out the + // top bit and shift back. + significand = static_cast(significand & ~first_exponent_bit); + significand = static_cast(significand >> 1); + } + return significand; + } + + // These exist because MSVC throws warnings on negative right-shifts + // even if they are not going to be executed. Eg: + // constant_number < 0? 0: constant_number + // These convert the negative left-shifts into right shifts. + + template + uint_type negatable_left_shift(int_type N, uint_type val) + { + if(N >= 0) + return val << N; + + return val >> -N; + } + + template + uint_type negatable_right_shift(int_type N, uint_type val) + { + if(N >= 0) + return val >> N; + + return val << -N; + } + + // Returns the significand, rounded to fit in a significand in + // other_T. This is shifted so that the most significant + // bit of the rounded number lines up with the most significant bit + // of the returned significand. + template + typename other_T::uint_type getRoundedNormalizedSignificand( + round_direction dir, bool* carry_bit) { + typedef typename other_T::uint_type other_uint_type; + static const int_type num_throwaway_bits = + static_cast(num_fraction_bits) - + static_cast(other_T::num_fraction_bits); + + static const uint_type last_significant_bit = + (num_throwaway_bits < 0) + ? 0 + : negatable_left_shift(num_throwaway_bits, 1u); + static const uint_type first_rounded_bit = + (num_throwaway_bits < 1) + ? 0 + : negatable_left_shift(num_throwaway_bits - 1, 1u); + + static const uint_type throwaway_mask_bits = + num_throwaway_bits > 0 ? num_throwaway_bits : 0; + static const uint_type throwaway_mask = + spvutils::SetBits::get; + + *carry_bit = false; + other_uint_type out_val = 0; + uint_type significand = getNormalizedSignificand(); + // If we are up-casting, then we just have to shift to the right location. + if (num_throwaway_bits <= 0) { + out_val = static_cast(significand); + uint_type shift_amount = static_cast(-num_throwaway_bits); + out_val = static_cast(out_val << shift_amount); + return out_val; + } + + // If every non-representable bit is 0, then we don't have any casting to + // do. + if ((significand & throwaway_mask) == 0) { + return static_cast( + negatable_right_shift(num_throwaway_bits, significand)); + } + + bool round_away_from_zero = false; + // We actually have to narrow the significand here, so we have to follow the + // rounding rules. + switch (dir) { + case kRoundToZero: + break; + case kRoundToPositiveInfinity: + round_away_from_zero = !isNegative(); + break; + case kRoundToNegativeInfinity: + round_away_from_zero = isNegative(); + break; + case kRoundToNearestEven: + // Have to round down, round bit is 0 + if ((first_rounded_bit & significand) == 0) { + break; + } + if (((significand & throwaway_mask) & ~first_rounded_bit) != 0) { + // If any subsequent bit of the rounded portion is non-0 then we round + // up. + round_away_from_zero = true; + break; + } + // We are exactly half-way between 2 numbers, pick even. + if ((significand & last_significant_bit) != 0) { + // 1 for our last bit, round up. + round_away_from_zero = true; + break; + } + break; + } + + if (round_away_from_zero) { + return static_cast( + negatable_right_shift(num_throwaway_bits, incrementSignificand( + significand, last_significant_bit, carry_bit))); + } else { + return static_cast( + negatable_right_shift(num_throwaway_bits, significand)); + } + } + + // Casts this value to another HexFloat. If the cast is widening, + // then round_dir is ignored. If the cast is narrowing, then + // the result is rounded in the direction specified. + // This number will retain Nan and Inf values. + // It will also saturate to Inf if the number overflows, and + // underflow to (0 or min depending on rounding) if the number underflows. + template + void castTo(other_T& other, round_direction round_dir) { + other = other_T(static_cast(0)); + bool negate = isNegative(); + if (getUnsignedBits() == 0) { + if (negate) { + other.set_value(-other.value()); + } + return; + } + uint_type significand = getSignificandBits(); + bool carried = false; + typename other_T::uint_type rounded_significand = + getRoundedNormalizedSignificand(round_dir, &carried); + + int_type exponent = getUnbiasedExponent(); + if (exponent == min_exponent) { + // If we are denormal, normalize the exponent, so that we can encode + // easily. + exponent = static_cast(exponent + 1); + for (uint_type check_bit = first_exponent_bit >> 1; check_bit != 0; + check_bit = static_cast(check_bit >> 1)) { + exponent = static_cast(exponent - 1); + if (check_bit & significand) break; + } + } + + bool is_nan = + (getBits() & exponent_mask) == exponent_mask && significand != 0; + bool is_inf = + !is_nan && + ((exponent + carried) > static_cast(other_T::exponent_bias) || + (significand == 0 && (getBits() & exponent_mask) == exponent_mask)); + + // If we are Nan or Inf we should pass that through. + if (is_inf) { + other.set_value(BitwiseCast( + static_cast( + (negate ? other_T::sign_mask : 0) | other_T::exponent_mask))); + return; + } + if (is_nan) { + typename other_T::uint_type shifted_significand; + shifted_significand = static_cast( + negatable_left_shift( + static_cast(other_T::num_fraction_bits) - + static_cast(num_fraction_bits), significand)); + + // We are some sort of Nan. We try to keep the bit-pattern of the Nan + // as close as possible. If we had to shift off bits so we are 0, then we + // just set the last bit. + other.set_value(BitwiseCast( + static_cast( + (negate ? other_T::sign_mask : 0) | other_T::exponent_mask | + (shifted_significand == 0 ? 0x1 : shifted_significand)))); + return; + } + + bool round_underflow_up = + isNegative() ? round_dir == kRoundToNegativeInfinity + : round_dir == kRoundToPositiveInfinity; + typedef typename other_T::int_type other_int_type; + // setFromSignUnbiasedExponentAndNormalizedSignificand will + // zero out any underflowing value (but retain the sign). + other.setFromSignUnbiasedExponentAndNormalizedSignificand( + negate, static_cast(exponent), rounded_significand, + round_underflow_up); + return; + } + + private: + T value_; + + static_assert(num_used_bits == + Traits::num_exponent_bits + Traits::num_fraction_bits + 1, + "The number of bits do not fit"); + static_assert(sizeof(T) == sizeof(uint_type), "The type sizes do not match"); +}; + +// Returns 4 bits represented by the hex character. +inline uint8_t get_nibble_from_character(int character) { + const char* dec = "0123456789"; + const char* lower = "abcdef"; + const char* upper = "ABCDEF"; + const char* p = nullptr; + if ((p = strchr(dec, character))) { + return static_cast(p - dec); + } else if ((p = strchr(lower, character))) { + return static_cast(p - lower + 0xa); + } else if ((p = strchr(upper, character))) { + return static_cast(p - upper + 0xa); + } + + assert(false && "This was called with a non-hex character"); + return 0; +} + +// Outputs the given HexFloat to the stream. +template +std::ostream& operator<<(std::ostream& os, const HexFloat& value) { + typedef HexFloat HF; + typedef typename HF::uint_type uint_type; + typedef typename HF::int_type int_type; + + static_assert(HF::num_used_bits != 0, + "num_used_bits must be non-zero for a valid float"); + static_assert(HF::num_exponent_bits != 0, + "num_exponent_bits must be non-zero for a valid float"); + static_assert(HF::num_fraction_bits != 0, + "num_fractin_bits must be non-zero for a valid float"); + + const uint_type bits = spvutils::BitwiseCast(value.value()); + const char* const sign = (bits & HF::sign_mask) ? "-" : ""; + const uint_type exponent = static_cast( + (bits & HF::exponent_mask) >> HF::num_fraction_bits); + + uint_type fraction = static_cast((bits & HF::fraction_encode_mask) + << HF::num_overflow_bits); + + const bool is_zero = exponent == 0 && fraction == 0; + const bool is_denorm = exponent == 0 && !is_zero; + + // exponent contains the biased exponent we have to convert it back into + // the normal range. + int_type int_exponent = static_cast(exponent - HF::exponent_bias); + // If the number is all zeros, then we actually have to NOT shift the + // exponent. + int_exponent = is_zero ? 0 : int_exponent; + + // If we are denorm, then start shifting, and decreasing the exponent until + // our leading bit is 1. + + if (is_denorm) { + while ((fraction & HF::fraction_top_bit) == 0) { + fraction = static_cast(fraction << 1); + int_exponent = static_cast(int_exponent - 1); + } + // Since this is denormalized, we have to consume the leading 1 since it + // will end up being implicit. + fraction = static_cast(fraction << 1); // eat the leading 1 + fraction &= HF::fraction_represent_mask; + } + + uint_type fraction_nibbles = HF::fraction_nibbles; + // We do not have to display any trailing 0s, since this represents the + // fractional part. + while (fraction_nibbles > 0 && (fraction & 0xF) == 0) { + // Shift off any trailing values; + fraction = static_cast(fraction >> 4); + --fraction_nibbles; + } + + const auto saved_flags = os.flags(); + const auto saved_fill = os.fill(); + + os << sign << "0x" << (is_zero ? '0' : '1'); + if (fraction_nibbles) { + // Make sure to keep the leading 0s in place, since this is the fractional + // part. + os << "." << std::setw(static_cast(fraction_nibbles)) + << std::setfill('0') << std::hex << fraction; + } + os << "p" << std::dec << (int_exponent >= 0 ? "+" : "") << int_exponent; + + os.flags(saved_flags); + os.fill(saved_fill); + + return os; +} + +// Returns true if negate_value is true and the next character on the +// input stream is a plus or minus sign. In that case we also set the fail bit +// on the stream and set the value to the zero value for its type. +template +inline bool RejectParseDueToLeadingSign(std::istream& is, bool negate_value, + HexFloat& value) { + if (negate_value) { + auto next_char = is.peek(); + if (next_char == '-' || next_char == '+') { + // Fail the parse. Emulate standard behaviour by setting the value to + // the zero value, and set the fail bit on the stream. + value = HexFloat(typename HexFloat::uint_type(0)); + is.setstate(std::ios_base::failbit); + return true; + } + } + return false; +} + +// Parses a floating point number from the given stream and stores it into the +// value parameter. +// If negate_value is true then the number may not have a leading minus or +// plus, and if it successfully parses, then the number is negated before +// being stored into the value parameter. +// If the value cannot be correctly parsed or overflows the target floating +// point type, then set the fail bit on the stream. +// TODO(dneto): Promise C++11 standard behavior in how the value is set in +// the error case, but only after all target platforms implement it correctly. +// In particular, the Microsoft C++ runtime appears to be out of spec. +template +inline std::istream& ParseNormalFloat(std::istream& is, bool negate_value, + HexFloat& value) { + if (RejectParseDueToLeadingSign(is, negate_value, value)) { + return is; + } + T val; + is >> val; + if (negate_value) { + val = -val; + } + value.set_value(val); + // In the failure case, map -0.0 to 0.0. + if (is.fail() && value.getUnsignedBits() == 0u) { + value = HexFloat(typename HexFloat::uint_type(0)); + } + if (val.isInfinity()) { + // Fail the parse. Emulate standard behaviour by setting the value to + // the closest normal value, and set the fail bit on the stream. + value.set_value((value.isNegative() || negate_value) ? T::lowest() + : T::max()); + is.setstate(std::ios_base::failbit); + } + return is; +} + +// Specialization of ParseNormalFloat for FloatProxy values. +// This will parse the float as it were a 32-bit floating point number, +// and then round it down to fit into a Float16 value. +// The number is rounded towards zero. +// If negate_value is true then the number may not have a leading minus or +// plus, and if it successfully parses, then the number is negated before +// being stored into the value parameter. +// If the value cannot be correctly parsed or overflows the target floating +// point type, then set the fail bit on the stream. +// TODO(dneto): Promise C++11 standard behavior in how the value is set in +// the error case, but only after all target platforms implement it correctly. +// In particular, the Microsoft C++ runtime appears to be out of spec. +template <> +inline std::istream& +ParseNormalFloat, HexFloatTraits>>( + std::istream& is, bool negate_value, + HexFloat, HexFloatTraits>>& value) { + // First parse as a 32-bit float. + HexFloat> float_val(0.0f); + ParseNormalFloat(is, negate_value, float_val); + + // Then convert to 16-bit float, saturating at infinities, and + // rounding toward zero. + float_val.castTo(value, kRoundToZero); + + // Overflow on 16-bit behaves the same as for 32- and 64-bit: set the + // fail bit and set the lowest or highest value. + if (Float16::isInfinity(value.value().getAsFloat())) { + value.set_value(value.isNegative() ? Float16::lowest() : Float16::max()); + is.setstate(std::ios_base::failbit); + } + return is; +} + +// Reads a HexFloat from the given stream. +// If the float is not encoded as a hex-float then it will be parsed +// as a regular float. +// This may fail if your stream does not support at least one unget. +// Nan values can be encoded with "0x1.p+exponent_bias". +// This would normally overflow a float and round to +// infinity but this special pattern is the exact representation for a NaN, +// and therefore is actually encoded as the correct NaN. To encode inf, +// either 0x0p+exponent_bias can be specified or any exponent greater than +// exponent_bias. +// Examples using IEEE 32-bit float encoding. +// 0x1.0p+128 (+inf) +// -0x1.0p-128 (-inf) +// +// 0x1.1p+128 (+Nan) +// -0x1.1p+128 (-Nan) +// +// 0x1p+129 (+inf) +// -0x1p+129 (-inf) +template +std::istream& operator>>(std::istream& is, HexFloat& value) { + using HF = HexFloat; + using uint_type = typename HF::uint_type; + using int_type = typename HF::int_type; + + value.set_value(static_cast(0.f)); + + if (is.flags() & std::ios::skipws) { + // If the user wants to skip whitespace , then we should obey that. + while (std::isspace(is.peek())) { + is.get(); + } + } + + auto next_char = is.peek(); + bool negate_value = false; + + if (next_char != '-' && next_char != '0') { + return ParseNormalFloat(is, negate_value, value); + } + + if (next_char == '-') { + negate_value = true; + is.get(); + next_char = is.peek(); + } + + if (next_char == '0') { + is.get(); // We may have to unget this. + auto maybe_hex_start = is.peek(); + if (maybe_hex_start != 'x' && maybe_hex_start != 'X') { + is.unget(); + return ParseNormalFloat(is, negate_value, value); + } else { + is.get(); // Throw away the 'x'; + } + } else { + return ParseNormalFloat(is, negate_value, value); + } + + // This "looks" like a hex-float so treat it as one. + bool seen_p = false; + bool seen_dot = false; + uint_type fraction_index = 0; + + uint_type fraction = 0; + int_type exponent = HF::exponent_bias; + + // Strip off leading zeros so we don't have to special-case them later. + while ((next_char = is.peek()) == '0') { + is.get(); + } + + bool is_denorm = + true; // Assume denorm "representation" until we hear otherwise. + // NB: This does not mean the value is actually denorm, + // it just means that it was written 0. + bool bits_written = false; // Stays false until we write a bit. + while (!seen_p && !seen_dot) { + // Handle characters that are left of the fractional part. + if (next_char == '.') { + seen_dot = true; + } else if (next_char == 'p') { + seen_p = true; + } else if (::isxdigit(next_char)) { + // We know this is not denormalized since we have stripped all leading + // zeroes and we are not a ".". + is_denorm = false; + int number = get_nibble_from_character(next_char); + for (int i = 0; i < 4; ++i, number <<= 1) { + uint_type write_bit = (number & 0x8) ? 0x1 : 0x0; + if (bits_written) { + // If we are here the bits represented belong in the fractional + // part of the float, and we have to adjust the exponent accordingly. + fraction = static_cast( + fraction | + static_cast( + write_bit << (HF::top_bit_left_shift - fraction_index++))); + exponent = static_cast(exponent + 1); + } + bits_written |= write_bit != 0; + } + } else { + // We have not found our exponent yet, so we have to fail. + is.setstate(std::ios::failbit); + return is; + } + is.get(); + next_char = is.peek(); + } + bits_written = false; + while (seen_dot && !seen_p) { + // Handle only fractional parts now. + if (next_char == 'p') { + seen_p = true; + } else if (::isxdigit(next_char)) { + int number = get_nibble_from_character(next_char); + for (int i = 0; i < 4; ++i, number <<= 1) { + uint_type write_bit = (number & 0x8) ? 0x01 : 0x00; + bits_written |= write_bit != 0; + if (is_denorm && !bits_written) { + // Handle modifying the exponent here this way we can handle + // an arbitrary number of hex values without overflowing our + // integer. + exponent = static_cast(exponent - 1); + } else { + fraction = static_cast( + fraction | + static_cast( + write_bit << (HF::top_bit_left_shift - fraction_index++))); + } + } + } else { + // We still have not found our 'p' exponent yet, so this is not a valid + // hex-float. + is.setstate(std::ios::failbit); + return is; + } + is.get(); + next_char = is.peek(); + } + + bool seen_sign = false; + int8_t exponent_sign = 1; + int_type written_exponent = 0; + while (true) { + if ((next_char == '-' || next_char == '+')) { + if (seen_sign) { + is.setstate(std::ios::failbit); + return is; + } + seen_sign = true; + exponent_sign = (next_char == '-') ? -1 : 1; + } else if (::isdigit(next_char)) { + // Hex-floats express their exponent as decimal. + written_exponent = static_cast(written_exponent * 10); + written_exponent = + static_cast(written_exponent + (next_char - '0')); + } else { + break; + } + is.get(); + next_char = is.peek(); + } + + written_exponent = static_cast(written_exponent * exponent_sign); + exponent = static_cast(exponent + written_exponent); + + bool is_zero = is_denorm && (fraction == 0); + if (is_denorm && !is_zero) { + fraction = static_cast(fraction << 1); + exponent = static_cast(exponent - 1); + } else if (is_zero) { + exponent = 0; + } + + if (exponent <= 0 && !is_zero) { + fraction = static_cast(fraction >> 1); + fraction |= static_cast(1) << HF::top_bit_left_shift; + } + + fraction = (fraction >> HF::fraction_right_shift) & HF::fraction_encode_mask; + + const int_type max_exponent = + SetBits::get; + + // Handle actual denorm numbers + while (exponent < 0 && !is_zero) { + fraction = static_cast(fraction >> 1); + exponent = static_cast(exponent + 1); + + fraction &= HF::fraction_encode_mask; + if (fraction == 0) { + // We have underflowed our fraction. We should clamp to zero. + is_zero = true; + exponent = 0; + } + } + + // We have overflowed so we should be inf/-inf. + if (exponent > max_exponent) { + exponent = max_exponent; + fraction = 0; + } + + uint_type output_bits = static_cast( + static_cast(negate_value ? 1 : 0) << HF::top_bit_left_shift); + output_bits |= fraction; + + uint_type shifted_exponent = static_cast( + static_cast(exponent << HF::exponent_left_shift) & + HF::exponent_mask); + output_bits |= shifted_exponent; + + T output_float = spvutils::BitwiseCast(output_bits); + value.set_value(output_float); + + return is; +} + +// Writes a FloatProxy value to a stream. +// Zero and normal numbers are printed in the usual notation, but with +// enough digits to fully reproduce the value. Other values (subnormal, +// NaN, and infinity) are printed as a hex float. +template +std::ostream& operator<<(std::ostream& os, const FloatProxy& value) { + auto float_val = value.getAsFloat(); + switch (std::fpclassify(float_val)) { + case FP_ZERO: + case FP_NORMAL: { + auto saved_precision = os.precision(); + os.precision(std::numeric_limits::digits10); + os << float_val; + os.precision(saved_precision); + } break; + default: + os << HexFloat>(value); + break; + } + return os; +} + +template <> +inline std::ostream& operator<<(std::ostream& os, + const FloatProxy& value) { + os << HexFloat>(value); + return os; +} +} + +#endif // LIBSPIRV_UTIL_HEX_FLOAT_H_ diff --git a/android/armeabi-v7a/include/SPIRV/spirv.hpp b/android/armeabi-v7a/include/SPIRV/spirv.hpp new file mode 100644 index 00000000..dae36cf2 --- /dev/null +++ b/android/armeabi-v7a/include/SPIRV/spirv.hpp @@ -0,0 +1,2114 @@ +// Copyright (c) 2014-2020 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and/or associated documentation files (the "Materials"), +// to deal in the Materials without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Materials, and to permit persons to whom the +// Materials are furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +// IN THE MATERIALS. + +// This header is automatically generated by the same tool that creates +// the Binary Section of the SPIR-V specification. + +// Enumeration tokens for SPIR-V, in various styles: +// C, C++, C++11, JSON, Lua, Python, C#, D +// +// - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL +// - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL +// - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL +// - Lua will use tables, e.g.: spv.SourceLanguage.GLSL +// - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] +// - C# will use enum classes in the Specification class located in the "Spv" namespace, +// e.g.: Spv.Specification.SourceLanguage.GLSL +// - D will have tokens under the "spv" module, e.g: spv.SourceLanguage.GLSL +// +// Some tokens act like mask values, which can be OR'd together, +// while others are mutually exclusive. The mask-like ones have +// "Mask" in their name, and a parallel enum that has the shift +// amount (1 << x) for each corresponding enumerant. + +#ifndef spirv_HPP +#define spirv_HPP + +namespace spv { + +typedef unsigned int Id; + +#define SPV_VERSION 0x10500 +#define SPV_REVISION 3 + +static const unsigned int MagicNumber = 0x07230203; +static const unsigned int Version = 0x00010500; +static const unsigned int Revision = 3; +static const unsigned int OpCodeMask = 0xffff; +static const unsigned int WordCountShift = 16; + +enum SourceLanguage { + SourceLanguageUnknown = 0, + SourceLanguageESSL = 1, + SourceLanguageGLSL = 2, + SourceLanguageOpenCL_C = 3, + SourceLanguageOpenCL_CPP = 4, + SourceLanguageHLSL = 5, + SourceLanguageMax = 0x7fffffff, +}; + +enum ExecutionModel { + ExecutionModelVertex = 0, + ExecutionModelTessellationControl = 1, + ExecutionModelTessellationEvaluation = 2, + ExecutionModelGeometry = 3, + ExecutionModelFragment = 4, + ExecutionModelGLCompute = 5, + ExecutionModelKernel = 6, + ExecutionModelTaskNV = 5267, + ExecutionModelMeshNV = 5268, + ExecutionModelRayGenerationKHR = 5313, + ExecutionModelRayGenerationNV = 5313, + ExecutionModelIntersectionKHR = 5314, + ExecutionModelIntersectionNV = 5314, + ExecutionModelAnyHitKHR = 5315, + ExecutionModelAnyHitNV = 5315, + ExecutionModelClosestHitKHR = 5316, + ExecutionModelClosestHitNV = 5316, + ExecutionModelMissKHR = 5317, + ExecutionModelMissNV = 5317, + ExecutionModelCallableKHR = 5318, + ExecutionModelCallableNV = 5318, + ExecutionModelMax = 0x7fffffff, +}; + +enum AddressingModel { + AddressingModelLogical = 0, + AddressingModelPhysical32 = 1, + AddressingModelPhysical64 = 2, + AddressingModelPhysicalStorageBuffer64 = 5348, + AddressingModelPhysicalStorageBuffer64EXT = 5348, + AddressingModelMax = 0x7fffffff, +}; + +enum MemoryModel { + MemoryModelSimple = 0, + MemoryModelGLSL450 = 1, + MemoryModelOpenCL = 2, + MemoryModelVulkan = 3, + MemoryModelVulkanKHR = 3, + MemoryModelMax = 0x7fffffff, +}; + +enum ExecutionMode { + ExecutionModeInvocations = 0, + ExecutionModeSpacingEqual = 1, + ExecutionModeSpacingFractionalEven = 2, + ExecutionModeSpacingFractionalOdd = 3, + ExecutionModeVertexOrderCw = 4, + ExecutionModeVertexOrderCcw = 5, + ExecutionModePixelCenterInteger = 6, + ExecutionModeOriginUpperLeft = 7, + ExecutionModeOriginLowerLeft = 8, + ExecutionModeEarlyFragmentTests = 9, + ExecutionModePointMode = 10, + ExecutionModeXfb = 11, + ExecutionModeDepthReplacing = 12, + ExecutionModeDepthGreater = 14, + ExecutionModeDepthLess = 15, + ExecutionModeDepthUnchanged = 16, + ExecutionModeLocalSize = 17, + ExecutionModeLocalSizeHint = 18, + ExecutionModeInputPoints = 19, + ExecutionModeInputLines = 20, + ExecutionModeInputLinesAdjacency = 21, + ExecutionModeTriangles = 22, + ExecutionModeInputTrianglesAdjacency = 23, + ExecutionModeQuads = 24, + ExecutionModeIsolines = 25, + ExecutionModeOutputVertices = 26, + ExecutionModeOutputPoints = 27, + ExecutionModeOutputLineStrip = 28, + ExecutionModeOutputTriangleStrip = 29, + ExecutionModeVecTypeHint = 30, + ExecutionModeContractionOff = 31, + ExecutionModeInitializer = 33, + ExecutionModeFinalizer = 34, + ExecutionModeSubgroupSize = 35, + ExecutionModeSubgroupsPerWorkgroup = 36, + ExecutionModeSubgroupsPerWorkgroupId = 37, + ExecutionModeLocalSizeId = 38, + ExecutionModeLocalSizeHintId = 39, + ExecutionModePostDepthCoverage = 4446, + ExecutionModeDenormPreserve = 4459, + ExecutionModeDenormFlushToZero = 4460, + ExecutionModeSignedZeroInfNanPreserve = 4461, + ExecutionModeRoundingModeRTE = 4462, + ExecutionModeRoundingModeRTZ = 4463, + ExecutionModeStencilRefReplacingEXT = 5027, + ExecutionModeOutputLinesNV = 5269, + ExecutionModeOutputPrimitivesNV = 5270, + ExecutionModeDerivativeGroupQuadsNV = 5289, + ExecutionModeDerivativeGroupLinearNV = 5290, + ExecutionModeOutputTrianglesNV = 5298, + ExecutionModePixelInterlockOrderedEXT = 5366, + ExecutionModePixelInterlockUnorderedEXT = 5367, + ExecutionModeSampleInterlockOrderedEXT = 5368, + ExecutionModeSampleInterlockUnorderedEXT = 5369, + ExecutionModeShadingRateInterlockOrderedEXT = 5370, + ExecutionModeShadingRateInterlockUnorderedEXT = 5371, + ExecutionModeMax = 0x7fffffff, +}; + +enum StorageClass { + StorageClassUniformConstant = 0, + StorageClassInput = 1, + StorageClassUniform = 2, + StorageClassOutput = 3, + StorageClassWorkgroup = 4, + StorageClassCrossWorkgroup = 5, + StorageClassPrivate = 6, + StorageClassFunction = 7, + StorageClassGeneric = 8, + StorageClassPushConstant = 9, + StorageClassAtomicCounter = 10, + StorageClassImage = 11, + StorageClassStorageBuffer = 12, + StorageClassCallableDataKHR = 5328, + StorageClassCallableDataNV = 5328, + StorageClassIncomingCallableDataKHR = 5329, + StorageClassIncomingCallableDataNV = 5329, + StorageClassRayPayloadKHR = 5338, + StorageClassRayPayloadNV = 5338, + StorageClassHitAttributeKHR = 5339, + StorageClassHitAttributeNV = 5339, + StorageClassIncomingRayPayloadKHR = 5342, + StorageClassIncomingRayPayloadNV = 5342, + StorageClassShaderRecordBufferKHR = 5343, + StorageClassShaderRecordBufferNV = 5343, + StorageClassPhysicalStorageBuffer = 5349, + StorageClassPhysicalStorageBufferEXT = 5349, + StorageClassMax = 0x7fffffff, +}; + +enum Dim { + Dim1D = 0, + Dim2D = 1, + Dim3D = 2, + DimCube = 3, + DimRect = 4, + DimBuffer = 5, + DimSubpassData = 6, + DimMax = 0x7fffffff, +}; + +enum SamplerAddressingMode { + SamplerAddressingModeNone = 0, + SamplerAddressingModeClampToEdge = 1, + SamplerAddressingModeClamp = 2, + SamplerAddressingModeRepeat = 3, + SamplerAddressingModeRepeatMirrored = 4, + SamplerAddressingModeMax = 0x7fffffff, +}; + +enum SamplerFilterMode { + SamplerFilterModeNearest = 0, + SamplerFilterModeLinear = 1, + SamplerFilterModeMax = 0x7fffffff, +}; + +enum ImageFormat { + ImageFormatUnknown = 0, + ImageFormatRgba32f = 1, + ImageFormatRgba16f = 2, + ImageFormatR32f = 3, + ImageFormatRgba8 = 4, + ImageFormatRgba8Snorm = 5, + ImageFormatRg32f = 6, + ImageFormatRg16f = 7, + ImageFormatR11fG11fB10f = 8, + ImageFormatR16f = 9, + ImageFormatRgba16 = 10, + ImageFormatRgb10A2 = 11, + ImageFormatRg16 = 12, + ImageFormatRg8 = 13, + ImageFormatR16 = 14, + ImageFormatR8 = 15, + ImageFormatRgba16Snorm = 16, + ImageFormatRg16Snorm = 17, + ImageFormatRg8Snorm = 18, + ImageFormatR16Snorm = 19, + ImageFormatR8Snorm = 20, + ImageFormatRgba32i = 21, + ImageFormatRgba16i = 22, + ImageFormatRgba8i = 23, + ImageFormatR32i = 24, + ImageFormatRg32i = 25, + ImageFormatRg16i = 26, + ImageFormatRg8i = 27, + ImageFormatR16i = 28, + ImageFormatR8i = 29, + ImageFormatRgba32ui = 30, + ImageFormatRgba16ui = 31, + ImageFormatRgba8ui = 32, + ImageFormatR32ui = 33, + ImageFormatRgb10a2ui = 34, + ImageFormatRg32ui = 35, + ImageFormatRg16ui = 36, + ImageFormatRg8ui = 37, + ImageFormatR16ui = 38, + ImageFormatR8ui = 39, + ImageFormatMax = 0x7fffffff, +}; + +enum ImageChannelOrder { + ImageChannelOrderR = 0, + ImageChannelOrderA = 1, + ImageChannelOrderRG = 2, + ImageChannelOrderRA = 3, + ImageChannelOrderRGB = 4, + ImageChannelOrderRGBA = 5, + ImageChannelOrderBGRA = 6, + ImageChannelOrderARGB = 7, + ImageChannelOrderIntensity = 8, + ImageChannelOrderLuminance = 9, + ImageChannelOrderRx = 10, + ImageChannelOrderRGx = 11, + ImageChannelOrderRGBx = 12, + ImageChannelOrderDepth = 13, + ImageChannelOrderDepthStencil = 14, + ImageChannelOrdersRGB = 15, + ImageChannelOrdersRGBx = 16, + ImageChannelOrdersRGBA = 17, + ImageChannelOrdersBGRA = 18, + ImageChannelOrderABGR = 19, + ImageChannelOrderMax = 0x7fffffff, +}; + +enum ImageChannelDataType { + ImageChannelDataTypeSnormInt8 = 0, + ImageChannelDataTypeSnormInt16 = 1, + ImageChannelDataTypeUnormInt8 = 2, + ImageChannelDataTypeUnormInt16 = 3, + ImageChannelDataTypeUnormShort565 = 4, + ImageChannelDataTypeUnormShort555 = 5, + ImageChannelDataTypeUnormInt101010 = 6, + ImageChannelDataTypeSignedInt8 = 7, + ImageChannelDataTypeSignedInt16 = 8, + ImageChannelDataTypeSignedInt32 = 9, + ImageChannelDataTypeUnsignedInt8 = 10, + ImageChannelDataTypeUnsignedInt16 = 11, + ImageChannelDataTypeUnsignedInt32 = 12, + ImageChannelDataTypeHalfFloat = 13, + ImageChannelDataTypeFloat = 14, + ImageChannelDataTypeUnormInt24 = 15, + ImageChannelDataTypeUnormInt101010_2 = 16, + ImageChannelDataTypeMax = 0x7fffffff, +}; + +enum ImageOperandsShift { + ImageOperandsBiasShift = 0, + ImageOperandsLodShift = 1, + ImageOperandsGradShift = 2, + ImageOperandsConstOffsetShift = 3, + ImageOperandsOffsetShift = 4, + ImageOperandsConstOffsetsShift = 5, + ImageOperandsSampleShift = 6, + ImageOperandsMinLodShift = 7, + ImageOperandsMakeTexelAvailableShift = 8, + ImageOperandsMakeTexelAvailableKHRShift = 8, + ImageOperandsMakeTexelVisibleShift = 9, + ImageOperandsMakeTexelVisibleKHRShift = 9, + ImageOperandsNonPrivateTexelShift = 10, + ImageOperandsNonPrivateTexelKHRShift = 10, + ImageOperandsVolatileTexelShift = 11, + ImageOperandsVolatileTexelKHRShift = 11, + ImageOperandsSignExtendShift = 12, + ImageOperandsZeroExtendShift = 13, + ImageOperandsMax = 0x7fffffff, +}; + +enum ImageOperandsMask { + ImageOperandsMaskNone = 0, + ImageOperandsBiasMask = 0x00000001, + ImageOperandsLodMask = 0x00000002, + ImageOperandsGradMask = 0x00000004, + ImageOperandsConstOffsetMask = 0x00000008, + ImageOperandsOffsetMask = 0x00000010, + ImageOperandsConstOffsetsMask = 0x00000020, + ImageOperandsSampleMask = 0x00000040, + ImageOperandsMinLodMask = 0x00000080, + ImageOperandsMakeTexelAvailableMask = 0x00000100, + ImageOperandsMakeTexelAvailableKHRMask = 0x00000100, + ImageOperandsMakeTexelVisibleMask = 0x00000200, + ImageOperandsMakeTexelVisibleKHRMask = 0x00000200, + ImageOperandsNonPrivateTexelMask = 0x00000400, + ImageOperandsNonPrivateTexelKHRMask = 0x00000400, + ImageOperandsVolatileTexelMask = 0x00000800, + ImageOperandsVolatileTexelKHRMask = 0x00000800, + ImageOperandsSignExtendMask = 0x00001000, + ImageOperandsZeroExtendMask = 0x00002000, +}; + +enum FPFastMathModeShift { + FPFastMathModeNotNaNShift = 0, + FPFastMathModeNotInfShift = 1, + FPFastMathModeNSZShift = 2, + FPFastMathModeAllowRecipShift = 3, + FPFastMathModeFastShift = 4, + FPFastMathModeMax = 0x7fffffff, +}; + +enum FPFastMathModeMask { + FPFastMathModeMaskNone = 0, + FPFastMathModeNotNaNMask = 0x00000001, + FPFastMathModeNotInfMask = 0x00000002, + FPFastMathModeNSZMask = 0x00000004, + FPFastMathModeAllowRecipMask = 0x00000008, + FPFastMathModeFastMask = 0x00000010, +}; + +enum FPRoundingMode { + FPRoundingModeRTE = 0, + FPRoundingModeRTZ = 1, + FPRoundingModeRTP = 2, + FPRoundingModeRTN = 3, + FPRoundingModeMax = 0x7fffffff, +}; + +enum LinkageType { + LinkageTypeExport = 0, + LinkageTypeImport = 1, + LinkageTypeMax = 0x7fffffff, +}; + +enum AccessQualifier { + AccessQualifierReadOnly = 0, + AccessQualifierWriteOnly = 1, + AccessQualifierReadWrite = 2, + AccessQualifierMax = 0x7fffffff, +}; + +enum FunctionParameterAttribute { + FunctionParameterAttributeZext = 0, + FunctionParameterAttributeSext = 1, + FunctionParameterAttributeByVal = 2, + FunctionParameterAttributeSret = 3, + FunctionParameterAttributeNoAlias = 4, + FunctionParameterAttributeNoCapture = 5, + FunctionParameterAttributeNoWrite = 6, + FunctionParameterAttributeNoReadWrite = 7, + FunctionParameterAttributeMax = 0x7fffffff, +}; + +enum Decoration { + DecorationRelaxedPrecision = 0, + DecorationSpecId = 1, + DecorationBlock = 2, + DecorationBufferBlock = 3, + DecorationRowMajor = 4, + DecorationColMajor = 5, + DecorationArrayStride = 6, + DecorationMatrixStride = 7, + DecorationGLSLShared = 8, + DecorationGLSLPacked = 9, + DecorationCPacked = 10, + DecorationBuiltIn = 11, + DecorationNoPerspective = 13, + DecorationFlat = 14, + DecorationPatch = 15, + DecorationCentroid = 16, + DecorationSample = 17, + DecorationInvariant = 18, + DecorationRestrict = 19, + DecorationAliased = 20, + DecorationVolatile = 21, + DecorationConstant = 22, + DecorationCoherent = 23, + DecorationNonWritable = 24, + DecorationNonReadable = 25, + DecorationUniform = 26, + DecorationUniformId = 27, + DecorationSaturatedConversion = 28, + DecorationStream = 29, + DecorationLocation = 30, + DecorationComponent = 31, + DecorationIndex = 32, + DecorationBinding = 33, + DecorationDescriptorSet = 34, + DecorationOffset = 35, + DecorationXfbBuffer = 36, + DecorationXfbStride = 37, + DecorationFuncParamAttr = 38, + DecorationFPRoundingMode = 39, + DecorationFPFastMathMode = 40, + DecorationLinkageAttributes = 41, + DecorationNoContraction = 42, + DecorationInputAttachmentIndex = 43, + DecorationAlignment = 44, + DecorationMaxByteOffset = 45, + DecorationAlignmentId = 46, + DecorationMaxByteOffsetId = 47, + DecorationNoSignedWrap = 4469, + DecorationNoUnsignedWrap = 4470, + DecorationExplicitInterpAMD = 4999, + DecorationOverrideCoverageNV = 5248, + DecorationPassthroughNV = 5250, + DecorationViewportRelativeNV = 5252, + DecorationSecondaryViewportRelativeNV = 5256, + DecorationPerPrimitiveNV = 5271, + DecorationPerViewNV = 5272, + DecorationPerTaskNV = 5273, + DecorationPerVertexNV = 5285, + DecorationNonUniform = 5300, + DecorationNonUniformEXT = 5300, + DecorationRestrictPointer = 5355, + DecorationRestrictPointerEXT = 5355, + DecorationAliasedPointer = 5356, + DecorationAliasedPointerEXT = 5356, + DecorationCounterBuffer = 5634, + DecorationHlslCounterBufferGOOGLE = 5634, + DecorationHlslSemanticGOOGLE = 5635, + DecorationUserSemantic = 5635, + DecorationUserTypeGOOGLE = 5636, + DecorationMax = 0x7fffffff, +}; + +enum BuiltIn { + BuiltInPosition = 0, + BuiltInPointSize = 1, + BuiltInClipDistance = 3, + BuiltInCullDistance = 4, + BuiltInVertexId = 5, + BuiltInInstanceId = 6, + BuiltInPrimitiveId = 7, + BuiltInInvocationId = 8, + BuiltInLayer = 9, + BuiltInViewportIndex = 10, + BuiltInTessLevelOuter = 11, + BuiltInTessLevelInner = 12, + BuiltInTessCoord = 13, + BuiltInPatchVertices = 14, + BuiltInFragCoord = 15, + BuiltInPointCoord = 16, + BuiltInFrontFacing = 17, + BuiltInSampleId = 18, + BuiltInSamplePosition = 19, + BuiltInSampleMask = 20, + BuiltInFragDepth = 22, + BuiltInHelperInvocation = 23, + BuiltInNumWorkgroups = 24, + BuiltInWorkgroupSize = 25, + BuiltInWorkgroupId = 26, + BuiltInLocalInvocationId = 27, + BuiltInGlobalInvocationId = 28, + BuiltInLocalInvocationIndex = 29, + BuiltInWorkDim = 30, + BuiltInGlobalSize = 31, + BuiltInEnqueuedWorkgroupSize = 32, + BuiltInGlobalOffset = 33, + BuiltInGlobalLinearId = 34, + BuiltInSubgroupSize = 36, + BuiltInSubgroupMaxSize = 37, + BuiltInNumSubgroups = 38, + BuiltInNumEnqueuedSubgroups = 39, + BuiltInSubgroupId = 40, + BuiltInSubgroupLocalInvocationId = 41, + BuiltInVertexIndex = 42, + BuiltInInstanceIndex = 43, + BuiltInSubgroupEqMask = 4416, + BuiltInSubgroupEqMaskKHR = 4416, + BuiltInSubgroupGeMask = 4417, + BuiltInSubgroupGeMaskKHR = 4417, + BuiltInSubgroupGtMask = 4418, + BuiltInSubgroupGtMaskKHR = 4418, + BuiltInSubgroupLeMask = 4419, + BuiltInSubgroupLeMaskKHR = 4419, + BuiltInSubgroupLtMask = 4420, + BuiltInSubgroupLtMaskKHR = 4420, + BuiltInBaseVertex = 4424, + BuiltInBaseInstance = 4425, + BuiltInDrawIndex = 4426, + BuiltInDeviceIndex = 4438, + BuiltInViewIndex = 4440, + BuiltInBaryCoordNoPerspAMD = 4992, + BuiltInBaryCoordNoPerspCentroidAMD = 4993, + BuiltInBaryCoordNoPerspSampleAMD = 4994, + BuiltInBaryCoordSmoothAMD = 4995, + BuiltInBaryCoordSmoothCentroidAMD = 4996, + BuiltInBaryCoordSmoothSampleAMD = 4997, + BuiltInBaryCoordPullModelAMD = 4998, + BuiltInFragStencilRefEXT = 5014, + BuiltInViewportMaskNV = 5253, + BuiltInSecondaryPositionNV = 5257, + BuiltInSecondaryViewportMaskNV = 5258, + BuiltInPositionPerViewNV = 5261, + BuiltInViewportMaskPerViewNV = 5262, + BuiltInFullyCoveredEXT = 5264, + BuiltInTaskCountNV = 5274, + BuiltInPrimitiveCountNV = 5275, + BuiltInPrimitiveIndicesNV = 5276, + BuiltInClipDistancePerViewNV = 5277, + BuiltInCullDistancePerViewNV = 5278, + BuiltInLayerPerViewNV = 5279, + BuiltInMeshViewCountNV = 5280, + BuiltInMeshViewIndicesNV = 5281, + BuiltInBaryCoordNV = 5286, + BuiltInBaryCoordNoPerspNV = 5287, + BuiltInFragSizeEXT = 5292, + BuiltInFragmentSizeNV = 5292, + BuiltInFragInvocationCountEXT = 5293, + BuiltInInvocationsPerPixelNV = 5293, + BuiltInLaunchIdKHR = 5319, + BuiltInLaunchIdNV = 5319, + BuiltInLaunchSizeKHR = 5320, + BuiltInLaunchSizeNV = 5320, + BuiltInWorldRayOriginKHR = 5321, + BuiltInWorldRayOriginNV = 5321, + BuiltInWorldRayDirectionKHR = 5322, + BuiltInWorldRayDirectionNV = 5322, + BuiltInObjectRayOriginKHR = 5323, + BuiltInObjectRayOriginNV = 5323, + BuiltInObjectRayDirectionKHR = 5324, + BuiltInObjectRayDirectionNV = 5324, + BuiltInRayTminKHR = 5325, + BuiltInRayTminNV = 5325, + BuiltInRayTmaxKHR = 5326, + BuiltInRayTmaxNV = 5326, + BuiltInInstanceCustomIndexKHR = 5327, + BuiltInInstanceCustomIndexNV = 5327, + BuiltInObjectToWorldKHR = 5330, + BuiltInObjectToWorldNV = 5330, + BuiltInWorldToObjectKHR = 5331, + BuiltInWorldToObjectNV = 5331, + BuiltInHitTKHR = 5332, + BuiltInHitTNV = 5332, + BuiltInHitKindKHR = 5333, + BuiltInHitKindNV = 5333, + BuiltInIncomingRayFlagsKHR = 5351, + BuiltInIncomingRayFlagsNV = 5351, + BuiltInRayGeometryIndexKHR = 5352, + BuiltInWarpsPerSMNV = 5374, + BuiltInSMCountNV = 5375, + BuiltInWarpIDNV = 5376, + BuiltInSMIDNV = 5377, + BuiltInMax = 0x7fffffff, +}; + +enum SelectionControlShift { + SelectionControlFlattenShift = 0, + SelectionControlDontFlattenShift = 1, + SelectionControlMax = 0x7fffffff, +}; + +enum SelectionControlMask { + SelectionControlMaskNone = 0, + SelectionControlFlattenMask = 0x00000001, + SelectionControlDontFlattenMask = 0x00000002, +}; + +enum LoopControlShift { + LoopControlUnrollShift = 0, + LoopControlDontUnrollShift = 1, + LoopControlDependencyInfiniteShift = 2, + LoopControlDependencyLengthShift = 3, + LoopControlMinIterationsShift = 4, + LoopControlMaxIterationsShift = 5, + LoopControlIterationMultipleShift = 6, + LoopControlPeelCountShift = 7, + LoopControlPartialCountShift = 8, + LoopControlMax = 0x7fffffff, +}; + +enum LoopControlMask { + LoopControlMaskNone = 0, + LoopControlUnrollMask = 0x00000001, + LoopControlDontUnrollMask = 0x00000002, + LoopControlDependencyInfiniteMask = 0x00000004, + LoopControlDependencyLengthMask = 0x00000008, + LoopControlMinIterationsMask = 0x00000010, + LoopControlMaxIterationsMask = 0x00000020, + LoopControlIterationMultipleMask = 0x00000040, + LoopControlPeelCountMask = 0x00000080, + LoopControlPartialCountMask = 0x00000100, +}; + +enum FunctionControlShift { + FunctionControlInlineShift = 0, + FunctionControlDontInlineShift = 1, + FunctionControlPureShift = 2, + FunctionControlConstShift = 3, + FunctionControlMax = 0x7fffffff, +}; + +enum FunctionControlMask { + FunctionControlMaskNone = 0, + FunctionControlInlineMask = 0x00000001, + FunctionControlDontInlineMask = 0x00000002, + FunctionControlPureMask = 0x00000004, + FunctionControlConstMask = 0x00000008, +}; + +enum MemorySemanticsShift { + MemorySemanticsAcquireShift = 1, + MemorySemanticsReleaseShift = 2, + MemorySemanticsAcquireReleaseShift = 3, + MemorySemanticsSequentiallyConsistentShift = 4, + MemorySemanticsUniformMemoryShift = 6, + MemorySemanticsSubgroupMemoryShift = 7, + MemorySemanticsWorkgroupMemoryShift = 8, + MemorySemanticsCrossWorkgroupMemoryShift = 9, + MemorySemanticsAtomicCounterMemoryShift = 10, + MemorySemanticsImageMemoryShift = 11, + MemorySemanticsOutputMemoryShift = 12, + MemorySemanticsOutputMemoryKHRShift = 12, + MemorySemanticsMakeAvailableShift = 13, + MemorySemanticsMakeAvailableKHRShift = 13, + MemorySemanticsMakeVisibleShift = 14, + MemorySemanticsMakeVisibleKHRShift = 14, + MemorySemanticsVolatileShift = 15, + MemorySemanticsMax = 0x7fffffff, +}; + +enum MemorySemanticsMask { + MemorySemanticsMaskNone = 0, + MemorySemanticsAcquireMask = 0x00000002, + MemorySemanticsReleaseMask = 0x00000004, + MemorySemanticsAcquireReleaseMask = 0x00000008, + MemorySemanticsSequentiallyConsistentMask = 0x00000010, + MemorySemanticsUniformMemoryMask = 0x00000040, + MemorySemanticsSubgroupMemoryMask = 0x00000080, + MemorySemanticsWorkgroupMemoryMask = 0x00000100, + MemorySemanticsCrossWorkgroupMemoryMask = 0x00000200, + MemorySemanticsAtomicCounterMemoryMask = 0x00000400, + MemorySemanticsImageMemoryMask = 0x00000800, + MemorySemanticsOutputMemoryMask = 0x00001000, + MemorySemanticsOutputMemoryKHRMask = 0x00001000, + MemorySemanticsMakeAvailableMask = 0x00002000, + MemorySemanticsMakeAvailableKHRMask = 0x00002000, + MemorySemanticsMakeVisibleMask = 0x00004000, + MemorySemanticsMakeVisibleKHRMask = 0x00004000, + MemorySemanticsVolatileMask = 0x00008000, +}; + +enum MemoryAccessShift { + MemoryAccessVolatileShift = 0, + MemoryAccessAlignedShift = 1, + MemoryAccessNontemporalShift = 2, + MemoryAccessMakePointerAvailableShift = 3, + MemoryAccessMakePointerAvailableKHRShift = 3, + MemoryAccessMakePointerVisibleShift = 4, + MemoryAccessMakePointerVisibleKHRShift = 4, + MemoryAccessNonPrivatePointerShift = 5, + MemoryAccessNonPrivatePointerKHRShift = 5, + MemoryAccessMax = 0x7fffffff, +}; + +enum MemoryAccessMask { + MemoryAccessMaskNone = 0, + MemoryAccessVolatileMask = 0x00000001, + MemoryAccessAlignedMask = 0x00000002, + MemoryAccessNontemporalMask = 0x00000004, + MemoryAccessMakePointerAvailableMask = 0x00000008, + MemoryAccessMakePointerAvailableKHRMask = 0x00000008, + MemoryAccessMakePointerVisibleMask = 0x00000010, + MemoryAccessMakePointerVisibleKHRMask = 0x00000010, + MemoryAccessNonPrivatePointerMask = 0x00000020, + MemoryAccessNonPrivatePointerKHRMask = 0x00000020, +}; + +enum Scope { + ScopeCrossDevice = 0, + ScopeDevice = 1, + ScopeWorkgroup = 2, + ScopeSubgroup = 3, + ScopeInvocation = 4, + ScopeQueueFamily = 5, + ScopeQueueFamilyKHR = 5, + ScopeShaderCallKHR = 6, + ScopeMax = 0x7fffffff, +}; + +enum GroupOperation { + GroupOperationReduce = 0, + GroupOperationInclusiveScan = 1, + GroupOperationExclusiveScan = 2, + GroupOperationClusteredReduce = 3, + GroupOperationPartitionedReduceNV = 6, + GroupOperationPartitionedInclusiveScanNV = 7, + GroupOperationPartitionedExclusiveScanNV = 8, + GroupOperationMax = 0x7fffffff, +}; + +enum KernelEnqueueFlags { + KernelEnqueueFlagsNoWait = 0, + KernelEnqueueFlagsWaitKernel = 1, + KernelEnqueueFlagsWaitWorkGroup = 2, + KernelEnqueueFlagsMax = 0x7fffffff, +}; + +enum KernelProfilingInfoShift { + KernelProfilingInfoCmdExecTimeShift = 0, + KernelProfilingInfoMax = 0x7fffffff, +}; + +enum KernelProfilingInfoMask { + KernelProfilingInfoMaskNone = 0, + KernelProfilingInfoCmdExecTimeMask = 0x00000001, +}; + +enum Capability { + CapabilityMatrix = 0, + CapabilityShader = 1, + CapabilityGeometry = 2, + CapabilityTessellation = 3, + CapabilityAddresses = 4, + CapabilityLinkage = 5, + CapabilityKernel = 6, + CapabilityVector16 = 7, + CapabilityFloat16Buffer = 8, + CapabilityFloat16 = 9, + CapabilityFloat64 = 10, + CapabilityInt64 = 11, + CapabilityInt64Atomics = 12, + CapabilityImageBasic = 13, + CapabilityImageReadWrite = 14, + CapabilityImageMipmap = 15, + CapabilityPipes = 17, + CapabilityGroups = 18, + CapabilityDeviceEnqueue = 19, + CapabilityLiteralSampler = 20, + CapabilityAtomicStorage = 21, + CapabilityInt16 = 22, + CapabilityTessellationPointSize = 23, + CapabilityGeometryPointSize = 24, + CapabilityImageGatherExtended = 25, + CapabilityStorageImageMultisample = 27, + CapabilityUniformBufferArrayDynamicIndexing = 28, + CapabilitySampledImageArrayDynamicIndexing = 29, + CapabilityStorageBufferArrayDynamicIndexing = 30, + CapabilityStorageImageArrayDynamicIndexing = 31, + CapabilityClipDistance = 32, + CapabilityCullDistance = 33, + CapabilityImageCubeArray = 34, + CapabilitySampleRateShading = 35, + CapabilityImageRect = 36, + CapabilitySampledRect = 37, + CapabilityGenericPointer = 38, + CapabilityInt8 = 39, + CapabilityInputAttachment = 40, + CapabilitySparseResidency = 41, + CapabilityMinLod = 42, + CapabilitySampled1D = 43, + CapabilityImage1D = 44, + CapabilitySampledCubeArray = 45, + CapabilitySampledBuffer = 46, + CapabilityImageBuffer = 47, + CapabilityImageMSArray = 48, + CapabilityStorageImageExtendedFormats = 49, + CapabilityImageQuery = 50, + CapabilityDerivativeControl = 51, + CapabilityInterpolationFunction = 52, + CapabilityTransformFeedback = 53, + CapabilityGeometryStreams = 54, + CapabilityStorageImageReadWithoutFormat = 55, + CapabilityStorageImageWriteWithoutFormat = 56, + CapabilityMultiViewport = 57, + CapabilitySubgroupDispatch = 58, + CapabilityNamedBarrier = 59, + CapabilityPipeStorage = 60, + CapabilityGroupNonUniform = 61, + CapabilityGroupNonUniformVote = 62, + CapabilityGroupNonUniformArithmetic = 63, + CapabilityGroupNonUniformBallot = 64, + CapabilityGroupNonUniformShuffle = 65, + CapabilityGroupNonUniformShuffleRelative = 66, + CapabilityGroupNonUniformClustered = 67, + CapabilityGroupNonUniformQuad = 68, + CapabilityShaderLayer = 69, + CapabilityShaderViewportIndex = 70, + CapabilitySubgroupBallotKHR = 4423, + CapabilityDrawParameters = 4427, + CapabilitySubgroupVoteKHR = 4431, + CapabilityStorageBuffer16BitAccess = 4433, + CapabilityStorageUniformBufferBlock16 = 4433, + CapabilityStorageUniform16 = 4434, + CapabilityUniformAndStorageBuffer16BitAccess = 4434, + CapabilityStoragePushConstant16 = 4435, + CapabilityStorageInputOutput16 = 4436, + CapabilityDeviceGroup = 4437, + CapabilityMultiView = 4439, + CapabilityVariablePointersStorageBuffer = 4441, + CapabilityVariablePointers = 4442, + CapabilityAtomicStorageOps = 4445, + CapabilitySampleMaskPostDepthCoverage = 4447, + CapabilityStorageBuffer8BitAccess = 4448, + CapabilityUniformAndStorageBuffer8BitAccess = 4449, + CapabilityStoragePushConstant8 = 4450, + CapabilityDenormPreserve = 4464, + CapabilityDenormFlushToZero = 4465, + CapabilitySignedZeroInfNanPreserve = 4466, + CapabilityRoundingModeRTE = 4467, + CapabilityRoundingModeRTZ = 4468, + CapabilityRayQueryProvisionalKHR = 4471, + CapabilityRayTraversalPrimitiveCullingProvisionalKHR = 4478, + CapabilityFloat16ImageAMD = 5008, + CapabilityImageGatherBiasLodAMD = 5009, + CapabilityFragmentMaskAMD = 5010, + CapabilityStencilExportEXT = 5013, + CapabilityImageReadWriteLodAMD = 5015, + CapabilityShaderClockKHR = 5055, + CapabilitySampleMaskOverrideCoverageNV = 5249, + CapabilityGeometryShaderPassthroughNV = 5251, + CapabilityShaderViewportIndexLayerEXT = 5254, + CapabilityShaderViewportIndexLayerNV = 5254, + CapabilityShaderViewportMaskNV = 5255, + CapabilityShaderStereoViewNV = 5259, + CapabilityPerViewAttributesNV = 5260, + CapabilityFragmentFullyCoveredEXT = 5265, + CapabilityMeshShadingNV = 5266, + CapabilityImageFootprintNV = 5282, + CapabilityFragmentBarycentricNV = 5284, + CapabilityComputeDerivativeGroupQuadsNV = 5288, + CapabilityFragmentDensityEXT = 5291, + CapabilityShadingRateNV = 5291, + CapabilityGroupNonUniformPartitionedNV = 5297, + CapabilityShaderNonUniform = 5301, + CapabilityShaderNonUniformEXT = 5301, + CapabilityRuntimeDescriptorArray = 5302, + CapabilityRuntimeDescriptorArrayEXT = 5302, + CapabilityInputAttachmentArrayDynamicIndexing = 5303, + CapabilityInputAttachmentArrayDynamicIndexingEXT = 5303, + CapabilityUniformTexelBufferArrayDynamicIndexing = 5304, + CapabilityUniformTexelBufferArrayDynamicIndexingEXT = 5304, + CapabilityStorageTexelBufferArrayDynamicIndexing = 5305, + CapabilityStorageTexelBufferArrayDynamicIndexingEXT = 5305, + CapabilityUniformBufferArrayNonUniformIndexing = 5306, + CapabilityUniformBufferArrayNonUniformIndexingEXT = 5306, + CapabilitySampledImageArrayNonUniformIndexing = 5307, + CapabilitySampledImageArrayNonUniformIndexingEXT = 5307, + CapabilityStorageBufferArrayNonUniformIndexing = 5308, + CapabilityStorageBufferArrayNonUniformIndexingEXT = 5308, + CapabilityStorageImageArrayNonUniformIndexing = 5309, + CapabilityStorageImageArrayNonUniformIndexingEXT = 5309, + CapabilityInputAttachmentArrayNonUniformIndexing = 5310, + CapabilityInputAttachmentArrayNonUniformIndexingEXT = 5310, + CapabilityUniformTexelBufferArrayNonUniformIndexing = 5311, + CapabilityUniformTexelBufferArrayNonUniformIndexingEXT = 5311, + CapabilityStorageTexelBufferArrayNonUniformIndexing = 5312, + CapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312, + CapabilityRayTracingNV = 5340, + CapabilityVulkanMemoryModel = 5345, + CapabilityVulkanMemoryModelKHR = 5345, + CapabilityVulkanMemoryModelDeviceScope = 5346, + CapabilityVulkanMemoryModelDeviceScopeKHR = 5346, + CapabilityPhysicalStorageBufferAddresses = 5347, + CapabilityPhysicalStorageBufferAddressesEXT = 5347, + CapabilityComputeDerivativeGroupLinearNV = 5350, + CapabilityRayTracingProvisionalKHR = 5353, + CapabilityCooperativeMatrixNV = 5357, + CapabilityFragmentShaderSampleInterlockEXT = 5363, + CapabilityFragmentShaderShadingRateInterlockEXT = 5372, + CapabilityShaderSMBuiltinsNV = 5373, + CapabilityFragmentShaderPixelInterlockEXT = 5378, + CapabilityDemoteToHelperInvocationEXT = 5379, + CapabilitySubgroupShuffleINTEL = 5568, + CapabilitySubgroupBufferBlockIOINTEL = 5569, + CapabilitySubgroupImageBlockIOINTEL = 5570, + CapabilitySubgroupImageMediaBlockIOINTEL = 5579, + CapabilityIntegerFunctions2INTEL = 5584, + CapabilitySubgroupAvcMotionEstimationINTEL = 5696, + CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697, + CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698, + CapabilityMax = 0x7fffffff, +}; + +enum RayFlagsShift { + RayFlagsOpaqueKHRShift = 0, + RayFlagsNoOpaqueKHRShift = 1, + RayFlagsTerminateOnFirstHitKHRShift = 2, + RayFlagsSkipClosestHitShaderKHRShift = 3, + RayFlagsCullBackFacingTrianglesKHRShift = 4, + RayFlagsCullFrontFacingTrianglesKHRShift = 5, + RayFlagsCullOpaqueKHRShift = 6, + RayFlagsCullNoOpaqueKHRShift = 7, + RayFlagsSkipTrianglesKHRShift = 8, + RayFlagsSkipAABBsKHRShift = 9, + RayFlagsMax = 0x7fffffff, +}; + +enum RayFlagsMask { + RayFlagsMaskNone = 0, + RayFlagsOpaqueKHRMask = 0x00000001, + RayFlagsNoOpaqueKHRMask = 0x00000002, + RayFlagsTerminateOnFirstHitKHRMask = 0x00000004, + RayFlagsSkipClosestHitShaderKHRMask = 0x00000008, + RayFlagsCullBackFacingTrianglesKHRMask = 0x00000010, + RayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020, + RayFlagsCullOpaqueKHRMask = 0x00000040, + RayFlagsCullNoOpaqueKHRMask = 0x00000080, + RayFlagsSkipTrianglesKHRMask = 0x00000100, + RayFlagsSkipAABBsKHRMask = 0x00000200, +}; + +enum RayQueryIntersection { + RayQueryIntersectionRayQueryCandidateIntersectionKHR = 0, + RayQueryIntersectionRayQueryCommittedIntersectionKHR = 1, + RayQueryIntersectionMax = 0x7fffffff, +}; + +enum RayQueryCommittedIntersectionType { + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR = 0, + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR = 1, + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR = 2, + RayQueryCommittedIntersectionTypeMax = 0x7fffffff, +}; + +enum RayQueryCandidateIntersectionType { + RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR = 0, + RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR = 1, + RayQueryCandidateIntersectionTypeMax = 0x7fffffff, +}; + +enum Op { + OpNop = 0, + OpUndef = 1, + OpSourceContinued = 2, + OpSource = 3, + OpSourceExtension = 4, + OpName = 5, + OpMemberName = 6, + OpString = 7, + OpLine = 8, + OpExtension = 10, + OpExtInstImport = 11, + OpExtInst = 12, + OpMemoryModel = 14, + OpEntryPoint = 15, + OpExecutionMode = 16, + OpCapability = 17, + OpTypeVoid = 19, + OpTypeBool = 20, + OpTypeInt = 21, + OpTypeFloat = 22, + OpTypeVector = 23, + OpTypeMatrix = 24, + OpTypeImage = 25, + OpTypeSampler = 26, + OpTypeSampledImage = 27, + OpTypeArray = 28, + OpTypeRuntimeArray = 29, + OpTypeStruct = 30, + OpTypeOpaque = 31, + OpTypePointer = 32, + OpTypeFunction = 33, + OpTypeEvent = 34, + OpTypeDeviceEvent = 35, + OpTypeReserveId = 36, + OpTypeQueue = 37, + OpTypePipe = 38, + OpTypeForwardPointer = 39, + OpConstantTrue = 41, + OpConstantFalse = 42, + OpConstant = 43, + OpConstantComposite = 44, + OpConstantSampler = 45, + OpConstantNull = 46, + OpSpecConstantTrue = 48, + OpSpecConstantFalse = 49, + OpSpecConstant = 50, + OpSpecConstantComposite = 51, + OpSpecConstantOp = 52, + OpFunction = 54, + OpFunctionParameter = 55, + OpFunctionEnd = 56, + OpFunctionCall = 57, + OpVariable = 59, + OpImageTexelPointer = 60, + OpLoad = 61, + OpStore = 62, + OpCopyMemory = 63, + OpCopyMemorySized = 64, + OpAccessChain = 65, + OpInBoundsAccessChain = 66, + OpPtrAccessChain = 67, + OpArrayLength = 68, + OpGenericPtrMemSemantics = 69, + OpInBoundsPtrAccessChain = 70, + OpDecorate = 71, + OpMemberDecorate = 72, + OpDecorationGroup = 73, + OpGroupDecorate = 74, + OpGroupMemberDecorate = 75, + OpVectorExtractDynamic = 77, + OpVectorInsertDynamic = 78, + OpVectorShuffle = 79, + OpCompositeConstruct = 80, + OpCompositeExtract = 81, + OpCompositeInsert = 82, + OpCopyObject = 83, + OpTranspose = 84, + OpSampledImage = 86, + OpImageSampleImplicitLod = 87, + OpImageSampleExplicitLod = 88, + OpImageSampleDrefImplicitLod = 89, + OpImageSampleDrefExplicitLod = 90, + OpImageSampleProjImplicitLod = 91, + OpImageSampleProjExplicitLod = 92, + OpImageSampleProjDrefImplicitLod = 93, + OpImageSampleProjDrefExplicitLod = 94, + OpImageFetch = 95, + OpImageGather = 96, + OpImageDrefGather = 97, + OpImageRead = 98, + OpImageWrite = 99, + OpImage = 100, + OpImageQueryFormat = 101, + OpImageQueryOrder = 102, + OpImageQuerySizeLod = 103, + OpImageQuerySize = 104, + OpImageQueryLod = 105, + OpImageQueryLevels = 106, + OpImageQuerySamples = 107, + OpConvertFToU = 109, + OpConvertFToS = 110, + OpConvertSToF = 111, + OpConvertUToF = 112, + OpUConvert = 113, + OpSConvert = 114, + OpFConvert = 115, + OpQuantizeToF16 = 116, + OpConvertPtrToU = 117, + OpSatConvertSToU = 118, + OpSatConvertUToS = 119, + OpConvertUToPtr = 120, + OpPtrCastToGeneric = 121, + OpGenericCastToPtr = 122, + OpGenericCastToPtrExplicit = 123, + OpBitcast = 124, + OpSNegate = 126, + OpFNegate = 127, + OpIAdd = 128, + OpFAdd = 129, + OpISub = 130, + OpFSub = 131, + OpIMul = 132, + OpFMul = 133, + OpUDiv = 134, + OpSDiv = 135, + OpFDiv = 136, + OpUMod = 137, + OpSRem = 138, + OpSMod = 139, + OpFRem = 140, + OpFMod = 141, + OpVectorTimesScalar = 142, + OpMatrixTimesScalar = 143, + OpVectorTimesMatrix = 144, + OpMatrixTimesVector = 145, + OpMatrixTimesMatrix = 146, + OpOuterProduct = 147, + OpDot = 148, + OpIAddCarry = 149, + OpISubBorrow = 150, + OpUMulExtended = 151, + OpSMulExtended = 152, + OpAny = 154, + OpAll = 155, + OpIsNan = 156, + OpIsInf = 157, + OpIsFinite = 158, + OpIsNormal = 159, + OpSignBitSet = 160, + OpLessOrGreater = 161, + OpOrdered = 162, + OpUnordered = 163, + OpLogicalEqual = 164, + OpLogicalNotEqual = 165, + OpLogicalOr = 166, + OpLogicalAnd = 167, + OpLogicalNot = 168, + OpSelect = 169, + OpIEqual = 170, + OpINotEqual = 171, + OpUGreaterThan = 172, + OpSGreaterThan = 173, + OpUGreaterThanEqual = 174, + OpSGreaterThanEqual = 175, + OpULessThan = 176, + OpSLessThan = 177, + OpULessThanEqual = 178, + OpSLessThanEqual = 179, + OpFOrdEqual = 180, + OpFUnordEqual = 181, + OpFOrdNotEqual = 182, + OpFUnordNotEqual = 183, + OpFOrdLessThan = 184, + OpFUnordLessThan = 185, + OpFOrdGreaterThan = 186, + OpFUnordGreaterThan = 187, + OpFOrdLessThanEqual = 188, + OpFUnordLessThanEqual = 189, + OpFOrdGreaterThanEqual = 190, + OpFUnordGreaterThanEqual = 191, + OpShiftRightLogical = 194, + OpShiftRightArithmetic = 195, + OpShiftLeftLogical = 196, + OpBitwiseOr = 197, + OpBitwiseXor = 198, + OpBitwiseAnd = 199, + OpNot = 200, + OpBitFieldInsert = 201, + OpBitFieldSExtract = 202, + OpBitFieldUExtract = 203, + OpBitReverse = 204, + OpBitCount = 205, + OpDPdx = 207, + OpDPdy = 208, + OpFwidth = 209, + OpDPdxFine = 210, + OpDPdyFine = 211, + OpFwidthFine = 212, + OpDPdxCoarse = 213, + OpDPdyCoarse = 214, + OpFwidthCoarse = 215, + OpEmitVertex = 218, + OpEndPrimitive = 219, + OpEmitStreamVertex = 220, + OpEndStreamPrimitive = 221, + OpControlBarrier = 224, + OpMemoryBarrier = 225, + OpAtomicLoad = 227, + OpAtomicStore = 228, + OpAtomicExchange = 229, + OpAtomicCompareExchange = 230, + OpAtomicCompareExchangeWeak = 231, + OpAtomicIIncrement = 232, + OpAtomicIDecrement = 233, + OpAtomicIAdd = 234, + OpAtomicISub = 235, + OpAtomicSMin = 236, + OpAtomicUMin = 237, + OpAtomicSMax = 238, + OpAtomicUMax = 239, + OpAtomicAnd = 240, + OpAtomicOr = 241, + OpAtomicXor = 242, + OpPhi = 245, + OpLoopMerge = 246, + OpSelectionMerge = 247, + OpLabel = 248, + OpBranch = 249, + OpBranchConditional = 250, + OpSwitch = 251, + OpKill = 252, + OpReturn = 253, + OpReturnValue = 254, + OpUnreachable = 255, + OpLifetimeStart = 256, + OpLifetimeStop = 257, + OpGroupAsyncCopy = 259, + OpGroupWaitEvents = 260, + OpGroupAll = 261, + OpGroupAny = 262, + OpGroupBroadcast = 263, + OpGroupIAdd = 264, + OpGroupFAdd = 265, + OpGroupFMin = 266, + OpGroupUMin = 267, + OpGroupSMin = 268, + OpGroupFMax = 269, + OpGroupUMax = 270, + OpGroupSMax = 271, + OpReadPipe = 274, + OpWritePipe = 275, + OpReservedReadPipe = 276, + OpReservedWritePipe = 277, + OpReserveReadPipePackets = 278, + OpReserveWritePipePackets = 279, + OpCommitReadPipe = 280, + OpCommitWritePipe = 281, + OpIsValidReserveId = 282, + OpGetNumPipePackets = 283, + OpGetMaxPipePackets = 284, + OpGroupReserveReadPipePackets = 285, + OpGroupReserveWritePipePackets = 286, + OpGroupCommitReadPipe = 287, + OpGroupCommitWritePipe = 288, + OpEnqueueMarker = 291, + OpEnqueueKernel = 292, + OpGetKernelNDrangeSubGroupCount = 293, + OpGetKernelNDrangeMaxSubGroupSize = 294, + OpGetKernelWorkGroupSize = 295, + OpGetKernelPreferredWorkGroupSizeMultiple = 296, + OpRetainEvent = 297, + OpReleaseEvent = 298, + OpCreateUserEvent = 299, + OpIsValidEvent = 300, + OpSetUserEventStatus = 301, + OpCaptureEventProfilingInfo = 302, + OpGetDefaultQueue = 303, + OpBuildNDRange = 304, + OpImageSparseSampleImplicitLod = 305, + OpImageSparseSampleExplicitLod = 306, + OpImageSparseSampleDrefImplicitLod = 307, + OpImageSparseSampleDrefExplicitLod = 308, + OpImageSparseSampleProjImplicitLod = 309, + OpImageSparseSampleProjExplicitLod = 310, + OpImageSparseSampleProjDrefImplicitLod = 311, + OpImageSparseSampleProjDrefExplicitLod = 312, + OpImageSparseFetch = 313, + OpImageSparseGather = 314, + OpImageSparseDrefGather = 315, + OpImageSparseTexelsResident = 316, + OpNoLine = 317, + OpAtomicFlagTestAndSet = 318, + OpAtomicFlagClear = 319, + OpImageSparseRead = 320, + OpSizeOf = 321, + OpTypePipeStorage = 322, + OpConstantPipeStorage = 323, + OpCreatePipeFromPipeStorage = 324, + OpGetKernelLocalSizeForSubgroupCount = 325, + OpGetKernelMaxNumSubgroups = 326, + OpTypeNamedBarrier = 327, + OpNamedBarrierInitialize = 328, + OpMemoryNamedBarrier = 329, + OpModuleProcessed = 330, + OpExecutionModeId = 331, + OpDecorateId = 332, + OpGroupNonUniformElect = 333, + OpGroupNonUniformAll = 334, + OpGroupNonUniformAny = 335, + OpGroupNonUniformAllEqual = 336, + OpGroupNonUniformBroadcast = 337, + OpGroupNonUniformBroadcastFirst = 338, + OpGroupNonUniformBallot = 339, + OpGroupNonUniformInverseBallot = 340, + OpGroupNonUniformBallotBitExtract = 341, + OpGroupNonUniformBallotBitCount = 342, + OpGroupNonUniformBallotFindLSB = 343, + OpGroupNonUniformBallotFindMSB = 344, + OpGroupNonUniformShuffle = 345, + OpGroupNonUniformShuffleXor = 346, + OpGroupNonUniformShuffleUp = 347, + OpGroupNonUniformShuffleDown = 348, + OpGroupNonUniformIAdd = 349, + OpGroupNonUniformFAdd = 350, + OpGroupNonUniformIMul = 351, + OpGroupNonUniformFMul = 352, + OpGroupNonUniformSMin = 353, + OpGroupNonUniformUMin = 354, + OpGroupNonUniformFMin = 355, + OpGroupNonUniformSMax = 356, + OpGroupNonUniformUMax = 357, + OpGroupNonUniformFMax = 358, + OpGroupNonUniformBitwiseAnd = 359, + OpGroupNonUniformBitwiseOr = 360, + OpGroupNonUniformBitwiseXor = 361, + OpGroupNonUniformLogicalAnd = 362, + OpGroupNonUniformLogicalOr = 363, + OpGroupNonUniformLogicalXor = 364, + OpGroupNonUniformQuadBroadcast = 365, + OpGroupNonUniformQuadSwap = 366, + OpCopyLogical = 400, + OpPtrEqual = 401, + OpPtrNotEqual = 402, + OpPtrDiff = 403, + OpSubgroupBallotKHR = 4421, + OpSubgroupFirstInvocationKHR = 4422, + OpSubgroupAllKHR = 4428, + OpSubgroupAnyKHR = 4429, + OpSubgroupAllEqualKHR = 4430, + OpSubgroupReadInvocationKHR = 4432, + OpTypeRayQueryProvisionalKHR = 4472, + OpRayQueryInitializeKHR = 4473, + OpRayQueryTerminateKHR = 4474, + OpRayQueryGenerateIntersectionKHR = 4475, + OpRayQueryConfirmIntersectionKHR = 4476, + OpRayQueryProceedKHR = 4477, + OpRayQueryGetIntersectionTypeKHR = 4479, + OpGroupIAddNonUniformAMD = 5000, + OpGroupFAddNonUniformAMD = 5001, + OpGroupFMinNonUniformAMD = 5002, + OpGroupUMinNonUniformAMD = 5003, + OpGroupSMinNonUniformAMD = 5004, + OpGroupFMaxNonUniformAMD = 5005, + OpGroupUMaxNonUniformAMD = 5006, + OpGroupSMaxNonUniformAMD = 5007, + OpFragmentMaskFetchAMD = 5011, + OpFragmentFetchAMD = 5012, + OpReadClockKHR = 5056, + OpImageSampleFootprintNV = 5283, + OpGroupNonUniformPartitionNV = 5296, + OpWritePackedPrimitiveIndices4x8NV = 5299, + OpReportIntersectionKHR = 5334, + OpReportIntersectionNV = 5334, + OpIgnoreIntersectionKHR = 5335, + OpIgnoreIntersectionNV = 5335, + OpTerminateRayKHR = 5336, + OpTerminateRayNV = 5336, + OpTraceNV = 5337, + OpTraceRayKHR = 5337, + OpTypeAccelerationStructureKHR = 5341, + OpTypeAccelerationStructureNV = 5341, + OpExecuteCallableKHR = 5344, + OpExecuteCallableNV = 5344, + OpTypeCooperativeMatrixNV = 5358, + OpCooperativeMatrixLoadNV = 5359, + OpCooperativeMatrixStoreNV = 5360, + OpCooperativeMatrixMulAddNV = 5361, + OpCooperativeMatrixLengthNV = 5362, + OpBeginInvocationInterlockEXT = 5364, + OpEndInvocationInterlockEXT = 5365, + OpDemoteToHelperInvocationEXT = 5380, + OpIsHelperInvocationEXT = 5381, + OpSubgroupShuffleINTEL = 5571, + OpSubgroupShuffleDownINTEL = 5572, + OpSubgroupShuffleUpINTEL = 5573, + OpSubgroupShuffleXorINTEL = 5574, + OpSubgroupBlockReadINTEL = 5575, + OpSubgroupBlockWriteINTEL = 5576, + OpSubgroupImageBlockReadINTEL = 5577, + OpSubgroupImageBlockWriteINTEL = 5578, + OpSubgroupImageMediaBlockReadINTEL = 5580, + OpSubgroupImageMediaBlockWriteINTEL = 5581, + OpUCountLeadingZerosINTEL = 5585, + OpUCountTrailingZerosINTEL = 5586, + OpAbsISubINTEL = 5587, + OpAbsUSubINTEL = 5588, + OpIAddSatINTEL = 5589, + OpUAddSatINTEL = 5590, + OpIAverageINTEL = 5591, + OpUAverageINTEL = 5592, + OpIAverageRoundedINTEL = 5593, + OpUAverageRoundedINTEL = 5594, + OpISubSatINTEL = 5595, + OpUSubSatINTEL = 5596, + OpIMul32x16INTEL = 5597, + OpUMul32x16INTEL = 5598, + OpDecorateString = 5632, + OpDecorateStringGOOGLE = 5632, + OpMemberDecorateString = 5633, + OpMemberDecorateStringGOOGLE = 5633, + OpVmeImageINTEL = 5699, + OpTypeVmeImageINTEL = 5700, + OpTypeAvcImePayloadINTEL = 5701, + OpTypeAvcRefPayloadINTEL = 5702, + OpTypeAvcSicPayloadINTEL = 5703, + OpTypeAvcMcePayloadINTEL = 5704, + OpTypeAvcMceResultINTEL = 5705, + OpTypeAvcImeResultINTEL = 5706, + OpTypeAvcImeResultSingleReferenceStreamoutINTEL = 5707, + OpTypeAvcImeResultDualReferenceStreamoutINTEL = 5708, + OpTypeAvcImeSingleReferenceStreaminINTEL = 5709, + OpTypeAvcImeDualReferenceStreaminINTEL = 5710, + OpTypeAvcRefResultINTEL = 5711, + OpTypeAvcSicResultINTEL = 5712, + OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL = 5713, + OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL = 5714, + OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL = 5715, + OpSubgroupAvcMceSetInterShapePenaltyINTEL = 5716, + OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL = 5717, + OpSubgroupAvcMceSetInterDirectionPenaltyINTEL = 5718, + OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL = 5719, + OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL = 5720, + OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL = 5721, + OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL = 5722, + OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL = 5723, + OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL = 5724, + OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL = 5725, + OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL = 5726, + OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL = 5727, + OpSubgroupAvcMceSetAcOnlyHaarINTEL = 5728, + OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL = 5729, + OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL = 5730, + OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL = 5731, + OpSubgroupAvcMceConvertToImePayloadINTEL = 5732, + OpSubgroupAvcMceConvertToImeResultINTEL = 5733, + OpSubgroupAvcMceConvertToRefPayloadINTEL = 5734, + OpSubgroupAvcMceConvertToRefResultINTEL = 5735, + OpSubgroupAvcMceConvertToSicPayloadINTEL = 5736, + OpSubgroupAvcMceConvertToSicResultINTEL = 5737, + OpSubgroupAvcMceGetMotionVectorsINTEL = 5738, + OpSubgroupAvcMceGetInterDistortionsINTEL = 5739, + OpSubgroupAvcMceGetBestInterDistortionsINTEL = 5740, + OpSubgroupAvcMceGetInterMajorShapeINTEL = 5741, + OpSubgroupAvcMceGetInterMinorShapeINTEL = 5742, + OpSubgroupAvcMceGetInterDirectionsINTEL = 5743, + OpSubgroupAvcMceGetInterMotionVectorCountINTEL = 5744, + OpSubgroupAvcMceGetInterReferenceIdsINTEL = 5745, + OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL = 5746, + OpSubgroupAvcImeInitializeINTEL = 5747, + OpSubgroupAvcImeSetSingleReferenceINTEL = 5748, + OpSubgroupAvcImeSetDualReferenceINTEL = 5749, + OpSubgroupAvcImeRefWindowSizeINTEL = 5750, + OpSubgroupAvcImeAdjustRefOffsetINTEL = 5751, + OpSubgroupAvcImeConvertToMcePayloadINTEL = 5752, + OpSubgroupAvcImeSetMaxMotionVectorCountINTEL = 5753, + OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL = 5754, + OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL = 5755, + OpSubgroupAvcImeSetWeightedSadINTEL = 5756, + OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL = 5757, + OpSubgroupAvcImeEvaluateWithDualReferenceINTEL = 5758, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL = 5759, + OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL = 5760, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL = 5761, + OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL = 5762, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL = 5763, + OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL = 5764, + OpSubgroupAvcImeConvertToMceResultINTEL = 5765, + OpSubgroupAvcImeGetSingleReferenceStreaminINTEL = 5766, + OpSubgroupAvcImeGetDualReferenceStreaminINTEL = 5767, + OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL = 5768, + OpSubgroupAvcImeStripDualReferenceStreamoutINTEL = 5769, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL = 5770, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL = 5771, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL = 5772, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL = 5773, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL = 5774, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL = 5775, + OpSubgroupAvcImeGetBorderReachedINTEL = 5776, + OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL = 5777, + OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL = 5778, + OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL = 5779, + OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL = 5780, + OpSubgroupAvcFmeInitializeINTEL = 5781, + OpSubgroupAvcBmeInitializeINTEL = 5782, + OpSubgroupAvcRefConvertToMcePayloadINTEL = 5783, + OpSubgroupAvcRefSetBidirectionalMixDisableINTEL = 5784, + OpSubgroupAvcRefSetBilinearFilterEnableINTEL = 5785, + OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL = 5786, + OpSubgroupAvcRefEvaluateWithDualReferenceINTEL = 5787, + OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL = 5788, + OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL = 5789, + OpSubgroupAvcRefConvertToMceResultINTEL = 5790, + OpSubgroupAvcSicInitializeINTEL = 5791, + OpSubgroupAvcSicConfigureSkcINTEL = 5792, + OpSubgroupAvcSicConfigureIpeLumaINTEL = 5793, + OpSubgroupAvcSicConfigureIpeLumaChromaINTEL = 5794, + OpSubgroupAvcSicGetMotionVectorMaskINTEL = 5795, + OpSubgroupAvcSicConvertToMcePayloadINTEL = 5796, + OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL = 5797, + OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL = 5798, + OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL = 5799, + OpSubgroupAvcSicSetBilinearFilterEnableINTEL = 5800, + OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL = 5801, + OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL = 5802, + OpSubgroupAvcSicEvaluateIpeINTEL = 5803, + OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL = 5804, + OpSubgroupAvcSicEvaluateWithDualReferenceINTEL = 5805, + OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL = 5806, + OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL = 5807, + OpSubgroupAvcSicConvertToMceResultINTEL = 5808, + OpSubgroupAvcSicGetIpeLumaShapeINTEL = 5809, + OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL = 5810, + OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL = 5811, + OpSubgroupAvcSicGetPackedIpeLumaModesINTEL = 5812, + OpSubgroupAvcSicGetIpeChromaModeINTEL = 5813, + OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, + OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, + OpSubgroupAvcSicGetInterRawSadsINTEL = 5816, + OpRayQueryGetRayTMinKHR = 6016, + OpRayQueryGetRayFlagsKHR = 6017, + OpRayQueryGetIntersectionTKHR = 6018, + OpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019, + OpRayQueryGetIntersectionInstanceIdKHR = 6020, + OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021, + OpRayQueryGetIntersectionGeometryIndexKHR = 6022, + OpRayQueryGetIntersectionPrimitiveIndexKHR = 6023, + OpRayQueryGetIntersectionBarycentricsKHR = 6024, + OpRayQueryGetIntersectionFrontFaceKHR = 6025, + OpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026, + OpRayQueryGetIntersectionObjectRayDirectionKHR = 6027, + OpRayQueryGetIntersectionObjectRayOriginKHR = 6028, + OpRayQueryGetWorldRayDirectionKHR = 6029, + OpRayQueryGetWorldRayOriginKHR = 6030, + OpRayQueryGetIntersectionObjectToWorldKHR = 6031, + OpRayQueryGetIntersectionWorldToObjectKHR = 6032, + OpMax = 0x7fffffff, +}; + +#ifdef SPV_ENABLE_UTILITY_CODE +inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) { + *hasResult = *hasResultType = false; + switch (opcode) { + default: /* unknown opcode */ break; + case OpNop: *hasResult = false; *hasResultType = false; break; + case OpUndef: *hasResult = true; *hasResultType = true; break; + case OpSourceContinued: *hasResult = false; *hasResultType = false; break; + case OpSource: *hasResult = false; *hasResultType = false; break; + case OpSourceExtension: *hasResult = false; *hasResultType = false; break; + case OpName: *hasResult = false; *hasResultType = false; break; + case OpMemberName: *hasResult = false; *hasResultType = false; break; + case OpString: *hasResult = true; *hasResultType = false; break; + case OpLine: *hasResult = false; *hasResultType = false; break; + case OpExtension: *hasResult = false; *hasResultType = false; break; + case OpExtInstImport: *hasResult = true; *hasResultType = false; break; + case OpExtInst: *hasResult = true; *hasResultType = true; break; + case OpMemoryModel: *hasResult = false; *hasResultType = false; break; + case OpEntryPoint: *hasResult = false; *hasResultType = false; break; + case OpExecutionMode: *hasResult = false; *hasResultType = false; break; + case OpCapability: *hasResult = false; *hasResultType = false; break; + case OpTypeVoid: *hasResult = true; *hasResultType = false; break; + case OpTypeBool: *hasResult = true; *hasResultType = false; break; + case OpTypeInt: *hasResult = true; *hasResultType = false; break; + case OpTypeFloat: *hasResult = true; *hasResultType = false; break; + case OpTypeVector: *hasResult = true; *hasResultType = false; break; + case OpTypeMatrix: *hasResult = true; *hasResultType = false; break; + case OpTypeImage: *hasResult = true; *hasResultType = false; break; + case OpTypeSampler: *hasResult = true; *hasResultType = false; break; + case OpTypeSampledImage: *hasResult = true; *hasResultType = false; break; + case OpTypeArray: *hasResult = true; *hasResultType = false; break; + case OpTypeRuntimeArray: *hasResult = true; *hasResultType = false; break; + case OpTypeStruct: *hasResult = true; *hasResultType = false; break; + case OpTypeOpaque: *hasResult = true; *hasResultType = false; break; + case OpTypePointer: *hasResult = true; *hasResultType = false; break; + case OpTypeFunction: *hasResult = true; *hasResultType = false; break; + case OpTypeEvent: *hasResult = true; *hasResultType = false; break; + case OpTypeDeviceEvent: *hasResult = true; *hasResultType = false; break; + case OpTypeReserveId: *hasResult = true; *hasResultType = false; break; + case OpTypeQueue: *hasResult = true; *hasResultType = false; break; + case OpTypePipe: *hasResult = true; *hasResultType = false; break; + case OpTypeForwardPointer: *hasResult = false; *hasResultType = false; break; + case OpConstantTrue: *hasResult = true; *hasResultType = true; break; + case OpConstantFalse: *hasResult = true; *hasResultType = true; break; + case OpConstant: *hasResult = true; *hasResultType = true; break; + case OpConstantComposite: *hasResult = true; *hasResultType = true; break; + case OpConstantSampler: *hasResult = true; *hasResultType = true; break; + case OpConstantNull: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantTrue: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantFalse: *hasResult = true; *hasResultType = true; break; + case OpSpecConstant: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantComposite: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantOp: *hasResult = true; *hasResultType = true; break; + case OpFunction: *hasResult = true; *hasResultType = true; break; + case OpFunctionParameter: *hasResult = true; *hasResultType = true; break; + case OpFunctionEnd: *hasResult = false; *hasResultType = false; break; + case OpFunctionCall: *hasResult = true; *hasResultType = true; break; + case OpVariable: *hasResult = true; *hasResultType = true; break; + case OpImageTexelPointer: *hasResult = true; *hasResultType = true; break; + case OpLoad: *hasResult = true; *hasResultType = true; break; + case OpStore: *hasResult = false; *hasResultType = false; break; + case OpCopyMemory: *hasResult = false; *hasResultType = false; break; + case OpCopyMemorySized: *hasResult = false; *hasResultType = false; break; + case OpAccessChain: *hasResult = true; *hasResultType = true; break; + case OpInBoundsAccessChain: *hasResult = true; *hasResultType = true; break; + case OpPtrAccessChain: *hasResult = true; *hasResultType = true; break; + case OpArrayLength: *hasResult = true; *hasResultType = true; break; + case OpGenericPtrMemSemantics: *hasResult = true; *hasResultType = true; break; + case OpInBoundsPtrAccessChain: *hasResult = true; *hasResultType = true; break; + case OpDecorate: *hasResult = false; *hasResultType = false; break; + case OpMemberDecorate: *hasResult = false; *hasResultType = false; break; + case OpDecorationGroup: *hasResult = true; *hasResultType = false; break; + case OpGroupDecorate: *hasResult = false; *hasResultType = false; break; + case OpGroupMemberDecorate: *hasResult = false; *hasResultType = false; break; + case OpVectorExtractDynamic: *hasResult = true; *hasResultType = true; break; + case OpVectorInsertDynamic: *hasResult = true; *hasResultType = true; break; + case OpVectorShuffle: *hasResult = true; *hasResultType = true; break; + case OpCompositeConstruct: *hasResult = true; *hasResultType = true; break; + case OpCompositeExtract: *hasResult = true; *hasResultType = true; break; + case OpCompositeInsert: *hasResult = true; *hasResultType = true; break; + case OpCopyObject: *hasResult = true; *hasResultType = true; break; + case OpTranspose: *hasResult = true; *hasResultType = true; break; + case OpSampledImage: *hasResult = true; *hasResultType = true; break; + case OpImageSampleImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageFetch: *hasResult = true; *hasResultType = true; break; + case OpImageGather: *hasResult = true; *hasResultType = true; break; + case OpImageDrefGather: *hasResult = true; *hasResultType = true; break; + case OpImageRead: *hasResult = true; *hasResultType = true; break; + case OpImageWrite: *hasResult = false; *hasResultType = false; break; + case OpImage: *hasResult = true; *hasResultType = true; break; + case OpImageQueryFormat: *hasResult = true; *hasResultType = true; break; + case OpImageQueryOrder: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySizeLod: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySize: *hasResult = true; *hasResultType = true; break; + case OpImageQueryLod: *hasResult = true; *hasResultType = true; break; + case OpImageQueryLevels: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySamples: *hasResult = true; *hasResultType = true; break; + case OpConvertFToU: *hasResult = true; *hasResultType = true; break; + case OpConvertFToS: *hasResult = true; *hasResultType = true; break; + case OpConvertSToF: *hasResult = true; *hasResultType = true; break; + case OpConvertUToF: *hasResult = true; *hasResultType = true; break; + case OpUConvert: *hasResult = true; *hasResultType = true; break; + case OpSConvert: *hasResult = true; *hasResultType = true; break; + case OpFConvert: *hasResult = true; *hasResultType = true; break; + case OpQuantizeToF16: *hasResult = true; *hasResultType = true; break; + case OpConvertPtrToU: *hasResult = true; *hasResultType = true; break; + case OpSatConvertSToU: *hasResult = true; *hasResultType = true; break; + case OpSatConvertUToS: *hasResult = true; *hasResultType = true; break; + case OpConvertUToPtr: *hasResult = true; *hasResultType = true; break; + case OpPtrCastToGeneric: *hasResult = true; *hasResultType = true; break; + case OpGenericCastToPtr: *hasResult = true; *hasResultType = true; break; + case OpGenericCastToPtrExplicit: *hasResult = true; *hasResultType = true; break; + case OpBitcast: *hasResult = true; *hasResultType = true; break; + case OpSNegate: *hasResult = true; *hasResultType = true; break; + case OpFNegate: *hasResult = true; *hasResultType = true; break; + case OpIAdd: *hasResult = true; *hasResultType = true; break; + case OpFAdd: *hasResult = true; *hasResultType = true; break; + case OpISub: *hasResult = true; *hasResultType = true; break; + case OpFSub: *hasResult = true; *hasResultType = true; break; + case OpIMul: *hasResult = true; *hasResultType = true; break; + case OpFMul: *hasResult = true; *hasResultType = true; break; + case OpUDiv: *hasResult = true; *hasResultType = true; break; + case OpSDiv: *hasResult = true; *hasResultType = true; break; + case OpFDiv: *hasResult = true; *hasResultType = true; break; + case OpUMod: *hasResult = true; *hasResultType = true; break; + case OpSRem: *hasResult = true; *hasResultType = true; break; + case OpSMod: *hasResult = true; *hasResultType = true; break; + case OpFRem: *hasResult = true; *hasResultType = true; break; + case OpFMod: *hasResult = true; *hasResultType = true; break; + case OpVectorTimesScalar: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesScalar: *hasResult = true; *hasResultType = true; break; + case OpVectorTimesMatrix: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesVector: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesMatrix: *hasResult = true; *hasResultType = true; break; + case OpOuterProduct: *hasResult = true; *hasResultType = true; break; + case OpDot: *hasResult = true; *hasResultType = true; break; + case OpIAddCarry: *hasResult = true; *hasResultType = true; break; + case OpISubBorrow: *hasResult = true; *hasResultType = true; break; + case OpUMulExtended: *hasResult = true; *hasResultType = true; break; + case OpSMulExtended: *hasResult = true; *hasResultType = true; break; + case OpAny: *hasResult = true; *hasResultType = true; break; + case OpAll: *hasResult = true; *hasResultType = true; break; + case OpIsNan: *hasResult = true; *hasResultType = true; break; + case OpIsInf: *hasResult = true; *hasResultType = true; break; + case OpIsFinite: *hasResult = true; *hasResultType = true; break; + case OpIsNormal: *hasResult = true; *hasResultType = true; break; + case OpSignBitSet: *hasResult = true; *hasResultType = true; break; + case OpLessOrGreater: *hasResult = true; *hasResultType = true; break; + case OpOrdered: *hasResult = true; *hasResultType = true; break; + case OpUnordered: *hasResult = true; *hasResultType = true; break; + case OpLogicalEqual: *hasResult = true; *hasResultType = true; break; + case OpLogicalNotEqual: *hasResult = true; *hasResultType = true; break; + case OpLogicalOr: *hasResult = true; *hasResultType = true; break; + case OpLogicalAnd: *hasResult = true; *hasResultType = true; break; + case OpLogicalNot: *hasResult = true; *hasResultType = true; break; + case OpSelect: *hasResult = true; *hasResultType = true; break; + case OpIEqual: *hasResult = true; *hasResultType = true; break; + case OpINotEqual: *hasResult = true; *hasResultType = true; break; + case OpUGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpSGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpUGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpSGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpULessThan: *hasResult = true; *hasResultType = true; break; + case OpSLessThan: *hasResult = true; *hasResultType = true; break; + case OpULessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpSLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdNotEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordNotEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdLessThan: *hasResult = true; *hasResultType = true; break; + case OpFUnordLessThan: *hasResult = true; *hasResultType = true; break; + case OpFOrdGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpFUnordGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpFOrdLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpShiftRightLogical: *hasResult = true; *hasResultType = true; break; + case OpShiftRightArithmetic: *hasResult = true; *hasResultType = true; break; + case OpShiftLeftLogical: *hasResult = true; *hasResultType = true; break; + case OpBitwiseOr: *hasResult = true; *hasResultType = true; break; + case OpBitwiseXor: *hasResult = true; *hasResultType = true; break; + case OpBitwiseAnd: *hasResult = true; *hasResultType = true; break; + case OpNot: *hasResult = true; *hasResultType = true; break; + case OpBitFieldInsert: *hasResult = true; *hasResultType = true; break; + case OpBitFieldSExtract: *hasResult = true; *hasResultType = true; break; + case OpBitFieldUExtract: *hasResult = true; *hasResultType = true; break; + case OpBitReverse: *hasResult = true; *hasResultType = true; break; + case OpBitCount: *hasResult = true; *hasResultType = true; break; + case OpDPdx: *hasResult = true; *hasResultType = true; break; + case OpDPdy: *hasResult = true; *hasResultType = true; break; + case OpFwidth: *hasResult = true; *hasResultType = true; break; + case OpDPdxFine: *hasResult = true; *hasResultType = true; break; + case OpDPdyFine: *hasResult = true; *hasResultType = true; break; + case OpFwidthFine: *hasResult = true; *hasResultType = true; break; + case OpDPdxCoarse: *hasResult = true; *hasResultType = true; break; + case OpDPdyCoarse: *hasResult = true; *hasResultType = true; break; + case OpFwidthCoarse: *hasResult = true; *hasResultType = true; break; + case OpEmitVertex: *hasResult = false; *hasResultType = false; break; + case OpEndPrimitive: *hasResult = false; *hasResultType = false; break; + case OpEmitStreamVertex: *hasResult = false; *hasResultType = false; break; + case OpEndStreamPrimitive: *hasResult = false; *hasResultType = false; break; + case OpControlBarrier: *hasResult = false; *hasResultType = false; break; + case OpMemoryBarrier: *hasResult = false; *hasResultType = false; break; + case OpAtomicLoad: *hasResult = true; *hasResultType = true; break; + case OpAtomicStore: *hasResult = false; *hasResultType = false; break; + case OpAtomicExchange: *hasResult = true; *hasResultType = true; break; + case OpAtomicCompareExchange: *hasResult = true; *hasResultType = true; break; + case OpAtomicCompareExchangeWeak: *hasResult = true; *hasResultType = true; break; + case OpAtomicIIncrement: *hasResult = true; *hasResultType = true; break; + case OpAtomicIDecrement: *hasResult = true; *hasResultType = true; break; + case OpAtomicIAdd: *hasResult = true; *hasResultType = true; break; + case OpAtomicISub: *hasResult = true; *hasResultType = true; break; + case OpAtomicSMin: *hasResult = true; *hasResultType = true; break; + case OpAtomicUMin: *hasResult = true; *hasResultType = true; break; + case OpAtomicSMax: *hasResult = true; *hasResultType = true; break; + case OpAtomicUMax: *hasResult = true; *hasResultType = true; break; + case OpAtomicAnd: *hasResult = true; *hasResultType = true; break; + case OpAtomicOr: *hasResult = true; *hasResultType = true; break; + case OpAtomicXor: *hasResult = true; *hasResultType = true; break; + case OpPhi: *hasResult = true; *hasResultType = true; break; + case OpLoopMerge: *hasResult = false; *hasResultType = false; break; + case OpSelectionMerge: *hasResult = false; *hasResultType = false; break; + case OpLabel: *hasResult = true; *hasResultType = false; break; + case OpBranch: *hasResult = false; *hasResultType = false; break; + case OpBranchConditional: *hasResult = false; *hasResultType = false; break; + case OpSwitch: *hasResult = false; *hasResultType = false; break; + case OpKill: *hasResult = false; *hasResultType = false; break; + case OpReturn: *hasResult = false; *hasResultType = false; break; + case OpReturnValue: *hasResult = false; *hasResultType = false; break; + case OpUnreachable: *hasResult = false; *hasResultType = false; break; + case OpLifetimeStart: *hasResult = false; *hasResultType = false; break; + case OpLifetimeStop: *hasResult = false; *hasResultType = false; break; + case OpGroupAsyncCopy: *hasResult = true; *hasResultType = true; break; + case OpGroupWaitEvents: *hasResult = false; *hasResultType = false; break; + case OpGroupAll: *hasResult = true; *hasResultType = true; break; + case OpGroupAny: *hasResult = true; *hasResultType = true; break; + case OpGroupBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupIAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupFAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupFMin: *hasResult = true; *hasResultType = true; break; + case OpGroupUMin: *hasResult = true; *hasResultType = true; break; + case OpGroupSMin: *hasResult = true; *hasResultType = true; break; + case OpGroupFMax: *hasResult = true; *hasResultType = true; break; + case OpGroupUMax: *hasResult = true; *hasResultType = true; break; + case OpGroupSMax: *hasResult = true; *hasResultType = true; break; + case OpReadPipe: *hasResult = true; *hasResultType = true; break; + case OpWritePipe: *hasResult = true; *hasResultType = true; break; + case OpReservedReadPipe: *hasResult = true; *hasResultType = true; break; + case OpReservedWritePipe: *hasResult = true; *hasResultType = true; break; + case OpReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; + case OpReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; + case OpCommitReadPipe: *hasResult = false; *hasResultType = false; break; + case OpCommitWritePipe: *hasResult = false; *hasResultType = false; break; + case OpIsValidReserveId: *hasResult = true; *hasResultType = true; break; + case OpGetNumPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGetMaxPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupCommitReadPipe: *hasResult = false; *hasResultType = false; break; + case OpGroupCommitWritePipe: *hasResult = false; *hasResultType = false; break; + case OpEnqueueMarker: *hasResult = true; *hasResultType = true; break; + case OpEnqueueKernel: *hasResult = true; *hasResultType = true; break; + case OpGetKernelNDrangeSubGroupCount: *hasResult = true; *hasResultType = true; break; + case OpGetKernelNDrangeMaxSubGroupSize: *hasResult = true; *hasResultType = true; break; + case OpGetKernelWorkGroupSize: *hasResult = true; *hasResultType = true; break; + case OpGetKernelPreferredWorkGroupSizeMultiple: *hasResult = true; *hasResultType = true; break; + case OpRetainEvent: *hasResult = false; *hasResultType = false; break; + case OpReleaseEvent: *hasResult = false; *hasResultType = false; break; + case OpCreateUserEvent: *hasResult = true; *hasResultType = true; break; + case OpIsValidEvent: *hasResult = true; *hasResultType = true; break; + case OpSetUserEventStatus: *hasResult = false; *hasResultType = false; break; + case OpCaptureEventProfilingInfo: *hasResult = false; *hasResultType = false; break; + case OpGetDefaultQueue: *hasResult = true; *hasResultType = true; break; + case OpBuildNDRange: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseFetch: *hasResult = true; *hasResultType = true; break; + case OpImageSparseGather: *hasResult = true; *hasResultType = true; break; + case OpImageSparseDrefGather: *hasResult = true; *hasResultType = true; break; + case OpImageSparseTexelsResident: *hasResult = true; *hasResultType = true; break; + case OpNoLine: *hasResult = false; *hasResultType = false; break; + case OpAtomicFlagTestAndSet: *hasResult = true; *hasResultType = true; break; + case OpAtomicFlagClear: *hasResult = false; *hasResultType = false; break; + case OpImageSparseRead: *hasResult = true; *hasResultType = true; break; + case OpSizeOf: *hasResult = true; *hasResultType = true; break; + case OpTypePipeStorage: *hasResult = true; *hasResultType = false; break; + case OpConstantPipeStorage: *hasResult = true; *hasResultType = true; break; + case OpCreatePipeFromPipeStorage: *hasResult = true; *hasResultType = true; break; + case OpGetKernelLocalSizeForSubgroupCount: *hasResult = true; *hasResultType = true; break; + case OpGetKernelMaxNumSubgroups: *hasResult = true; *hasResultType = true; break; + case OpTypeNamedBarrier: *hasResult = true; *hasResultType = false; break; + case OpNamedBarrierInitialize: *hasResult = true; *hasResultType = true; break; + case OpMemoryNamedBarrier: *hasResult = false; *hasResultType = false; break; + case OpModuleProcessed: *hasResult = false; *hasResultType = false; break; + case OpExecutionModeId: *hasResult = false; *hasResultType = false; break; + case OpDecorateId: *hasResult = false; *hasResultType = false; break; + case OpGroupNonUniformElect: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAll: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAny: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAllEqual: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBroadcastFirst: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallot: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformInverseBallot: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotBitExtract: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotBitCount: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotFindLSB: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotFindMSB: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffle: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleUp: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleDown: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformIAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformIMul: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMul: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformSMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformUMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformSMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformUMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseAnd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseOr: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalAnd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalOr: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformQuadBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformQuadSwap: *hasResult = true; *hasResultType = true; break; + case OpCopyLogical: *hasResult = true; *hasResultType = true; break; + case OpPtrEqual: *hasResult = true; *hasResultType = true; break; + case OpPtrNotEqual: *hasResult = true; *hasResultType = true; break; + case OpPtrDiff: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break; + case OpTypeRayQueryProvisionalKHR: *hasResult = true; *hasResultType = false; break; + case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break; + case OpGroupIAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupUMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupSMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupUMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupSMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpFragmentMaskFetchAMD: *hasResult = true; *hasResultType = true; break; + case OpFragmentFetchAMD: *hasResult = true; *hasResultType = true; break; + case OpReadClockKHR: *hasResult = true; *hasResultType = true; break; + case OpImageSampleFootprintNV: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformPartitionNV: *hasResult = true; *hasResultType = true; break; + case OpWritePackedPrimitiveIndices4x8NV: *hasResult = false; *hasResultType = false; break; + case OpReportIntersectionNV: *hasResult = true; *hasResultType = true; break; + case OpIgnoreIntersectionNV: *hasResult = false; *hasResultType = false; break; + case OpTerminateRayNV: *hasResult = false; *hasResultType = false; break; + case OpTraceNV: *hasResult = false; *hasResultType = false; break; + case OpTypeAccelerationStructureNV: *hasResult = true; *hasResultType = false; break; + case OpExecuteCallableNV: *hasResult = false; *hasResultType = false; break; + case OpTypeCooperativeMatrixNV: *hasResult = true; *hasResultType = false; break; + case OpCooperativeMatrixLoadNV: *hasResult = true; *hasResultType = true; break; + case OpCooperativeMatrixStoreNV: *hasResult = false; *hasResultType = false; break; + case OpCooperativeMatrixMulAddNV: *hasResult = true; *hasResultType = true; break; + case OpCooperativeMatrixLengthNV: *hasResult = true; *hasResultType = true; break; + case OpBeginInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; + case OpEndInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; + case OpDemoteToHelperInvocationEXT: *hasResult = false; *hasResultType = false; break; + case OpIsHelperInvocationEXT: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleDownINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleUpINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleXorINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpSubgroupImageBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupImageBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpSubgroupImageMediaBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupImageMediaBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpUCountLeadingZerosINTEL: *hasResult = true; *hasResultType = true; break; + case OpUCountTrailingZerosINTEL: *hasResult = true; *hasResultType = true; break; + case OpAbsISubINTEL: *hasResult = true; *hasResultType = true; break; + case OpAbsUSubINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAddSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAddSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAverageINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAverageINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; + case OpISubSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break; + case OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break; + case OpDecorateString: *hasResult = false; *hasResultType = false; break; + case OpMemberDecorateString: *hasResult = false; *hasResultType = false; break; + case OpVmeImageINTEL: *hasResult = true; *hasResultType = true; break; + case OpTypeVmeImageINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImePayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcRefPayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcSicPayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcMcePayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcMceResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcRefResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcSicResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetAcOnlyHaarINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToImePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToImeResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToRefPayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToRefResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToSicPayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToSicResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetBestInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMajorShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMinorShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterDirectionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeRefWindowSizeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeAdjustRefOffsetINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetMaxMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetWeightedSadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeStripDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetBorderReachedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcFmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcBmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefSetBidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureSkcINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureIpeLumaINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureIpeLumaChromaINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetMotionVectorMaskINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateIpeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetIpeLumaShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedIpeLumaModesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetIpeChromaModeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetRayTMinKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetRayFlagsKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionTKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceCustomIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceIdKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionGeometryIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionPrimitiveIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionBarycentricsKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionFrontFaceKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetWorldRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetWorldRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break; + } +} +#endif /* SPV_ENABLE_UTILITY_CODE */ + +// Overload operator| for mask bit combining + +inline ImageOperandsMask operator|(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) | unsigned(b)); } +inline FPFastMathModeMask operator|(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) | unsigned(b)); } +inline SelectionControlMask operator|(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) | unsigned(b)); } +inline LoopControlMask operator|(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) | unsigned(b)); } +inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) | unsigned(b)); } +inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); } +inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); } +inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); } +inline RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); } + +} // end namespace spv + +#endif // #ifndef spirv_HPP + diff --git a/android/armeabi-v7a/include/SPIRV/spvIR.h b/android/armeabi-v7a/include/SPIRV/spvIR.h new file mode 100644 index 00000000..6523035e --- /dev/null +++ b/android/armeabi-v7a/include/SPIRV/spvIR.h @@ -0,0 +1,485 @@ +// +// Copyright (C) 2014 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// SPIRV-IR +// +// Simple in-memory representation (IR) of SPIRV. Just for holding +// Each function's CFG of blocks. Has this hierarchy: +// - Module, which is a list of +// - Function, which is a list of +// - Block, which is a list of +// - Instruction +// + +#pragma once +#ifndef spvIR_H +#define spvIR_H + +#include "spirv.hpp" + +#include +#include +#include +#include +#include +#include + +namespace spv { + +class Block; +class Function; +class Module; + +const Id NoResult = 0; +const Id NoType = 0; + +const Decoration NoPrecision = DecorationMax; + +#ifdef __GNUC__ +# define POTENTIALLY_UNUSED __attribute__((unused)) +#else +# define POTENTIALLY_UNUSED +#endif + +POTENTIALLY_UNUSED +const MemorySemanticsMask MemorySemanticsAllMemory = + (MemorySemanticsMask)(MemorySemanticsUniformMemoryMask | + MemorySemanticsWorkgroupMemoryMask | + MemorySemanticsAtomicCounterMemoryMask | + MemorySemanticsImageMemoryMask); + +struct IdImmediate { + bool isId; // true if word is an Id, false if word is an immediate + unsigned word; + IdImmediate(bool i, unsigned w) : isId(i), word(w) {} +}; + +// +// SPIR-V IR instruction. +// + +class Instruction { +public: + Instruction(Id resultId, Id typeId, Op opCode) : resultId(resultId), typeId(typeId), opCode(opCode), block(nullptr) { } + explicit Instruction(Op opCode) : resultId(NoResult), typeId(NoType), opCode(opCode), block(nullptr) { } + virtual ~Instruction() {} + void addIdOperand(Id id) { + operands.push_back(id); + idOperand.push_back(true); + } + void addImmediateOperand(unsigned int immediate) { + operands.push_back(immediate); + idOperand.push_back(false); + } + void setImmediateOperand(unsigned idx, unsigned int immediate) { + assert(!idOperand[idx]); + operands[idx] = immediate; + } + + void addStringOperand(const char* str) + { + unsigned int word; + char* wordString = (char*)&word; + char* wordPtr = wordString; + int charCount = 0; + char c; + do { + c = *(str++); + *(wordPtr++) = c; + ++charCount; + if (charCount == 4) { + addImmediateOperand(word); + wordPtr = wordString; + charCount = 0; + } + } while (c != 0); + + // deal with partial last word + if (charCount > 0) { + // pad with 0s + for (; charCount < 4; ++charCount) + *(wordPtr++) = 0; + addImmediateOperand(word); + } + } + bool isIdOperand(int op) const { return idOperand[op]; } + void setBlock(Block* b) { block = b; } + Block* getBlock() const { return block; } + Op getOpCode() const { return opCode; } + int getNumOperands() const + { + assert(operands.size() == idOperand.size()); + return (int)operands.size(); + } + Id getResultId() const { return resultId; } + Id getTypeId() const { return typeId; } + Id getIdOperand(int op) const { + assert(idOperand[op]); + return operands[op]; + } + unsigned int getImmediateOperand(int op) const { + assert(!idOperand[op]); + return operands[op]; + } + + // Write out the binary form. + void dump(std::vector& out) const + { + // Compute the wordCount + unsigned int wordCount = 1; + if (typeId) + ++wordCount; + if (resultId) + ++wordCount; + wordCount += (unsigned int)operands.size(); + + // Write out the beginning of the instruction + out.push_back(((wordCount) << WordCountShift) | opCode); + if (typeId) + out.push_back(typeId); + if (resultId) + out.push_back(resultId); + + // Write out the operands + for (int op = 0; op < (int)operands.size(); ++op) + out.push_back(operands[op]); + } + +protected: + Instruction(const Instruction&); + Id resultId; + Id typeId; + Op opCode; + std::vector operands; // operands, both and immediates (both are unsigned int) + std::vector idOperand; // true for operands that are , false for immediates + Block* block; +}; + +// +// SPIR-V IR block. +// + +class Block { +public: + Block(Id id, Function& parent); + virtual ~Block() + { + } + + Id getId() { return instructions.front()->getResultId(); } + + Function& getParent() const { return parent; } + void addInstruction(std::unique_ptr inst); + void addPredecessor(Block* pred) { predecessors.push_back(pred); pred->successors.push_back(this);} + void addLocalVariable(std::unique_ptr inst) { localVariables.push_back(std::move(inst)); } + const std::vector& getPredecessors() const { return predecessors; } + const std::vector& getSuccessors() const { return successors; } + const std::vector >& getInstructions() const { + return instructions; + } + const std::vector >& getLocalVariables() const { return localVariables; } + void setUnreachable() { unreachable = true; } + bool isUnreachable() const { return unreachable; } + // Returns the block's merge instruction, if one exists (otherwise null). + const Instruction* getMergeInstruction() const { + if (instructions.size() < 2) return nullptr; + const Instruction* nextToLast = (instructions.cend() - 2)->get(); + switch (nextToLast->getOpCode()) { + case OpSelectionMerge: + case OpLoopMerge: + return nextToLast; + default: + return nullptr; + } + return nullptr; + } + + // Change this block into a canonical dead merge block. Delete instructions + // as necessary. A canonical dead merge block has only an OpLabel and an + // OpUnreachable. + void rewriteAsCanonicalUnreachableMerge() { + assert(localVariables.empty()); + // Delete all instructions except for the label. + assert(instructions.size() > 0); + instructions.resize(1); + successors.clear(); + addInstruction(std::unique_ptr(new Instruction(OpUnreachable))); + } + // Change this block into a canonical dead continue target branching to the + // given header ID. Delete instructions as necessary. A canonical dead continue + // target has only an OpLabel and an unconditional branch back to the corresponding + // header. + void rewriteAsCanonicalUnreachableContinue(Block* header) { + assert(localVariables.empty()); + // Delete all instructions except for the label. + assert(instructions.size() > 0); + instructions.resize(1); + successors.clear(); + // Add OpBranch back to the header. + assert(header != nullptr); + Instruction* branch = new Instruction(OpBranch); + branch->addIdOperand(header->getId()); + addInstruction(std::unique_ptr(branch)); + successors.push_back(header); + } + + bool isTerminated() const + { + switch (instructions.back()->getOpCode()) { + case OpBranch: + case OpBranchConditional: + case OpSwitch: + case OpKill: + case OpReturn: + case OpReturnValue: + case OpUnreachable: + return true; + default: + return false; + } + } + + void dump(std::vector& out) const + { + instructions[0]->dump(out); + for (int i = 0; i < (int)localVariables.size(); ++i) + localVariables[i]->dump(out); + for (int i = 1; i < (int)instructions.size(); ++i) + instructions[i]->dump(out); + } + +protected: + Block(const Block&); + Block& operator=(Block&); + + // To enforce keeping parent and ownership in sync: + friend Function; + + std::vector > instructions; + std::vector predecessors, successors; + std::vector > localVariables; + Function& parent; + + // track whether this block is known to be uncreachable (not necessarily + // true for all unreachable blocks, but should be set at least + // for the extraneous ones introduced by the builder). + bool unreachable; +}; + +// The different reasons for reaching a block in the inReadableOrder traversal. +enum ReachReason { + // Reachable from the entry block via transfers of control, i.e. branches. + ReachViaControlFlow = 0, + // A continue target that is not reachable via control flow. + ReachDeadContinue, + // A merge block that is not reachable via control flow. + ReachDeadMerge +}; + +// Traverses the control-flow graph rooted at root in an order suited for +// readable code generation. Invokes callback at every node in the traversal +// order. The callback arguments are: +// - the block, +// - the reason we reached the block, +// - if the reason was that block is an unreachable continue or unreachable merge block +// then the last parameter is the corresponding header block. +void inReadableOrder(Block* root, std::function callback); + +// +// SPIR-V IR Function. +// + +class Function { +public: + Function(Id id, Id resultType, Id functionType, Id firstParam, Module& parent); + virtual ~Function() + { + for (int i = 0; i < (int)parameterInstructions.size(); ++i) + delete parameterInstructions[i]; + + for (int i = 0; i < (int)blocks.size(); ++i) + delete blocks[i]; + } + Id getId() const { return functionInstruction.getResultId(); } + Id getParamId(int p) const { return parameterInstructions[p]->getResultId(); } + Id getParamType(int p) const { return parameterInstructions[p]->getTypeId(); } + + void addBlock(Block* block) { blocks.push_back(block); } + void removeBlock(Block* block) + { + auto found = find(blocks.begin(), blocks.end(), block); + assert(found != blocks.end()); + blocks.erase(found); + delete block; + } + + Module& getParent() const { return parent; } + Block* getEntryBlock() const { return blocks.front(); } + Block* getLastBlock() const { return blocks.back(); } + const std::vector& getBlocks() const { return blocks; } + void addLocalVariable(std::unique_ptr inst); + Id getReturnType() const { return functionInstruction.getTypeId(); } + + void setImplicitThis() { implicitThis = true; } + bool hasImplicitThis() const { return implicitThis; } + + void dump(std::vector& out) const + { + // OpFunction + functionInstruction.dump(out); + + // OpFunctionParameter + for (int p = 0; p < (int)parameterInstructions.size(); ++p) + parameterInstructions[p]->dump(out); + + // Blocks + inReadableOrder(blocks[0], [&out](const Block* b, ReachReason, Block*) { b->dump(out); }); + Instruction end(0, 0, OpFunctionEnd); + end.dump(out); + } + +protected: + Function(const Function&); + Function& operator=(Function&); + + Module& parent; + Instruction functionInstruction; + std::vector parameterInstructions; + std::vector blocks; + bool implicitThis; // true if this is a member function expecting to be passed a 'this' as the first argument +}; + +// +// SPIR-V IR Module. +// + +class Module { +public: + Module() {} + virtual ~Module() + { + // TODO delete things + } + + void addFunction(Function *fun) { functions.push_back(fun); } + + void mapInstruction(Instruction *instruction) + { + spv::Id resultId = instruction->getResultId(); + // map the instruction's result id + if (resultId >= idToInstruction.size()) + idToInstruction.resize(resultId + 16); + idToInstruction[resultId] = instruction; + } + + Instruction* getInstruction(Id id) const { return idToInstruction[id]; } + const std::vector& getFunctions() const { return functions; } + spv::Id getTypeId(Id resultId) const { + return idToInstruction[resultId] == nullptr ? NoType : idToInstruction[resultId]->getTypeId(); + } + StorageClass getStorageClass(Id typeId) const + { + assert(idToInstruction[typeId]->getOpCode() == spv::OpTypePointer); + return (StorageClass)idToInstruction[typeId]->getImmediateOperand(0); + } + + void dump(std::vector& out) const + { + for (int f = 0; f < (int)functions.size(); ++f) + functions[f]->dump(out); + } + +protected: + Module(const Module&); + std::vector functions; + + // map from result id to instruction having that result id + std::vector idToInstruction; + + // map from a result id to its type id +}; + +// +// Implementation (it's here due to circular type definitions). +// + +// Add both +// - the OpFunction instruction +// - all the OpFunctionParameter instructions +__inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, Module& parent) + : parent(parent), functionInstruction(id, resultType, OpFunction), implicitThis(false) +{ + // OpFunction + functionInstruction.addImmediateOperand(FunctionControlMaskNone); + functionInstruction.addIdOperand(functionType); + parent.mapInstruction(&functionInstruction); + parent.addFunction(this); + + // OpFunctionParameter + Instruction* typeInst = parent.getInstruction(functionType); + int numParams = typeInst->getNumOperands() - 1; + for (int p = 0; p < numParams; ++p) { + Instruction* param = new Instruction(firstParamId + p, typeInst->getIdOperand(p + 1), OpFunctionParameter); + parent.mapInstruction(param); + parameterInstructions.push_back(param); + } +} + +__inline void Function::addLocalVariable(std::unique_ptr inst) +{ + Instruction* raw_instruction = inst.get(); + blocks[0]->addLocalVariable(std::move(inst)); + parent.mapInstruction(raw_instruction); +} + +__inline Block::Block(Id id, Function& parent) : parent(parent), unreachable(false) +{ + instructions.push_back(std::unique_ptr(new Instruction(id, NoType, OpLabel))); + instructions.back()->setBlock(this); + parent.getParent().mapInstruction(instructions.back().get()); +} + +__inline void Block::addInstruction(std::unique_ptr inst) +{ + Instruction* raw_instruction = inst.get(); + instructions.push_back(std::move(inst)); + raw_instruction->setBlock(this); + if (raw_instruction->getResultId()) + parent.getParent().mapInstruction(raw_instruction); +} + +} // end spv namespace + +#endif // spvIR_H diff --git a/android/armeabi-v7a/include/glslang/Include/BaseTypes.h b/android/armeabi-v7a/include/glslang/Include/BaseTypes.h new file mode 100644 index 00000000..816b1794 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/Include/BaseTypes.h @@ -0,0 +1,565 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 LunarG, Inc. +// Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _BASICTYPES_INCLUDED_ +#define _BASICTYPES_INCLUDED_ + +namespace glslang { + +// +// Basic type. Arrays, vectors, sampler details, etc., are orthogonal to this. +// +enum TBasicType { + EbtVoid, + EbtFloat, + EbtDouble, + EbtFloat16, + EbtInt8, + EbtUint8, + EbtInt16, + EbtUint16, + EbtInt, + EbtUint, + EbtInt64, + EbtUint64, + EbtBool, + EbtAtomicUint, + EbtSampler, + EbtStruct, + EbtBlock, + EbtAccStruct, + EbtReference, + EbtRayQuery, + + // HLSL types that live only temporarily. + EbtString, + + EbtNumTypes +}; + +// +// Storage qualifiers. Should align with different kinds of storage or +// resource or GLSL storage qualifier. Expansion is deprecated. +// +// N.B.: You probably DON'T want to add anything here, but rather just add it +// to the built-in variables. See the comment above TBuiltInVariable. +// +// A new built-in variable will normally be an existing qualifier, like 'in', 'out', etc. +// DO NOT follow the design pattern of, say EvqInstanceId, etc. +// +enum TStorageQualifier { + EvqTemporary, // For temporaries (within a function), read/write + EvqGlobal, // For globals read/write + EvqConst, // User-defined constant values, will be semantically constant and constant folded + EvqVaryingIn, // pipeline input, read only, also supercategory for all built-ins not included in this enum (see TBuiltInVariable) + EvqVaryingOut, // pipeline output, read/write, also supercategory for all built-ins not included in this enum (see TBuiltInVariable) + EvqUniform, // read only, shared with app + EvqBuffer, // read/write, shared with app + EvqShared, // compute shader's read/write 'shared' qualifier + + EvqPayload, + EvqPayloadIn, + EvqHitAttr, + EvqCallableData, + EvqCallableDataIn, + + // parameters + EvqIn, // also, for 'in' in the grammar before we know if it's a pipeline input or an 'in' parameter + EvqOut, // also, for 'out' in the grammar before we know if it's a pipeline output or an 'out' parameter + EvqInOut, + EvqConstReadOnly, // input; also other read-only types having neither a constant value nor constant-value semantics + + // built-ins read by vertex shader + EvqVertexId, + EvqInstanceId, + + // built-ins written by vertex shader + EvqPosition, + EvqPointSize, + EvqClipVertex, + + // built-ins read by fragment shader + EvqFace, + EvqFragCoord, + EvqPointCoord, + + // built-ins written by fragment shader + EvqFragColor, + EvqFragDepth, + + // end of list + EvqLast +}; + +// +// Subcategories of the TStorageQualifier, simply to give a direct mapping +// between built-in variable names and an numerical value (the enum). +// +// For backward compatibility, there is some redundancy between the +// TStorageQualifier and these. Existing members should both be maintained accurately. +// However, any new built-in variable (and any existing non-redundant one) +// must follow the pattern that the specific built-in is here, and only its +// general qualifier is in TStorageQualifier. +// +// Something like gl_Position, which is sometimes 'in' and sometimes 'out' +// shows up as two different built-in variables in a single stage, but +// only has a single enum in TBuiltInVariable, so both the +// TStorageQualifier and the TBuitinVariable are needed to distinguish +// between them. +// +enum TBuiltInVariable { + EbvNone, + EbvNumWorkGroups, + EbvWorkGroupSize, + EbvWorkGroupId, + EbvLocalInvocationId, + EbvGlobalInvocationId, + EbvLocalInvocationIndex, + EbvNumSubgroups, + EbvSubgroupID, + EbvSubGroupSize, + EbvSubGroupInvocation, + EbvSubGroupEqMask, + EbvSubGroupGeMask, + EbvSubGroupGtMask, + EbvSubGroupLeMask, + EbvSubGroupLtMask, + EbvSubgroupSize2, + EbvSubgroupInvocation2, + EbvSubgroupEqMask2, + EbvSubgroupGeMask2, + EbvSubgroupGtMask2, + EbvSubgroupLeMask2, + EbvSubgroupLtMask2, + EbvVertexId, + EbvInstanceId, + EbvVertexIndex, + EbvInstanceIndex, + EbvBaseVertex, + EbvBaseInstance, + EbvDrawId, + EbvPosition, + EbvPointSize, + EbvClipVertex, + EbvClipDistance, + EbvCullDistance, + EbvNormal, + EbvVertex, + EbvMultiTexCoord0, + EbvMultiTexCoord1, + EbvMultiTexCoord2, + EbvMultiTexCoord3, + EbvMultiTexCoord4, + EbvMultiTexCoord5, + EbvMultiTexCoord6, + EbvMultiTexCoord7, + EbvFrontColor, + EbvBackColor, + EbvFrontSecondaryColor, + EbvBackSecondaryColor, + EbvTexCoord, + EbvFogFragCoord, + EbvInvocationId, + EbvPrimitiveId, + EbvLayer, + EbvViewportIndex, + EbvPatchVertices, + EbvTessLevelOuter, + EbvTessLevelInner, + EbvBoundingBox, + EbvTessCoord, + EbvColor, + EbvSecondaryColor, + EbvFace, + EbvFragCoord, + EbvPointCoord, + EbvFragColor, + EbvFragData, + EbvFragDepth, + EbvFragStencilRef, + EbvSampleId, + EbvSamplePosition, + EbvSampleMask, + EbvHelperInvocation, + + EbvBaryCoordNoPersp, + EbvBaryCoordNoPerspCentroid, + EbvBaryCoordNoPerspSample, + EbvBaryCoordSmooth, + EbvBaryCoordSmoothCentroid, + EbvBaryCoordSmoothSample, + EbvBaryCoordPullModel, + + EbvViewIndex, + EbvDeviceIndex, + + EbvFragSizeEXT, + EbvFragInvocationCountEXT, + + EbvViewportMaskNV, + EbvSecondaryPositionNV, + EbvSecondaryViewportMaskNV, + EbvPositionPerViewNV, + EbvViewportMaskPerViewNV, + EbvFragFullyCoveredNV, + EbvFragmentSizeNV, + EbvInvocationsPerPixelNV, + // ray tracing + EbvLaunchId, + EbvLaunchSize, + EbvInstanceCustomIndex, + EbvGeometryIndex, + EbvWorldRayOrigin, + EbvWorldRayDirection, + EbvObjectRayOrigin, + EbvObjectRayDirection, + EbvRayTmin, + EbvRayTmax, + EbvHitT, + EbvHitKind, + EbvObjectToWorld, + EbvObjectToWorld3x4, + EbvWorldToObject, + EbvWorldToObject3x4, + EbvIncomingRayFlags, + // barycentrics + EbvBaryCoordNV, + EbvBaryCoordNoPerspNV, + // mesh shaders + EbvTaskCountNV, + EbvPrimitiveCountNV, + EbvPrimitiveIndicesNV, + EbvClipDistancePerViewNV, + EbvCullDistancePerViewNV, + EbvLayerPerViewNV, + EbvMeshViewCountNV, + EbvMeshViewIndicesNV, + + // sm builtins + EbvWarpsPerSM, + EbvSMCount, + EbvWarpID, + EbvSMID, + + // HLSL built-ins that live only temporarily, until they get remapped + // to one of the above. + EbvFragDepthGreater, + EbvFragDepthLesser, + EbvGsOutputStream, + EbvOutputPatch, + EbvInputPatch, + + // structbuffer types + EbvAppendConsume, // no need to differentiate append and consume + EbvRWStructuredBuffer, + EbvStructuredBuffer, + EbvByteAddressBuffer, + EbvRWByteAddressBuffer, + + EbvLast +}; + +// In this enum, order matters; users can assume higher precision is a bigger value +// and EpqNone is 0. +enum TPrecisionQualifier { + EpqNone = 0, + EpqLow, + EpqMedium, + EpqHigh +}; + +#ifdef GLSLANG_WEB +__inline const char* GetStorageQualifierString(TStorageQualifier q) { return ""; } +__inline const char* GetPrecisionQualifierString(TPrecisionQualifier p) { return ""; } +#else +// These will show up in error messages +__inline const char* GetStorageQualifierString(TStorageQualifier q) +{ + switch (q) { + case EvqTemporary: return "temp"; break; + case EvqGlobal: return "global"; break; + case EvqConst: return "const"; break; + case EvqConstReadOnly: return "const (read only)"; break; + case EvqVaryingIn: return "in"; break; + case EvqVaryingOut: return "out"; break; + case EvqUniform: return "uniform"; break; + case EvqBuffer: return "buffer"; break; + case EvqShared: return "shared"; break; + case EvqIn: return "in"; break; + case EvqOut: return "out"; break; + case EvqInOut: return "inout"; break; + case EvqVertexId: return "gl_VertexId"; break; + case EvqInstanceId: return "gl_InstanceId"; break; + case EvqPosition: return "gl_Position"; break; + case EvqPointSize: return "gl_PointSize"; break; + case EvqClipVertex: return "gl_ClipVertex"; break; + case EvqFace: return "gl_FrontFacing"; break; + case EvqFragCoord: return "gl_FragCoord"; break; + case EvqPointCoord: return "gl_PointCoord"; break; + case EvqFragColor: return "fragColor"; break; + case EvqFragDepth: return "gl_FragDepth"; break; + case EvqPayload: return "rayPayloadNV"; break; + case EvqPayloadIn: return "rayPayloadInNV"; break; + case EvqHitAttr: return "hitAttributeNV"; break; + case EvqCallableData: return "callableDataNV"; break; + case EvqCallableDataIn: return "callableDataInNV"; break; + default: return "unknown qualifier"; + } +} + +__inline const char* GetBuiltInVariableString(TBuiltInVariable v) +{ + switch (v) { + case EbvNone: return ""; + case EbvNumWorkGroups: return "NumWorkGroups"; + case EbvWorkGroupSize: return "WorkGroupSize"; + case EbvWorkGroupId: return "WorkGroupID"; + case EbvLocalInvocationId: return "LocalInvocationID"; + case EbvGlobalInvocationId: return "GlobalInvocationID"; + case EbvLocalInvocationIndex: return "LocalInvocationIndex"; + case EbvNumSubgroups: return "NumSubgroups"; + case EbvSubgroupID: return "SubgroupID"; + case EbvSubGroupSize: return "SubGroupSize"; + case EbvSubGroupInvocation: return "SubGroupInvocation"; + case EbvSubGroupEqMask: return "SubGroupEqMask"; + case EbvSubGroupGeMask: return "SubGroupGeMask"; + case EbvSubGroupGtMask: return "SubGroupGtMask"; + case EbvSubGroupLeMask: return "SubGroupLeMask"; + case EbvSubGroupLtMask: return "SubGroupLtMask"; + case EbvSubgroupSize2: return "SubgroupSize"; + case EbvSubgroupInvocation2: return "SubgroupInvocationID"; + case EbvSubgroupEqMask2: return "SubgroupEqMask"; + case EbvSubgroupGeMask2: return "SubgroupGeMask"; + case EbvSubgroupGtMask2: return "SubgroupGtMask"; + case EbvSubgroupLeMask2: return "SubgroupLeMask"; + case EbvSubgroupLtMask2: return "SubgroupLtMask"; + case EbvVertexId: return "VertexId"; + case EbvInstanceId: return "InstanceId"; + case EbvVertexIndex: return "VertexIndex"; + case EbvInstanceIndex: return "InstanceIndex"; + case EbvBaseVertex: return "BaseVertex"; + case EbvBaseInstance: return "BaseInstance"; + case EbvDrawId: return "DrawId"; + case EbvPosition: return "Position"; + case EbvPointSize: return "PointSize"; + case EbvClipVertex: return "ClipVertex"; + case EbvClipDistance: return "ClipDistance"; + case EbvCullDistance: return "CullDistance"; + case EbvNormal: return "Normal"; + case EbvVertex: return "Vertex"; + case EbvMultiTexCoord0: return "MultiTexCoord0"; + case EbvMultiTexCoord1: return "MultiTexCoord1"; + case EbvMultiTexCoord2: return "MultiTexCoord2"; + case EbvMultiTexCoord3: return "MultiTexCoord3"; + case EbvMultiTexCoord4: return "MultiTexCoord4"; + case EbvMultiTexCoord5: return "MultiTexCoord5"; + case EbvMultiTexCoord6: return "MultiTexCoord6"; + case EbvMultiTexCoord7: return "MultiTexCoord7"; + case EbvFrontColor: return "FrontColor"; + case EbvBackColor: return "BackColor"; + case EbvFrontSecondaryColor: return "FrontSecondaryColor"; + case EbvBackSecondaryColor: return "BackSecondaryColor"; + case EbvTexCoord: return "TexCoord"; + case EbvFogFragCoord: return "FogFragCoord"; + case EbvInvocationId: return "InvocationID"; + case EbvPrimitiveId: return "PrimitiveID"; + case EbvLayer: return "Layer"; + case EbvViewportIndex: return "ViewportIndex"; + case EbvPatchVertices: return "PatchVertices"; + case EbvTessLevelOuter: return "TessLevelOuter"; + case EbvTessLevelInner: return "TessLevelInner"; + case EbvBoundingBox: return "BoundingBox"; + case EbvTessCoord: return "TessCoord"; + case EbvColor: return "Color"; + case EbvSecondaryColor: return "SecondaryColor"; + case EbvFace: return "Face"; + case EbvFragCoord: return "FragCoord"; + case EbvPointCoord: return "PointCoord"; + case EbvFragColor: return "FragColor"; + case EbvFragData: return "FragData"; + case EbvFragDepth: return "FragDepth"; + case EbvFragStencilRef: return "FragStencilRef"; + case EbvSampleId: return "SampleId"; + case EbvSamplePosition: return "SamplePosition"; + case EbvSampleMask: return "SampleMaskIn"; + case EbvHelperInvocation: return "HelperInvocation"; + + case EbvBaryCoordNoPersp: return "BaryCoordNoPersp"; + case EbvBaryCoordNoPerspCentroid: return "BaryCoordNoPerspCentroid"; + case EbvBaryCoordNoPerspSample: return "BaryCoordNoPerspSample"; + case EbvBaryCoordSmooth: return "BaryCoordSmooth"; + case EbvBaryCoordSmoothCentroid: return "BaryCoordSmoothCentroid"; + case EbvBaryCoordSmoothSample: return "BaryCoordSmoothSample"; + case EbvBaryCoordPullModel: return "BaryCoordPullModel"; + + case EbvViewIndex: return "ViewIndex"; + case EbvDeviceIndex: return "DeviceIndex"; + + case EbvFragSizeEXT: return "FragSizeEXT"; + case EbvFragInvocationCountEXT: return "FragInvocationCountEXT"; + + case EbvViewportMaskNV: return "ViewportMaskNV"; + case EbvSecondaryPositionNV: return "SecondaryPositionNV"; + case EbvSecondaryViewportMaskNV: return "SecondaryViewportMaskNV"; + case EbvPositionPerViewNV: return "PositionPerViewNV"; + case EbvViewportMaskPerViewNV: return "ViewportMaskPerViewNV"; + case EbvFragFullyCoveredNV: return "FragFullyCoveredNV"; + case EbvFragmentSizeNV: return "FragmentSizeNV"; + case EbvInvocationsPerPixelNV: return "InvocationsPerPixelNV"; + case EbvLaunchId: return "LaunchIdNV"; + case EbvLaunchSize: return "LaunchSizeNV"; + case EbvInstanceCustomIndex: return "InstanceCustomIndexNV"; + case EbvGeometryIndex: return "GeometryIndexEXT"; + case EbvWorldRayOrigin: return "WorldRayOriginNV"; + case EbvWorldRayDirection: return "WorldRayDirectionNV"; + case EbvObjectRayOrigin: return "ObjectRayOriginNV"; + case EbvObjectRayDirection: return "ObjectRayDirectionNV"; + case EbvRayTmin: return "ObjectRayTminNV"; + case EbvRayTmax: return "ObjectRayTmaxNV"; + case EbvHitT: return "HitTNV"; + case EbvHitKind: return "HitKindNV"; + case EbvIncomingRayFlags: return "IncomingRayFlagsNV"; + case EbvObjectToWorld: return "ObjectToWorldNV"; + case EbvWorldToObject: return "WorldToObjectNV"; + + case EbvBaryCoordNV: return "BaryCoordNV"; + case EbvBaryCoordNoPerspNV: return "BaryCoordNoPerspNV"; + + case EbvTaskCountNV: return "TaskCountNV"; + case EbvPrimitiveCountNV: return "PrimitiveCountNV"; + case EbvPrimitiveIndicesNV: return "PrimitiveIndicesNV"; + case EbvClipDistancePerViewNV: return "ClipDistancePerViewNV"; + case EbvCullDistancePerViewNV: return "CullDistancePerViewNV"; + case EbvLayerPerViewNV: return "LayerPerViewNV"; + case EbvMeshViewCountNV: return "MeshViewCountNV"; + case EbvMeshViewIndicesNV: return "MeshViewIndicesNV"; + + case EbvWarpsPerSM: return "WarpsPerSMNV"; + case EbvSMCount: return "SMCountNV"; + case EbvWarpID: return "WarpIDNV"; + case EbvSMID: return "SMIDNV"; + + default: return "unknown built-in variable"; + } +} + +__inline const char* GetPrecisionQualifierString(TPrecisionQualifier p) +{ + switch (p) { + case EpqNone: return ""; break; + case EpqLow: return "lowp"; break; + case EpqMedium: return "mediump"; break; + case EpqHigh: return "highp"; break; + default: return "unknown precision qualifier"; + } +} +#endif + +__inline bool isTypeSignedInt(TBasicType type) +{ + switch (type) { + case EbtInt8: + case EbtInt16: + case EbtInt: + case EbtInt64: + return true; + default: + return false; + } +} + +__inline bool isTypeUnsignedInt(TBasicType type) +{ + switch (type) { + case EbtUint8: + case EbtUint16: + case EbtUint: + case EbtUint64: + return true; + default: + return false; + } +} + +__inline bool isTypeInt(TBasicType type) +{ + return isTypeSignedInt(type) || isTypeUnsignedInt(type); +} + +__inline bool isTypeFloat(TBasicType type) +{ + switch (type) { + case EbtFloat: + case EbtDouble: + case EbtFloat16: + return true; + default: + return false; + } +} + +__inline int getTypeRank(TBasicType type) +{ + int res = -1; + switch(type) { + case EbtInt8: + case EbtUint8: + res = 0; + break; + case EbtInt16: + case EbtUint16: + res = 1; + break; + case EbtInt: + case EbtUint: + res = 2; + break; + case EbtInt64: + case EbtUint64: + res = 3; + break; + default: + assert(false); + break; + } + return res; +} + +} // end namespace glslang + +#endif // _BASICTYPES_INCLUDED_ diff --git a/android/armeabi-v7a/include/glslang/Include/Common.h b/android/armeabi-v7a/include/glslang/Include/Common.h new file mode 100644 index 00000000..733a790c --- /dev/null +++ b/android/armeabi-v7a/include/glslang/Include/Common.h @@ -0,0 +1,292 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _COMMON_INCLUDED_ +#define _COMMON_INCLUDED_ + + +#if defined(__ANDROID__) || (defined(_MSC_VER) && _MSC_VER < 1700) +#include +namespace std { +template +std::string to_string(const T& val) { + std::ostringstream os; + os << val; + return os.str(); +} +} +#endif + +#if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/) || defined MINGW_HAS_SECURE_API + #include + #ifndef snprintf + #define snprintf sprintf_s + #endif + #define safe_vsprintf(buf,max,format,args) vsnprintf_s((buf), (max), (max), (format), (args)) +#elif defined (solaris) + #define safe_vsprintf(buf,max,format,args) vsnprintf((buf), (max), (format), (args)) + #include + #define UINT_PTR uintptr_t +#else + #define safe_vsprintf(buf,max,format,args) vsnprintf((buf), (max), (format), (args)) + #include + #define UINT_PTR uintptr_t +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1800 + #include + inline long long int strtoll (const char* str, char** endptr, int base) + { + return _strtoi64(str, endptr, base); + } + inline unsigned long long int strtoull (const char* str, char** endptr, int base) + { + return _strtoui64(str, endptr, base); + } + inline long long int atoll (const char* str) + { + return strtoll(str, NULL, 10); + } +#endif + +#if defined(_MSC_VER) +#define strdup _strdup +#endif + +/* windows only pragma */ +#ifdef _MSC_VER + #pragma warning(disable : 4786) // Don't warn about too long identifiers + #pragma warning(disable : 4514) // unused inline method + #pragma warning(disable : 4201) // nameless union +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "PoolAlloc.h" + +// +// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme. +// +#define POOL_ALLOCATOR_NEW_DELETE(A) \ + void* operator new(size_t s) { return (A).allocate(s); } \ + void* operator new(size_t, void *_Where) { return (_Where); } \ + void operator delete(void*) { } \ + void operator delete(void *, void *) { } \ + void* operator new[](size_t s) { return (A).allocate(s); } \ + void* operator new[](size_t, void *_Where) { return (_Where); } \ + void operator delete[](void*) { } \ + void operator delete[](void *, void *) { } + +namespace glslang { + + // + // Pool version of string. + // + typedef pool_allocator TStringAllocator; + typedef std::basic_string , TStringAllocator> TString; + +} // end namespace glslang + +// Repackage the std::hash for use by unordered map/set with a TString key. +namespace std { + + template<> struct hash { + std::size_t operator()(const glslang::TString& s) const + { + const unsigned _FNV_offset_basis = 2166136261U; + const unsigned _FNV_prime = 16777619U; + unsigned _Val = _FNV_offset_basis; + size_t _Count = s.size(); + const char* _First = s.c_str(); + for (size_t _Next = 0; _Next < _Count; ++_Next) + { + _Val ^= (unsigned)_First[_Next]; + _Val *= _FNV_prime; + } + + return _Val; + } + }; +} + +namespace glslang { + +inline TString* NewPoolTString(const char* s) +{ + void* memory = GetThreadPoolAllocator().allocate(sizeof(TString)); + return new(memory) TString(s); +} + +template inline T* NewPoolObject(T*) +{ + return new(GetThreadPoolAllocator().allocate(sizeof(T))) T; +} + +template inline T* NewPoolObject(T, int instances) +{ + return new(GetThreadPoolAllocator().allocate(instances * sizeof(T))) T[instances]; +} + +// +// Pool allocator versions of vectors, lists, and maps +// +template class TVector : public std::vector > { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + typedef typename std::vector >::size_type size_type; + TVector() : std::vector >() {} + TVector(const pool_allocator& a) : std::vector >(a) {} + TVector(size_type i) : std::vector >(i) {} + TVector(size_type i, const T& val) : std::vector >(i, val) {} +}; + +template class TList : public std::list > { +}; + +template > +class TMap : public std::map > > { +}; + +template , class PRED = std::equal_to > +class TUnorderedMap : public std::unordered_map > > { +}; + +// +// Persistent string memory. Should only be used for strings that survive +// across compiles/links. +// +typedef std::basic_string TPersistString; + +// +// templatized min and max functions. +// +template T Min(const T a, const T b) { return a < b ? a : b; } +template T Max(const T a, const T b) { return a > b ? a : b; } + +// +// Create a TString object from an integer. +// +#if defined _MSC_VER || defined MINGW_HAS_SECURE_API +inline const TString String(const int i, const int base = 10) +{ + char text[16]; // 32 bit ints are at most 10 digits in base 10 + _itoa_s(i, text, sizeof(text), base); + return text; +} +#else +inline const TString String(const int i, const int /*base*/ = 10) +{ + char text[16]; // 32 bit ints are at most 10 digits in base 10 + + // we assume base 10 for all cases + snprintf(text, sizeof(text), "%d", i); + + return text; +} +#endif + +struct TSourceLoc { + void init() + { + name = nullptr; string = 0; line = 0; column = 0; + } + void init(int stringNum) { init(); string = stringNum; } + // Returns the name if it exists. Otherwise, returns the string number. + std::string getStringNameOrNum(bool quoteStringName = true) const + { + if (name != nullptr) { + TString qstr = quoteStringName ? ("\"" + *name + "\"") : *name; + std::string ret_str(qstr.c_str()); + return ret_str; + } + return std::to_string((long long)string); + } + const char* getFilename() const + { + if (name == nullptr) + return nullptr; + return name->c_str(); + } + const char* getFilenameStr() const { return name == nullptr ? "" : name->c_str(); } + TString* name; // descriptive name for this string, when a textual name is available, otherwise nullptr + int string; + int line; + int column; +}; + +class TPragmaTable : public TMap { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) +}; + +const int MaxTokenLength = 1024; + +template bool IsPow2(T powerOf2) +{ + if (powerOf2 <= 0) + return false; + + return (powerOf2 & (powerOf2 - 1)) == 0; +} + +// Round number up to a multiple of the given powerOf2, which is not +// a power, just a number that must be a power of 2. +template void RoundToPow2(T& number, int powerOf2) +{ + assert(IsPow2(powerOf2)); + number = (number + powerOf2 - 1) & ~(powerOf2 - 1); +} + +template bool IsMultipleOfPow2(T number, int powerOf2) +{ + assert(IsPow2(powerOf2)); + return ! (number & (powerOf2 - 1)); +} + +} // end namespace glslang + +#endif // _COMMON_INCLUDED_ diff --git a/android/armeabi-v7a/include/glslang/Include/ConstantUnion.h b/android/armeabi-v7a/include/glslang/Include/ConstantUnion.h new file mode 100644 index 00000000..c4ffb857 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/Include/ConstantUnion.h @@ -0,0 +1,974 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013 LunarG, Inc. +// Copyright (C) 2017 ARM Limited. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _CONSTANT_UNION_INCLUDED_ +#define _CONSTANT_UNION_INCLUDED_ + +#include "../Include/Common.h" +#include "../Include/BaseTypes.h" + +namespace glslang { + +class TConstUnion { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + TConstUnion() : iConst(0), type(EbtInt) { } + + void setI8Const(signed char i) + { + i8Const = i; + type = EbtInt8; + } + + void setU8Const(unsigned char u) + { + u8Const = u; + type = EbtUint8; + } + + void setI16Const(signed short i) + { + i16Const = i; + type = EbtInt16; + } + + void setU16Const(unsigned short u) + { + u16Const = u; + type = EbtUint16; + } + + void setIConst(int i) + { + iConst = i; + type = EbtInt; + } + + void setUConst(unsigned int u) + { + uConst = u; + type = EbtUint; + } + + void setI64Const(long long i64) + { + i64Const = i64; + type = EbtInt64; + } + + void setU64Const(unsigned long long u64) + { + u64Const = u64; + type = EbtUint64; + } + + void setDConst(double d) + { + dConst = d; + type = EbtDouble; + } + + void setBConst(bool b) + { + bConst = b; + type = EbtBool; + } + + void setSConst(const TString* s) + { + sConst = s; + type = EbtString; + } + + signed char getI8Const() const { return i8Const; } + unsigned char getU8Const() const { return u8Const; } + signed short getI16Const() const { return i16Const; } + unsigned short getU16Const() const { return u16Const; } + int getIConst() const { return iConst; } + unsigned int getUConst() const { return uConst; } + long long getI64Const() const { return i64Const; } + unsigned long long getU64Const() const { return u64Const; } + double getDConst() const { return dConst; } + bool getBConst() const { return bConst; } + const TString* getSConst() const { return sConst; } + + bool operator==(const signed char i) const + { + if (i == i8Const) + return true; + + return false; + } + + bool operator==(const unsigned char u) const + { + if (u == u8Const) + return true; + + return false; + } + + bool operator==(const signed short i) const + { + if (i == i16Const) + return true; + + return false; + } + + bool operator==(const unsigned short u) const + { + if (u == u16Const) + return true; + + return false; + } + + bool operator==(const int i) const + { + if (i == iConst) + return true; + + return false; + } + + bool operator==(const unsigned int u) const + { + if (u == uConst) + return true; + + return false; + } + + bool operator==(const long long i64) const + { + if (i64 == i64Const) + return true; + + return false; + } + + bool operator==(const unsigned long long u64) const + { + if (u64 == u64Const) + return true; + + return false; + } + + bool operator==(const double d) const + { + if (d == dConst) + return true; + + return false; + } + + bool operator==(const bool b) const + { + if (b == bConst) + return true; + + return false; + } + + bool operator==(const TConstUnion& constant) const + { + if (constant.type != type) + return false; + + switch (type) { + case EbtInt: + if (constant.iConst == iConst) + return true; + + break; + case EbtUint: + if (constant.uConst == uConst) + return true; + + break; + case EbtBool: + if (constant.bConst == bConst) + return true; + + break; + case EbtDouble: + if (constant.dConst == dConst) + return true; + + break; + +#ifndef GLSLANG_WEB + case EbtInt16: + if (constant.i16Const == i16Const) + return true; + + break; + case EbtUint16: + if (constant.u16Const == u16Const) + return true; + + break; + case EbtInt8: + if (constant.i8Const == i8Const) + return true; + + break; + case EbtUint8: + if (constant.u8Const == u8Const) + return true; + + break; + case EbtInt64: + if (constant.i64Const == i64Const) + return true; + + break; + case EbtUint64: + if (constant.u64Const == u64Const) + return true; + + break; +#endif + default: + assert(false && "Default missing"); + } + + return false; + } + + bool operator!=(const signed char i) const + { + return !operator==(i); + } + + bool operator!=(const unsigned char u) const + { + return !operator==(u); + } + + bool operator!=(const signed short i) const + { + return !operator==(i); + } + + bool operator!=(const unsigned short u) const + { + return !operator==(u); + } + + bool operator!=(const int i) const + { + return !operator==(i); + } + + bool operator!=(const unsigned int u) const + { + return !operator==(u); + } + + bool operator!=(const long long i) const + { + return !operator==(i); + } + + bool operator!=(const unsigned long long u) const + { + return !operator==(u); + } + + bool operator!=(const float f) const + { + return !operator==(f); + } + + bool operator!=(const bool b) const + { + return !operator==(b); + } + + bool operator!=(const TConstUnion& constant) const + { + return !operator==(constant); + } + + bool operator>(const TConstUnion& constant) const + { + assert(type == constant.type); + switch (type) { + case EbtInt: + if (iConst > constant.iConst) + return true; + + return false; + case EbtUint: + if (uConst > constant.uConst) + return true; + + return false; + case EbtDouble: + if (dConst > constant.dConst) + return true; + + return false; +#ifndef GLSLANG_WEB + case EbtInt8: + if (i8Const > constant.i8Const) + return true; + + return false; + case EbtUint8: + if (u8Const > constant.u8Const) + return true; + + return false; + case EbtInt16: + if (i16Const > constant.i16Const) + return true; + + return false; + case EbtUint16: + if (u16Const > constant.u16Const) + return true; + + return false; + case EbtInt64: + if (i64Const > constant.i64Const) + return true; + + return false; + case EbtUint64: + if (u64Const > constant.u64Const) + return true; + + return false; +#endif + default: + assert(false && "Default missing"); + return false; + } + } + + bool operator<(const TConstUnion& constant) const + { + assert(type == constant.type); + switch (type) { +#ifndef GLSLANG_WEB + case EbtInt8: + if (i8Const < constant.i8Const) + return true; + + return false; + case EbtUint8: + if (u8Const < constant.u8Const) + return true; + + return false; + case EbtInt16: + if (i16Const < constant.i16Const) + return true; + + return false; + case EbtUint16: + if (u16Const < constant.u16Const) + return true; + return false; + case EbtInt64: + if (i64Const < constant.i64Const) + return true; + + return false; + case EbtUint64: + if (u64Const < constant.u64Const) + return true; + + return false; +#endif + case EbtDouble: + if (dConst < constant.dConst) + return true; + + return false; + case EbtInt: + if (iConst < constant.iConst) + return true; + + return false; + case EbtUint: + if (uConst < constant.uConst) + return true; + + return false; + default: + assert(false && "Default missing"); + return false; + } + } + + TConstUnion operator+(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst + constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst + constant.uConst); break; + case EbtDouble: returnValue.setDConst(dConst + constant.dConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const + constant.i8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const + constant.i16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const + constant.i64Const); break; + case EbtUint8: returnValue.setU8Const(u8Const + constant.u8Const); break; + case EbtUint16: returnValue.setU16Const(u16Const + constant.u16Const); break; + case EbtUint64: returnValue.setU64Const(u64Const + constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator-(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst - constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst - constant.uConst); break; + case EbtDouble: returnValue.setDConst(dConst - constant.dConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const - constant.i8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const - constant.i16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const - constant.i64Const); break; + case EbtUint8: returnValue.setU8Const(u8Const - constant.u8Const); break; + case EbtUint16: returnValue.setU16Const(u16Const - constant.u16Const); break; + case EbtUint64: returnValue.setU64Const(u64Const - constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator*(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst * constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst * constant.uConst); break; + case EbtDouble: returnValue.setDConst(dConst * constant.dConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const * constant.i8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const * constant.i16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const * constant.i64Const); break; + case EbtUint8: returnValue.setU8Const(u8Const * constant.u8Const); break; + case EbtUint16: returnValue.setU16Const(u16Const * constant.u16Const); break; + case EbtUint64: returnValue.setU64Const(u64Const * constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator%(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst % constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst % constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const % constant.i8Const); break; + case EbtInt16: returnValue.setI8Const(i8Const % constant.i16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const % constant.i64Const); break; + case EbtUint8: returnValue.setU8Const(u8Const % constant.u8Const); break; + case EbtUint16: returnValue.setU16Const(u16Const % constant.u16Const); break; + case EbtUint64: returnValue.setU64Const(u64Const % constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator>>(const TConstUnion& constant) const + { + TConstUnion returnValue; + switch (type) { +#ifndef GLSLANG_WEB + case EbtInt8: + switch (constant.type) { + case EbtInt8: returnValue.setI8Const(i8Const >> constant.i8Const); break; + case EbtUint8: returnValue.setI8Const(i8Const >> constant.u8Const); break; + case EbtInt16: returnValue.setI8Const(i8Const >> constant.i16Const); break; + case EbtUint16: returnValue.setI8Const(i8Const >> constant.u16Const); break; + case EbtInt: returnValue.setI8Const(i8Const >> constant.iConst); break; + case EbtUint: returnValue.setI8Const(i8Const >> constant.uConst); break; + case EbtInt64: returnValue.setI8Const(i8Const >> constant.i64Const); break; + case EbtUint64: returnValue.setI8Const(i8Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint8: + switch (constant.type) { + case EbtInt8: returnValue.setU8Const(u8Const >> constant.i8Const); break; + case EbtUint8: returnValue.setU8Const(u8Const >> constant.u8Const); break; + case EbtInt16: returnValue.setU8Const(u8Const >> constant.i16Const); break; + case EbtUint16: returnValue.setU8Const(u8Const >> constant.u16Const); break; + case EbtInt: returnValue.setU8Const(u8Const >> constant.iConst); break; + case EbtUint: returnValue.setU8Const(u8Const >> constant.uConst); break; + case EbtInt64: returnValue.setU8Const(u8Const >> constant.i64Const); break; + case EbtUint64: returnValue.setU8Const(u8Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtInt16: + switch (constant.type) { + case EbtInt8: returnValue.setI16Const(i16Const >> constant.i8Const); break; + case EbtUint8: returnValue.setI16Const(i16Const >> constant.u8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const >> constant.i16Const); break; + case EbtUint16: returnValue.setI16Const(i16Const >> constant.u16Const); break; + case EbtInt: returnValue.setI16Const(i16Const >> constant.iConst); break; + case EbtUint: returnValue.setI16Const(i16Const >> constant.uConst); break; + case EbtInt64: returnValue.setI16Const(i16Const >> constant.i64Const); break; + case EbtUint64: returnValue.setI16Const(i16Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint16: + switch (constant.type) { + case EbtInt8: returnValue.setU16Const(u16Const >> constant.i8Const); break; + case EbtUint8: returnValue.setU16Const(u16Const >> constant.u8Const); break; + case EbtInt16: returnValue.setU16Const(u16Const >> constant.i16Const); break; + case EbtUint16: returnValue.setU16Const(u16Const >> constant.u16Const); break; + case EbtInt: returnValue.setU16Const(u16Const >> constant.iConst); break; + case EbtUint: returnValue.setU16Const(u16Const >> constant.uConst); break; + case EbtInt64: returnValue.setU16Const(u16Const >> constant.i64Const); break; + case EbtUint64: returnValue.setU16Const(u16Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; +#endif + case EbtInt: + switch (constant.type) { + case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break; + case EbtUint: returnValue.setIConst(iConst >> constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setIConst(iConst >> constant.i8Const); break; + case EbtUint8: returnValue.setIConst(iConst >> constant.u8Const); break; + case EbtInt16: returnValue.setIConst(iConst >> constant.i16Const); break; + case EbtUint16: returnValue.setIConst(iConst >> constant.u16Const); break; + case EbtInt64: returnValue.setIConst(iConst >> constant.i64Const); break; + case EbtUint64: returnValue.setIConst(iConst >> constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + break; + case EbtUint: + switch (constant.type) { + case EbtInt: returnValue.setUConst(uConst >> constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst >> constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setUConst(uConst >> constant.i8Const); break; + case EbtUint8: returnValue.setUConst(uConst >> constant.u8Const); break; + case EbtInt16: returnValue.setUConst(uConst >> constant.i16Const); break; + case EbtUint16: returnValue.setUConst(uConst >> constant.u16Const); break; + case EbtInt64: returnValue.setUConst(uConst >> constant.i64Const); break; + case EbtUint64: returnValue.setUConst(uConst >> constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + break; +#ifndef GLSLANG_WEB + case EbtInt64: + switch (constant.type) { + case EbtInt8: returnValue.setI64Const(i64Const >> constant.i8Const); break; + case EbtUint8: returnValue.setI64Const(i64Const >> constant.u8Const); break; + case EbtInt16: returnValue.setI64Const(i64Const >> constant.i16Const); break; + case EbtUint16: returnValue.setI64Const(i64Const >> constant.u16Const); break; + case EbtInt: returnValue.setI64Const(i64Const >> constant.iConst); break; + case EbtUint: returnValue.setI64Const(i64Const >> constant.uConst); break; + case EbtInt64: returnValue.setI64Const(i64Const >> constant.i64Const); break; + case EbtUint64: returnValue.setI64Const(i64Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint64: + switch (constant.type) { + case EbtInt8: returnValue.setU64Const(u64Const >> constant.i8Const); break; + case EbtUint8: returnValue.setU64Const(u64Const >> constant.u8Const); break; + case EbtInt16: returnValue.setU64Const(u64Const >> constant.i16Const); break; + case EbtUint16: returnValue.setU64Const(u64Const >> constant.u16Const); break; + case EbtInt: returnValue.setU64Const(u64Const >> constant.iConst); break; + case EbtUint: returnValue.setU64Const(u64Const >> constant.uConst); break; + case EbtInt64: returnValue.setU64Const(u64Const >> constant.i64Const); break; + case EbtUint64: returnValue.setU64Const(u64Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator<<(const TConstUnion& constant) const + { + TConstUnion returnValue; + switch (type) { +#ifndef GLSLANG_WEB + case EbtInt8: + switch (constant.type) { + case EbtInt8: returnValue.setI8Const(i8Const << constant.i8Const); break; + case EbtUint8: returnValue.setI8Const(i8Const << constant.u8Const); break; + case EbtInt16: returnValue.setI8Const(i8Const << constant.i16Const); break; + case EbtUint16: returnValue.setI8Const(i8Const << constant.u16Const); break; + case EbtInt: returnValue.setI8Const(i8Const << constant.iConst); break; + case EbtUint: returnValue.setI8Const(i8Const << constant.uConst); break; + case EbtInt64: returnValue.setI8Const(i8Const << constant.i64Const); break; + case EbtUint64: returnValue.setI8Const(i8Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint8: + switch (constant.type) { + case EbtInt8: returnValue.setU8Const(u8Const << constant.i8Const); break; + case EbtUint8: returnValue.setU8Const(u8Const << constant.u8Const); break; + case EbtInt16: returnValue.setU8Const(u8Const << constant.i16Const); break; + case EbtUint16: returnValue.setU8Const(u8Const << constant.u16Const); break; + case EbtInt: returnValue.setU8Const(u8Const << constant.iConst); break; + case EbtUint: returnValue.setU8Const(u8Const << constant.uConst); break; + case EbtInt64: returnValue.setU8Const(u8Const << constant.i64Const); break; + case EbtUint64: returnValue.setU8Const(u8Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtInt16: + switch (constant.type) { + case EbtInt8: returnValue.setI16Const(i16Const << constant.i8Const); break; + case EbtUint8: returnValue.setI16Const(i16Const << constant.u8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const << constant.i16Const); break; + case EbtUint16: returnValue.setI16Const(i16Const << constant.u16Const); break; + case EbtInt: returnValue.setI16Const(i16Const << constant.iConst); break; + case EbtUint: returnValue.setI16Const(i16Const << constant.uConst); break; + case EbtInt64: returnValue.setI16Const(i16Const << constant.i64Const); break; + case EbtUint64: returnValue.setI16Const(i16Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint16: + switch (constant.type) { + case EbtInt8: returnValue.setU16Const(u16Const << constant.i8Const); break; + case EbtUint8: returnValue.setU16Const(u16Const << constant.u8Const); break; + case EbtInt16: returnValue.setU16Const(u16Const << constant.i16Const); break; + case EbtUint16: returnValue.setU16Const(u16Const << constant.u16Const); break; + case EbtInt: returnValue.setU16Const(u16Const << constant.iConst); break; + case EbtUint: returnValue.setU16Const(u16Const << constant.uConst); break; + case EbtInt64: returnValue.setU16Const(u16Const << constant.i64Const); break; + case EbtUint64: returnValue.setU16Const(u16Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtInt64: + switch (constant.type) { + case EbtInt8: returnValue.setI64Const(i64Const << constant.i8Const); break; + case EbtUint8: returnValue.setI64Const(i64Const << constant.u8Const); break; + case EbtInt16: returnValue.setI64Const(i64Const << constant.i16Const); break; + case EbtUint16: returnValue.setI64Const(i64Const << constant.u16Const); break; + case EbtInt: returnValue.setI64Const(i64Const << constant.iConst); break; + case EbtUint: returnValue.setI64Const(i64Const << constant.uConst); break; + case EbtInt64: returnValue.setI64Const(i64Const << constant.i64Const); break; + case EbtUint64: returnValue.setI64Const(i64Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint64: + switch (constant.type) { + case EbtInt8: returnValue.setU64Const(u64Const << constant.i8Const); break; + case EbtUint8: returnValue.setU64Const(u64Const << constant.u8Const); break; + case EbtInt16: returnValue.setU64Const(u64Const << constant.i16Const); break; + case EbtUint16: returnValue.setU64Const(u64Const << constant.u16Const); break; + case EbtInt: returnValue.setU64Const(u64Const << constant.iConst); break; + case EbtUint: returnValue.setU64Const(u64Const << constant.uConst); break; + case EbtInt64: returnValue.setU64Const(u64Const << constant.i64Const); break; + case EbtUint64: returnValue.setU64Const(u64Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; +#endif + case EbtInt: + switch (constant.type) { + case EbtInt: returnValue.setIConst(iConst << constant.iConst); break; + case EbtUint: returnValue.setIConst(iConst << constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setIConst(iConst << constant.i8Const); break; + case EbtUint8: returnValue.setIConst(iConst << constant.u8Const); break; + case EbtInt16: returnValue.setIConst(iConst << constant.i16Const); break; + case EbtUint16: returnValue.setIConst(iConst << constant.u16Const); break; + case EbtInt64: returnValue.setIConst(iConst << constant.i64Const); break; + case EbtUint64: returnValue.setIConst(iConst << constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + break; + case EbtUint: + switch (constant.type) { + case EbtInt: returnValue.setUConst(uConst << constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst << constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setUConst(uConst << constant.i8Const); break; + case EbtUint8: returnValue.setUConst(uConst << constant.u8Const); break; + case EbtInt16: returnValue.setUConst(uConst << constant.i16Const); break; + case EbtUint16: returnValue.setUConst(uConst << constant.u16Const); break; + case EbtInt64: returnValue.setUConst(uConst << constant.i64Const); break; + case EbtUint64: returnValue.setUConst(uConst << constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator&(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst & constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst & constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const & constant.i8Const); break; + case EbtUint8: returnValue.setU8Const(u8Const & constant.u8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const & constant.i16Const); break; + case EbtUint16: returnValue.setU16Const(u16Const & constant.u16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const & constant.i64Const); break; + case EbtUint64: returnValue.setU64Const(u64Const & constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator|(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst | constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst | constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const | constant.i8Const); break; + case EbtUint8: returnValue.setU8Const(u8Const | constant.u8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const | constant.i16Const); break; + case EbtUint16: returnValue.setU16Const(u16Const | constant.u16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const | constant.i64Const); break; + case EbtUint64: returnValue.setU64Const(u64Const | constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator^(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst ^ constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst ^ constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const ^ constant.i8Const); break; + case EbtUint8: returnValue.setU8Const(u8Const ^ constant.u8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const ^ constant.i16Const); break; + case EbtUint16: returnValue.setU16Const(u16Const ^ constant.u16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const ^ constant.i64Const); break; + case EbtUint64: returnValue.setU64Const(u64Const ^ constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator~() const + { + TConstUnion returnValue; + switch (type) { + case EbtInt: returnValue.setIConst(~iConst); break; + case EbtUint: returnValue.setUConst(~uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(~i8Const); break; + case EbtUint8: returnValue.setU8Const(~u8Const); break; + case EbtInt16: returnValue.setI16Const(~i16Const); break; + case EbtUint16: returnValue.setU16Const(~u16Const); break; + case EbtInt64: returnValue.setI64Const(~i64Const); break; + case EbtUint64: returnValue.setU64Const(~u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator&&(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtBool: returnValue.setBConst(bConst && constant.bConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator||(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtBool: returnValue.setBConst(bConst || constant.bConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TBasicType getType() const { return type; } + +private: + union { + signed char i8Const; // used for i8vec, scalar int8s + unsigned char u8Const; // used for u8vec, scalar uint8s + signed short i16Const; // used for i16vec, scalar int16s + unsigned short u16Const; // used for u16vec, scalar uint16s + int iConst; // used for ivec, scalar ints + unsigned int uConst; // used for uvec, scalar uints + long long i64Const; // used for i64vec, scalar int64s + unsigned long long u64Const; // used for u64vec, scalar uint64s + bool bConst; // used for bvec, scalar bools + double dConst; // used for vec, dvec, mat, dmat, scalar floats and doubles + const TString* sConst; // string constant + }; + + TBasicType type; +}; + +// Encapsulate having a pointer to an array of TConstUnion, +// which only needs to be allocated if its size is going to be +// bigger than 0. +// +// One convenience is being able to use [] to go inside the array, instead +// of C++ assuming it as an array of pointers to vectors. +// +// General usage is that the size is known up front, and it is +// created once with the proper size. +// +class TConstUnionArray { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + TConstUnionArray() : unionArray(nullptr) { } + virtual ~TConstUnionArray() { } + + explicit TConstUnionArray(int size) + { + if (size == 0) + unionArray = nullptr; + else + unionArray = new TConstUnionVector(size); + } + TConstUnionArray(const TConstUnionArray& a) = default; + TConstUnionArray(const TConstUnionArray& a, int start, int size) + { + unionArray = new TConstUnionVector(size); + for (int i = 0; i < size; ++i) + (*unionArray)[i] = a[start + i]; + } + + // Use this constructor for a smear operation + TConstUnionArray(int size, const TConstUnion& val) + { + unionArray = new TConstUnionVector(size, val); + } + + int size() const { return unionArray ? (int)unionArray->size() : 0; } + TConstUnion& operator[](size_t index) { return (*unionArray)[index]; } + const TConstUnion& operator[](size_t index) const { return (*unionArray)[index]; } + bool operator==(const TConstUnionArray& rhs) const + { + // this includes the case that both are unallocated + if (unionArray == rhs.unionArray) + return true; + + if (! unionArray || ! rhs.unionArray) + return false; + + return *unionArray == *rhs.unionArray; + } + bool operator!=(const TConstUnionArray& rhs) const { return ! operator==(rhs); } + + double dot(const TConstUnionArray& rhs) + { + assert(rhs.unionArray->size() == unionArray->size()); + double sum = 0.0; + + for (size_t comp = 0; comp < unionArray->size(); ++comp) + sum += (*this)[comp].getDConst() * rhs[comp].getDConst(); + + return sum; + } + + bool empty() const { return unionArray == nullptr; } + +protected: + typedef TVector TConstUnionVector; + TConstUnionVector* unionArray; +}; + +} // end namespace glslang + +#endif // _CONSTANT_UNION_INCLUDED_ diff --git a/android/armeabi-v7a/include/glslang/Include/InfoSink.h b/android/armeabi-v7a/include/glslang/Include/InfoSink.h new file mode 100644 index 00000000..dceb603c --- /dev/null +++ b/android/armeabi-v7a/include/glslang/Include/InfoSink.h @@ -0,0 +1,144 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _INFOSINK_INCLUDED_ +#define _INFOSINK_INCLUDED_ + +#include "../Include/Common.h" +#include + +namespace glslang { + +// +// TPrefixType is used to centralize how info log messages start. +// See below. +// +enum TPrefixType { + EPrefixNone, + EPrefixWarning, + EPrefixError, + EPrefixInternalError, + EPrefixUnimplemented, + EPrefixNote +}; + +enum TOutputStream { + ENull = 0, + EDebugger = 0x01, + EStdOut = 0x02, + EString = 0x04, +}; +// +// Encapsulate info logs for all objects that have them. +// +// The methods are a general set of tools for getting a variety of +// messages and types inserted into the log. +// +class TInfoSinkBase { +public: + TInfoSinkBase() : outputStream(4) {} + void erase() { sink.erase(); } + TInfoSinkBase& operator<<(const TPersistString& t) { append(t); return *this; } + TInfoSinkBase& operator<<(char c) { append(1, c); return *this; } + TInfoSinkBase& operator<<(const char* s) { append(s); return *this; } + TInfoSinkBase& operator<<(int n) { append(String(n)); return *this; } + TInfoSinkBase& operator<<(unsigned int n) { append(String(n)); return *this; } + TInfoSinkBase& operator<<(float n) { const int size = 40; char buf[size]; + snprintf(buf, size, (fabs(n) > 1e-8 && fabs(n) < 1e8) || n == 0.0f ? "%f" : "%g", n); + append(buf); + return *this; } + TInfoSinkBase& operator+(const TPersistString& t) { append(t); return *this; } + TInfoSinkBase& operator+(const TString& t) { append(t); return *this; } + TInfoSinkBase& operator<<(const TString& t) { append(t); return *this; } + TInfoSinkBase& operator+(const char* s) { append(s); return *this; } + const char* c_str() const { return sink.c_str(); } + void prefix(TPrefixType message) { + switch(message) { + case EPrefixNone: break; + case EPrefixWarning: append("WARNING: "); break; + case EPrefixError: append("ERROR: "); break; + case EPrefixInternalError: append("INTERNAL ERROR: "); break; + case EPrefixUnimplemented: append("UNIMPLEMENTED: "); break; + case EPrefixNote: append("NOTE: "); break; + default: append("UNKNOWN ERROR: "); break; + } + } + void location(const TSourceLoc& loc) { + const int maxSize = 24; + char locText[maxSize]; + snprintf(locText, maxSize, ":%d", loc.line); + append(loc.getStringNameOrNum(false).c_str()); + append(locText); + append(": "); + } + void message(TPrefixType message, const char* s) { + prefix(message); + append(s); + append("\n"); + } + void message(TPrefixType message, const char* s, const TSourceLoc& loc) { + prefix(message); + location(loc); + append(s); + append("\n"); + } + + void setOutputStream(int output = 4) + { + outputStream = output; + } + +protected: + void append(const char* s); + + void append(int count, char c); + void append(const TPersistString& t); + void append(const TString& t); + + void checkMem(size_t growth) { if (sink.capacity() < sink.size() + growth + 2) + sink.reserve(sink.capacity() + sink.capacity() / 2); } + void appendToStream(const char* s); + TPersistString sink; + int outputStream; +}; + +} // end namespace glslang + +class TInfoSink { +public: + glslang::TInfoSinkBase info; + glslang::TInfoSinkBase debug; +}; + +#endif // _INFOSINK_INCLUDED_ diff --git a/android/armeabi-v7a/include/glslang/Include/InitializeGlobals.h b/android/armeabi-v7a/include/glslang/Include/InitializeGlobals.h new file mode 100644 index 00000000..95d0a40e --- /dev/null +++ b/android/armeabi-v7a/include/glslang/Include/InitializeGlobals.h @@ -0,0 +1,44 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef __INITIALIZE_GLOBALS_INCLUDED_ +#define __INITIALIZE_GLOBALS_INCLUDED_ + +namespace glslang { + +bool InitializePoolIndex(); + +} // end namespace glslang + +#endif // __INITIALIZE_GLOBALS_INCLUDED_ diff --git a/android/armeabi-v7a/include/glslang/Include/PoolAlloc.h b/android/armeabi-v7a/include/glslang/Include/PoolAlloc.h new file mode 100644 index 00000000..b8eccb88 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/Include/PoolAlloc.h @@ -0,0 +1,316 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _POOLALLOC_INCLUDED_ +#define _POOLALLOC_INCLUDED_ + +#ifdef _DEBUG +# define GUARD_BLOCKS // define to enable guard block sanity checking +#endif + +// +// This header defines an allocator that can be used to efficiently +// allocate a large number of small requests for heap memory, with the +// intention that they are not individually deallocated, but rather +// collectively deallocated at one time. +// +// This simultaneously +// +// * Makes each individual allocation much more efficient; the +// typical allocation is trivial. +// * Completely avoids the cost of doing individual deallocation. +// * Saves the trouble of tracking down and plugging a large class of leaks. +// +// Individual classes can use this allocator by supplying their own +// new and delete methods. +// +// STL containers can use this allocator by using the pool_allocator +// class as the allocator (second) template argument. +// + +#include +#include +#include + +namespace glslang { + +// If we are using guard blocks, we must track each individual +// allocation. If we aren't using guard blocks, these +// never get instantiated, so won't have any impact. +// + +class TAllocation { +public: + TAllocation(size_t size, unsigned char* mem, TAllocation* prev = 0) : + size(size), mem(mem), prevAlloc(prev) { + // Allocations are bracketed: + // [allocationHeader][initialGuardBlock][userData][finalGuardBlock] + // This would be cleaner with if (guardBlockSize)..., but that + // makes the compiler print warnings about 0 length memsets, + // even with the if() protecting them. +# ifdef GUARD_BLOCKS + memset(preGuard(), guardBlockBeginVal, guardBlockSize); + memset(data(), userDataFill, size); + memset(postGuard(), guardBlockEndVal, guardBlockSize); +# endif + } + + void check() const { + checkGuardBlock(preGuard(), guardBlockBeginVal, "before"); + checkGuardBlock(postGuard(), guardBlockEndVal, "after"); + } + + void checkAllocList() const; + + // Return total size needed to accommodate user buffer of 'size', + // plus our tracking data. + inline static size_t allocationSize(size_t size) { + return size + 2 * guardBlockSize + headerSize(); + } + + // Offset from surrounding buffer to get to user data buffer. + inline static unsigned char* offsetAllocation(unsigned char* m) { + return m + guardBlockSize + headerSize(); + } + +private: + void checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const; + + // Find offsets to pre and post guard blocks, and user data buffer + unsigned char* preGuard() const { return mem + headerSize(); } + unsigned char* data() const { return preGuard() + guardBlockSize; } + unsigned char* postGuard() const { return data() + size; } + + size_t size; // size of the user data area + unsigned char* mem; // beginning of our allocation (pts to header) + TAllocation* prevAlloc; // prior allocation in the chain + + const static unsigned char guardBlockBeginVal; + const static unsigned char guardBlockEndVal; + const static unsigned char userDataFill; + + const static size_t guardBlockSize; +# ifdef GUARD_BLOCKS + inline static size_t headerSize() { return sizeof(TAllocation); } +# else + inline static size_t headerSize() { return 0; } +# endif +}; + +// +// There are several stacks. One is to track the pushing and popping +// of the user, and not yet implemented. The others are simply a +// repositories of free pages or used pages. +// +// Page stacks are linked together with a simple header at the beginning +// of each allocation obtained from the underlying OS. Multi-page allocations +// are returned to the OS. Individual page allocations are kept for future +// re-use. +// +// The "page size" used is not, nor must it match, the underlying OS +// page size. But, having it be about that size or equal to a set of +// pages is likely most optimal. +// +class TPoolAllocator { +public: + TPoolAllocator(int growthIncrement = 8*1024, int allocationAlignment = 16); + + // + // Don't call the destructor just to free up the memory, call pop() + // + ~TPoolAllocator(); + + // + // Call push() to establish a new place to pop memory too. Does not + // have to be called to get things started. + // + void push(); + + // + // Call pop() to free all memory allocated since the last call to push(), + // or if no last call to push, frees all memory since first allocation. + // + void pop(); + + // + // Call popAll() to free all memory allocated. + // + void popAll(); + + // + // Call allocate() to actually acquire memory. Returns 0 if no memory + // available, otherwise a properly aligned pointer to 'numBytes' of memory. + // + void* allocate(size_t numBytes); + + // + // There is no deallocate. The point of this class is that + // deallocation can be skipped by the user of it, as the model + // of use is to simultaneously deallocate everything at once + // by calling pop(), and to not have to solve memory leak problems. + // + +protected: + friend struct tHeader; + + struct tHeader { + tHeader(tHeader* nextPage, size_t pageCount) : +#ifdef GUARD_BLOCKS + lastAllocation(0), +#endif + nextPage(nextPage), pageCount(pageCount) { } + + ~tHeader() { +#ifdef GUARD_BLOCKS + if (lastAllocation) + lastAllocation->checkAllocList(); +#endif + } + +#ifdef GUARD_BLOCKS + TAllocation* lastAllocation; +#endif + tHeader* nextPage; + size_t pageCount; + }; + + struct tAllocState { + size_t offset; + tHeader* page; + }; + typedef std::vector tAllocStack; + + // Track allocations if and only if we're using guard blocks +#ifndef GUARD_BLOCKS + void* initializeAllocation(tHeader*, unsigned char* memory, size_t) { +#else + void* initializeAllocation(tHeader* block, unsigned char* memory, size_t numBytes) { + new(memory) TAllocation(numBytes, memory, block->lastAllocation); + block->lastAllocation = reinterpret_cast(memory); +#endif + + // This is optimized entirely away if GUARD_BLOCKS is not defined. + return TAllocation::offsetAllocation(memory); + } + + size_t pageSize; // granularity of allocation from the OS + size_t alignment; // all returned allocations will be aligned at + // this granularity, which will be a power of 2 + size_t alignmentMask; + size_t headerSkip; // amount of memory to skip to make room for the + // header (basically, size of header, rounded + // up to make it aligned + size_t currentPageOffset; // next offset in top of inUseList to allocate from + tHeader* freeList; // list of popped memory + tHeader* inUseList; // list of all memory currently being used + tAllocStack stack; // stack of where to allocate from, to partition pool + + int numCalls; // just an interesting statistic + size_t totalBytes; // just an interesting statistic +private: + TPoolAllocator& operator=(const TPoolAllocator&); // don't allow assignment operator + TPoolAllocator(const TPoolAllocator&); // don't allow default copy constructor +}; + +// +// There could potentially be many pools with pops happening at +// different times. But a simple use is to have a global pop +// with everyone using the same global allocator. +// +extern TPoolAllocator& GetThreadPoolAllocator(); +void SetThreadPoolAllocator(TPoolAllocator* poolAllocator); + +// +// This STL compatible allocator is intended to be used as the allocator +// parameter to templatized STL containers, like vector and map. +// +// It will use the pools for allocation, and not +// do any deallocation, but will still do destruction. +// +template +class pool_allocator { +public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T *pointer; + typedef const T *const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T value_type; + template + struct rebind { + typedef pool_allocator other; + }; + pointer address(reference x) const { return &x; } + const_pointer address(const_reference x) const { return &x; } + + pool_allocator() : allocator(GetThreadPoolAllocator()) { } + pool_allocator(TPoolAllocator& a) : allocator(a) { } + pool_allocator(const pool_allocator& p) : allocator(p.allocator) { } + + template + pool_allocator(const pool_allocator& p) : allocator(p.getAllocator()) { } + + pointer allocate(size_type n) { + return reinterpret_cast(getAllocator().allocate(n * sizeof(T))); } + pointer allocate(size_type n, const void*) { + return reinterpret_cast(getAllocator().allocate(n * sizeof(T))); } + + void deallocate(void*, size_type) { } + void deallocate(pointer, size_type) { } + + pointer _Charalloc(size_t n) { + return reinterpret_cast(getAllocator().allocate(n)); } + + void construct(pointer p, const T& val) { new ((void *)p) T(val); } + void destroy(pointer p) { p->T::~T(); } + + bool operator==(const pool_allocator& rhs) const { return &getAllocator() == &rhs.getAllocator(); } + bool operator!=(const pool_allocator& rhs) const { return &getAllocator() != &rhs.getAllocator(); } + + size_type max_size() const { return static_cast(-1) / sizeof(T); } + size_type max_size(int size) const { return static_cast(-1) / size; } + + TPoolAllocator& getAllocator() const { return allocator; } + +protected: + pool_allocator& operator=(const pool_allocator&) { return *this; } + TPoolAllocator& allocator; +}; + +} // end namespace glslang + +#endif // _POOLALLOC_INCLUDED_ diff --git a/android/armeabi-v7a/include/glslang/Include/ResourceLimits.h b/android/armeabi-v7a/include/glslang/Include/ResourceLimits.h new file mode 100644 index 00000000..106b21d9 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/Include/ResourceLimits.h @@ -0,0 +1,149 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _RESOURCE_LIMITS_INCLUDED_ +#define _RESOURCE_LIMITS_INCLUDED_ + +struct TLimits { + bool nonInductiveForLoops; + bool whileLoops; + bool doWhileLoops; + bool generalUniformIndexing; + bool generalAttributeMatrixVectorIndexing; + bool generalVaryingIndexing; + bool generalSamplerIndexing; + bool generalVariableIndexing; + bool generalConstantMatrixVectorIndexing; +}; + +struct TBuiltInResource { + int maxLights; + int maxClipPlanes; + int maxTextureUnits; + int maxTextureCoords; + int maxVertexAttribs; + int maxVertexUniformComponents; + int maxVaryingFloats; + int maxVertexTextureImageUnits; + int maxCombinedTextureImageUnits; + int maxTextureImageUnits; + int maxFragmentUniformComponents; + int maxDrawBuffers; + int maxVertexUniformVectors; + int maxVaryingVectors; + int maxFragmentUniformVectors; + int maxVertexOutputVectors; + int maxFragmentInputVectors; + int minProgramTexelOffset; + int maxProgramTexelOffset; + int maxClipDistances; + int maxComputeWorkGroupCountX; + int maxComputeWorkGroupCountY; + int maxComputeWorkGroupCountZ; + int maxComputeWorkGroupSizeX; + int maxComputeWorkGroupSizeY; + int maxComputeWorkGroupSizeZ; + int maxComputeUniformComponents; + int maxComputeTextureImageUnits; + int maxComputeImageUniforms; + int maxComputeAtomicCounters; + int maxComputeAtomicCounterBuffers; + int maxVaryingComponents; + int maxVertexOutputComponents; + int maxGeometryInputComponents; + int maxGeometryOutputComponents; + int maxFragmentInputComponents; + int maxImageUnits; + int maxCombinedImageUnitsAndFragmentOutputs; + int maxCombinedShaderOutputResources; + int maxImageSamples; + int maxVertexImageUniforms; + int maxTessControlImageUniforms; + int maxTessEvaluationImageUniforms; + int maxGeometryImageUniforms; + int maxFragmentImageUniforms; + int maxCombinedImageUniforms; + int maxGeometryTextureImageUnits; + int maxGeometryOutputVertices; + int maxGeometryTotalOutputComponents; + int maxGeometryUniformComponents; + int maxGeometryVaryingComponents; + int maxTessControlInputComponents; + int maxTessControlOutputComponents; + int maxTessControlTextureImageUnits; + int maxTessControlUniformComponents; + int maxTessControlTotalOutputComponents; + int maxTessEvaluationInputComponents; + int maxTessEvaluationOutputComponents; + int maxTessEvaluationTextureImageUnits; + int maxTessEvaluationUniformComponents; + int maxTessPatchComponents; + int maxPatchVertices; + int maxTessGenLevel; + int maxViewports; + int maxVertexAtomicCounters; + int maxTessControlAtomicCounters; + int maxTessEvaluationAtomicCounters; + int maxGeometryAtomicCounters; + int maxFragmentAtomicCounters; + int maxCombinedAtomicCounters; + int maxAtomicCounterBindings; + int maxVertexAtomicCounterBuffers; + int maxTessControlAtomicCounterBuffers; + int maxTessEvaluationAtomicCounterBuffers; + int maxGeometryAtomicCounterBuffers; + int maxFragmentAtomicCounterBuffers; + int maxCombinedAtomicCounterBuffers; + int maxAtomicCounterBufferSize; + int maxTransformFeedbackBuffers; + int maxTransformFeedbackInterleavedComponents; + int maxCullDistances; + int maxCombinedClipAndCullDistances; + int maxSamples; + int maxMeshOutputVerticesNV; + int maxMeshOutputPrimitivesNV; + int maxMeshWorkGroupSizeX_NV; + int maxMeshWorkGroupSizeY_NV; + int maxMeshWorkGroupSizeZ_NV; + int maxTaskWorkGroupSizeX_NV; + int maxTaskWorkGroupSizeY_NV; + int maxTaskWorkGroupSizeZ_NV; + int maxMeshViewCountNV; + + TLimits limits; +}; + +#endif // _RESOURCE_LIMITS_INCLUDED_ diff --git a/android/armeabi-v7a/include/glslang/Include/ShHandle.h b/android/armeabi-v7a/include/glslang/Include/ShHandle.h new file mode 100644 index 00000000..df07bd8e --- /dev/null +++ b/android/armeabi-v7a/include/glslang/Include/ShHandle.h @@ -0,0 +1,176 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _SHHANDLE_INCLUDED_ +#define _SHHANDLE_INCLUDED_ + +// +// Machine independent part of the compiler private objects +// sent as ShHandle to the driver. +// +// This should not be included by driver code. +// + +#define SH_EXPORTING +#include "../Public/ShaderLang.h" +#include "../MachineIndependent/Versions.h" +#include "InfoSink.h" + +class TCompiler; +class TLinker; +class TUniformMap; + +// +// The base class used to back handles returned to the driver. +// +class TShHandleBase { +public: + TShHandleBase() { pool = new glslang::TPoolAllocator; } + virtual ~TShHandleBase() { delete pool; } + virtual TCompiler* getAsCompiler() { return 0; } + virtual TLinker* getAsLinker() { return 0; } + virtual TUniformMap* getAsUniformMap() { return 0; } + virtual glslang::TPoolAllocator* getPool() const { return pool; } +private: + glslang::TPoolAllocator* pool; +}; + +// +// The base class for the machine dependent linker to derive from +// for managing where uniforms live. +// +class TUniformMap : public TShHandleBase { +public: + TUniformMap() { } + virtual ~TUniformMap() { } + virtual TUniformMap* getAsUniformMap() { return this; } + virtual int getLocation(const char* name) = 0; + virtual TInfoSink& getInfoSink() { return infoSink; } + TInfoSink infoSink; +}; + +class TIntermNode; + +// +// The base class for the machine dependent compiler to derive from +// for managing object code from the compile. +// +class TCompiler : public TShHandleBase { +public: + TCompiler(EShLanguage l, TInfoSink& sink) : infoSink(sink) , language(l), haveValidObjectCode(false) { } + virtual ~TCompiler() { } + EShLanguage getLanguage() { return language; } + virtual TInfoSink& getInfoSink() { return infoSink; } + + virtual bool compile(TIntermNode* root, int version = 0, EProfile profile = ENoProfile) = 0; + + virtual TCompiler* getAsCompiler() { return this; } + virtual bool linkable() { return haveValidObjectCode; } + + TInfoSink& infoSink; +protected: + TCompiler& operator=(TCompiler&); + + EShLanguage language; + bool haveValidObjectCode; +}; + +// +// Link operations are based on a list of compile results... +// +typedef glslang::TVector TCompilerList; +typedef glslang::TVector THandleList; + +// +// The base class for the machine dependent linker to derive from +// to manage the resulting executable. +// + +class TLinker : public TShHandleBase { +public: + TLinker(EShExecutable e, TInfoSink& iSink) : + infoSink(iSink), + executable(e), + haveReturnableObjectCode(false), + appAttributeBindings(0), + fixedAttributeBindings(0), + excludedAttributes(0), + excludedCount(0), + uniformBindings(0) { } + virtual TLinker* getAsLinker() { return this; } + virtual ~TLinker() { } + virtual bool link(TCompilerList&, TUniformMap*) = 0; + virtual bool link(THandleList&) { return false; } + virtual void setAppAttributeBindings(const ShBindingTable* t) { appAttributeBindings = t; } + virtual void setFixedAttributeBindings(const ShBindingTable* t) { fixedAttributeBindings = t; } + virtual void getAttributeBindings(ShBindingTable const **t) const = 0; + virtual void setExcludedAttributes(const int* attributes, int count) { excludedAttributes = attributes; excludedCount = count; } + virtual ShBindingTable* getUniformBindings() const { return uniformBindings; } + virtual const void* getObjectCode() const { return 0; } // a real compiler would be returning object code here + virtual TInfoSink& getInfoSink() { return infoSink; } + TInfoSink& infoSink; +protected: + TLinker& operator=(TLinker&); + EShExecutable executable; + bool haveReturnableObjectCode; // true when objectCode is acceptable to send to driver + + const ShBindingTable* appAttributeBindings; + const ShBindingTable* fixedAttributeBindings; + const int* excludedAttributes; + int excludedCount; + ShBindingTable* uniformBindings; // created by the linker +}; + +// +// This is the interface between the machine independent code +// and the machine dependent code. +// +// The machine dependent code should derive from the classes +// above. Then Construct*() and Delete*() will create and +// destroy the machine dependent objects, which contain the +// above machine independent information. +// +TCompiler* ConstructCompiler(EShLanguage, int); + +TShHandleBase* ConstructLinker(EShExecutable, int); +TShHandleBase* ConstructBindings(); +void DeleteLinker(TShHandleBase*); +void DeleteBindingList(TShHandleBase* bindingList); + +TUniformMap* ConstructUniformMap(); +void DeleteCompiler(TCompiler*); + +void DeleteUniformMap(TUniformMap*); + +#endif // _SHHANDLE_INCLUDED_ diff --git a/android/armeabi-v7a/include/glslang/Include/Types.h b/android/armeabi-v7a/include/glslang/Include/Types.h new file mode 100644 index 00000000..b2c416d1 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/Include/Types.h @@ -0,0 +1,2483 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2016 LunarG, Inc. +// Copyright (C) 2015-2016 Google, Inc. +// Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _TYPES_INCLUDED +#define _TYPES_INCLUDED + +#include "../Include/Common.h" +#include "../Include/BaseTypes.h" +#include "../Public/ShaderLang.h" +#include "arrays.h" + +#include + +namespace glslang { + +const int GlslangMaxTypeLength = 200; // TODO: need to print block/struct one member per line, so this can stay bounded + +const char* const AnonymousPrefix = "anon@"; // for something like a block whose members can be directly accessed +inline bool IsAnonymous(const TString& name) +{ + return name.compare(0, 5, AnonymousPrefix) == 0; +} + +// +// Details within a sampler type +// +enum TSamplerDim { + EsdNone, + Esd1D, + Esd2D, + Esd3D, + EsdCube, + EsdRect, + EsdBuffer, + EsdSubpass, // goes only with non-sampled image (image is true) + EsdNumDims +}; + +struct TSampler { // misnomer now; includes images, textures without sampler, and textures with sampler + TBasicType type : 8; // type returned by sampler + TSamplerDim dim : 8; + bool arrayed : 1; + bool shadow : 1; + bool ms : 1; + bool image : 1; // image, combined should be false + bool combined : 1; // true means texture is combined with a sampler, false means texture with no sampler + bool sampler : 1; // true means a pure sampler, other fields should be clear() + +#ifdef GLSLANG_WEB + bool is1D() const { return false; } + bool isBuffer() const { return false; } + bool isRect() const { return false; } + bool isSubpass() const { return false; } + bool isCombined() const { return true; } + bool isImage() const { return false; } + bool isImageClass() const { return false; } + bool isMultiSample() const { return false; } + bool isExternal() const { return false; } + void setExternal(bool e) { } + bool isYuv() const { return false; } +#else + unsigned int vectorSize : 3; // vector return type size. + // Some languages support structures as sample results. Storing the whole structure in the + // TSampler is too large, so there is an index to a separate table. + static const unsigned structReturnIndexBits = 4; // number of index bits to use. + static const unsigned structReturnSlots = (1< TTypeList; + +typedef TVector TIdentifierList; + +// +// Following are a series of helper enums for managing layouts and qualifiers, +// used for TPublicType, TType, others. +// + +enum TLayoutPacking { + ElpNone, + ElpShared, // default, but different than saying nothing + ElpStd140, + ElpStd430, + ElpPacked, + ElpScalar, + ElpCount // If expanding, see bitfield width below +}; + +enum TLayoutMatrix { + ElmNone, + ElmRowMajor, + ElmColumnMajor, // default, but different than saying nothing + ElmCount // If expanding, see bitfield width below +}; + +// Union of geometry shader and tessellation shader geometry types. +// They don't go into TType, but rather have current state per shader or +// active parser type (TPublicType). +enum TLayoutGeometry { + ElgNone, + ElgPoints, + ElgLines, + ElgLinesAdjacency, + ElgLineStrip, + ElgTriangles, + ElgTrianglesAdjacency, + ElgTriangleStrip, + ElgQuads, + ElgIsolines, +}; + +enum TVertexSpacing { + EvsNone, + EvsEqual, + EvsFractionalEven, + EvsFractionalOdd +}; + +enum TVertexOrder { + EvoNone, + EvoCw, + EvoCcw +}; + +// Note: order matters, as type of format is done by comparison. +enum TLayoutFormat { + ElfNone, + + // Float image + ElfRgba32f, + ElfRgba16f, + ElfR32f, + ElfRgba8, + ElfRgba8Snorm, + + ElfEsFloatGuard, // to help with comparisons + + ElfRg32f, + ElfRg16f, + ElfR11fG11fB10f, + ElfR16f, + ElfRgba16, + ElfRgb10A2, + ElfRg16, + ElfRg8, + ElfR16, + ElfR8, + ElfRgba16Snorm, + ElfRg16Snorm, + ElfRg8Snorm, + ElfR16Snorm, + ElfR8Snorm, + + ElfFloatGuard, // to help with comparisons + + // Int image + ElfRgba32i, + ElfRgba16i, + ElfRgba8i, + ElfR32i, + + ElfEsIntGuard, // to help with comparisons + + ElfRg32i, + ElfRg16i, + ElfRg8i, + ElfR16i, + ElfR8i, + + ElfIntGuard, // to help with comparisons + + // Uint image + ElfRgba32ui, + ElfRgba16ui, + ElfRgba8ui, + ElfR32ui, + + ElfEsUintGuard, // to help with comparisons + + ElfRg32ui, + ElfRg16ui, + ElfRgb10a2ui, + ElfRg8ui, + ElfR16ui, + ElfR8ui, + + ElfCount +}; + +enum TLayoutDepth { + EldNone, + EldAny, + EldGreater, + EldLess, + EldUnchanged, + + EldCount +}; + +enum TBlendEquationShift { + // No 'EBlendNone': + // These are used as bit-shift amounts. A mask of such shifts will have type 'int', + // and in that space, 0 means no bits set, or none. In this enum, 0 means (1 << 0), a bit is set. + EBlendMultiply, + EBlendScreen, + EBlendOverlay, + EBlendDarken, + EBlendLighten, + EBlendColordodge, + EBlendColorburn, + EBlendHardlight, + EBlendSoftlight, + EBlendDifference, + EBlendExclusion, + EBlendHslHue, + EBlendHslSaturation, + EBlendHslColor, + EBlendHslLuminosity, + EBlendAllEquations, + + EBlendCount +}; + +enum TInterlockOrdering { + EioNone, + EioPixelInterlockOrdered, + EioPixelInterlockUnordered, + EioSampleInterlockOrdered, + EioSampleInterlockUnordered, + EioShadingRateInterlockOrdered, + EioShadingRateInterlockUnordered, + + EioCount, +}; + +enum TShaderInterface +{ + // Includes both uniform blocks and buffer blocks + EsiUniform = 0, + EsiInput, + EsiOutput, + EsiNone, + + EsiCount +}; + + +class TQualifier { +public: + static const int layoutNotSet = -1; + + void clear() + { + precision = EpqNone; + invariant = false; + makeTemporary(); + declaredBuiltIn = EbvNone; +#ifndef GLSLANG_WEB + noContraction = false; +#endif + } + + // drop qualifiers that don't belong in a temporary variable + void makeTemporary() + { + semanticName = nullptr; + storage = EvqTemporary; + builtIn = EbvNone; + clearInterstage(); + clearMemory(); + specConstant = false; + nonUniform = false; + clearLayout(); + } + + void clearInterstage() + { + clearInterpolation(); +#ifndef GLSLANG_WEB + patch = false; + sample = false; +#endif + } + + void clearInterpolation() + { + centroid = false; + smooth = false; + flat = false; +#ifndef GLSLANG_WEB + nopersp = false; + explicitInterp = false; + pervertexNV = false; + perPrimitiveNV = false; + perViewNV = false; + perTaskNV = false; +#endif + } + + void clearMemory() + { +#ifndef GLSLANG_WEB + coherent = false; + devicecoherent = false; + queuefamilycoherent = false; + workgroupcoherent = false; + subgroupcoherent = false; + shadercallcoherent = false; + nonprivate = false; + volatil = false; + restrict = false; + readonly = false; + writeonly = false; +#endif + } + + const char* semanticName; + TStorageQualifier storage : 6; + TBuiltInVariable builtIn : 9; + TBuiltInVariable declaredBuiltIn : 9; + static_assert(EbvLast < 256, "need to increase size of TBuiltInVariable bitfields!"); + TPrecisionQualifier precision : 3; + bool invariant : 1; // require canonical treatment for cross-shader invariance + bool centroid : 1; + bool smooth : 1; + bool flat : 1; + // having a constant_id is not sufficient: expressions have no id, but are still specConstant + bool specConstant : 1; + bool nonUniform : 1; + bool explicitOffset : 1; + +#ifdef GLSLANG_WEB + bool isWriteOnly() const { return false; } + bool isReadOnly() const { return false; } + bool isRestrict() const { return false; } + bool isCoherent() const { return false; } + bool isVolatile() const { return false; } + bool isSample() const { return false; } + bool isMemory() const { return false; } + bool isMemoryQualifierImageAndSSBOOnly() const { return false; } + bool bufferReferenceNeedsVulkanMemoryModel() const { return false; } + bool isInterpolation() const { return flat || smooth; } + bool isExplicitInterpolation() const { return false; } + bool isAuxiliary() const { return centroid; } + bool isPatch() const { return false; } + bool isNoContraction() const { return false; } + void setNoContraction() { } + bool isPervertexNV() const { return false; } +#else + bool noContraction: 1; // prevent contraction and reassociation, e.g., for 'precise' keyword, and expressions it affects + bool nopersp : 1; + bool explicitInterp : 1; + bool pervertexNV : 1; + bool perPrimitiveNV : 1; + bool perViewNV : 1; + bool perTaskNV : 1; + bool patch : 1; + bool sample : 1; + bool restrict : 1; + bool readonly : 1; + bool writeonly : 1; + bool coherent : 1; + bool volatil : 1; + bool devicecoherent : 1; + bool queuefamilycoherent : 1; + bool workgroupcoherent : 1; + bool subgroupcoherent : 1; + bool shadercallcoherent : 1; + bool nonprivate : 1; + bool isWriteOnly() const { return writeonly; } + bool isReadOnly() const { return readonly; } + bool isRestrict() const { return restrict; } + bool isCoherent() const { return coherent; } + bool isVolatile() const { return volatil; } + bool isSample() const { return sample; } + bool isMemory() const + { + return shadercallcoherent || subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly || nonprivate; + } + bool isMemoryQualifierImageAndSSBOOnly() const + { + return shadercallcoherent || subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly; + } + bool bufferReferenceNeedsVulkanMemoryModel() const + { + // include qualifiers that map to load/store availability/visibility/nonprivate memory access operands + return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || nonprivate; + } + bool isInterpolation() const + { + return flat || smooth || nopersp || explicitInterp; + } + bool isExplicitInterpolation() const + { + return explicitInterp; + } + bool isAuxiliary() const + { + return centroid || patch || sample || pervertexNV; + } + bool isPatch() const { return patch; } + bool isNoContraction() const { return noContraction; } + void setNoContraction() { noContraction = true; } + bool isPervertexNV() const { return pervertexNV; } +#endif + + bool isPipeInput() const + { + switch (storage) { + case EvqVaryingIn: + case EvqFragCoord: + case EvqPointCoord: + case EvqFace: + case EvqVertexId: + case EvqInstanceId: + return true; + default: + return false; + } + } + + bool isPipeOutput() const + { + switch (storage) { + case EvqPosition: + case EvqPointSize: + case EvqClipVertex: + case EvqVaryingOut: + case EvqFragColor: + case EvqFragDepth: + return true; + default: + return false; + } + } + + bool isParamInput() const + { + switch (storage) { + case EvqIn: + case EvqInOut: + case EvqConstReadOnly: + return true; + default: + return false; + } + } + + bool isParamOutput() const + { + switch (storage) { + case EvqOut: + case EvqInOut: + return true; + default: + return false; + } + } + + bool isUniformOrBuffer() const + { + switch (storage) { + case EvqUniform: + case EvqBuffer: + return true; + default: + return false; + } + } + + bool isIo() const + { + switch (storage) { + case EvqUniform: + case EvqBuffer: + case EvqVaryingIn: + case EvqFragCoord: + case EvqPointCoord: + case EvqFace: + case EvqVertexId: + case EvqInstanceId: + case EvqPosition: + case EvqPointSize: + case EvqClipVertex: + case EvqVaryingOut: + case EvqFragColor: + case EvqFragDepth: + return true; + default: + return false; + } + } + + // non-built-in symbols that might link between compilation units + bool isLinkable() const + { + switch (storage) { + case EvqGlobal: + case EvqVaryingIn: + case EvqVaryingOut: + case EvqUniform: + case EvqBuffer: + case EvqShared: + return true; + default: + return false; + } + } + +#ifdef GLSLANG_WEB + bool isPerView() const { return false; } + bool isTaskMemory() const { return false; } + bool isArrayedIo(EShLanguage language) const { return false; } +#else + bool isPerPrimitive() const { return perPrimitiveNV; } + bool isPerView() const { return perViewNV; } + bool isTaskMemory() const { return perTaskNV; } + + // True if this type of IO is supposed to be arrayed with extra level for per-vertex data + bool isArrayedIo(EShLanguage language) const + { + switch (language) { + case EShLangGeometry: + return isPipeInput(); + case EShLangTessControl: + return ! patch && (isPipeInput() || isPipeOutput()); + case EShLangTessEvaluation: + return ! patch && isPipeInput(); + case EShLangFragment: + return pervertexNV && isPipeInput(); + case EShLangMeshNV: + return ! perTaskNV && isPipeOutput(); + + default: + return false; + } + } +#endif + + // Implementing an embedded layout-qualifier class here, since C++ can't have a real class bitfield + void clearLayout() // all layout + { + clearUniformLayout(); + +#ifndef GLSLANG_WEB + layoutPushConstant = false; + layoutBufferReference = false; + layoutPassthrough = false; + layoutViewportRelative = false; + // -2048 as the default value indicating layoutSecondaryViewportRelative is not set + layoutSecondaryViewportRelativeOffset = -2048; + layoutShaderRecord = false; + layoutBufferReferenceAlign = layoutBufferReferenceAlignEnd; + layoutFormat = ElfNone; +#endif + + clearInterstageLayout(); + + layoutSpecConstantId = layoutSpecConstantIdEnd; + } + void clearInterstageLayout() + { + layoutLocation = layoutLocationEnd; + layoutComponent = layoutComponentEnd; +#ifndef GLSLANG_WEB + layoutIndex = layoutIndexEnd; + clearStreamLayout(); + clearXfbLayout(); +#endif + } + +#ifndef GLSLANG_WEB + void clearStreamLayout() + { + layoutStream = layoutStreamEnd; + } + void clearXfbLayout() + { + layoutXfbBuffer = layoutXfbBufferEnd; + layoutXfbStride = layoutXfbStrideEnd; + layoutXfbOffset = layoutXfbOffsetEnd; + } +#endif + + bool hasNonXfbLayout() const + { + return hasUniformLayout() || + hasAnyLocation() || + hasStream() || + hasFormat() || + isShaderRecord() || + isPushConstant() || + hasBufferReference(); + } + bool hasLayout() const + { + return hasNonXfbLayout() || + hasXfb(); + } + TLayoutMatrix layoutMatrix : 3; + TLayoutPacking layoutPacking : 4; + int layoutOffset; + int layoutAlign; + + unsigned int layoutLocation : 12; + static const unsigned int layoutLocationEnd = 0xFFF; + + unsigned int layoutComponent : 3; + static const unsigned int layoutComponentEnd = 4; + + unsigned int layoutSet : 7; + static const unsigned int layoutSetEnd = 0x3F; + + unsigned int layoutBinding : 16; + static const unsigned int layoutBindingEnd = 0xFFFF; + + unsigned int layoutIndex : 8; + static const unsigned int layoutIndexEnd = 0xFF; + + unsigned int layoutStream : 8; + static const unsigned int layoutStreamEnd = 0xFF; + + unsigned int layoutXfbBuffer : 4; + static const unsigned int layoutXfbBufferEnd = 0xF; + + unsigned int layoutXfbStride : 14; + static const unsigned int layoutXfbStrideEnd = 0x3FFF; + + unsigned int layoutXfbOffset : 13; + static const unsigned int layoutXfbOffsetEnd = 0x1FFF; + + unsigned int layoutAttachment : 8; // for input_attachment_index + static const unsigned int layoutAttachmentEnd = 0XFF; + + unsigned int layoutSpecConstantId : 11; + static const unsigned int layoutSpecConstantIdEnd = 0x7FF; + +#ifndef GLSLANG_WEB + // stored as log2 of the actual alignment value + unsigned int layoutBufferReferenceAlign : 6; + static const unsigned int layoutBufferReferenceAlignEnd = 0x3F; + + TLayoutFormat layoutFormat : 8; + + bool layoutPushConstant; + bool layoutBufferReference; + bool layoutPassthrough; + bool layoutViewportRelative; + int layoutSecondaryViewportRelativeOffset; + bool layoutShaderRecord; +#endif + + bool hasUniformLayout() const + { + return hasMatrix() || + hasPacking() || + hasOffset() || + hasBinding() || + hasSet() || + hasAlign(); + } + void clearUniformLayout() // only uniform specific + { + layoutMatrix = ElmNone; + layoutPacking = ElpNone; + layoutOffset = layoutNotSet; + layoutAlign = layoutNotSet; + + layoutSet = layoutSetEnd; + layoutBinding = layoutBindingEnd; +#ifndef GLSLANG_WEB + layoutAttachment = layoutAttachmentEnd; +#endif + } + + bool hasMatrix() const + { + return layoutMatrix != ElmNone; + } + bool hasPacking() const + { + return layoutPacking != ElpNone; + } + bool hasAlign() const + { + return layoutAlign != layoutNotSet; + } + bool hasAnyLocation() const + { + return hasLocation() || + hasComponent() || + hasIndex(); + } + bool hasLocation() const + { + return layoutLocation != layoutLocationEnd; + } + bool hasSet() const + { + return layoutSet != layoutSetEnd; + } + bool hasBinding() const + { + return layoutBinding != layoutBindingEnd; + } +#ifdef GLSLANG_WEB + bool hasOffset() const { return false; } + bool isNonPerspective() const { return false; } + bool hasIndex() const { return false; } + unsigned getIndex() const { return 0; } + bool hasComponent() const { return false; } + bool hasStream() const { return false; } + bool hasFormat() const { return false; } + bool hasXfb() const { return false; } + bool hasXfbBuffer() const { return false; } + bool hasXfbStride() const { return false; } + bool hasXfbOffset() const { return false; } + bool hasAttachment() const { return false; } + TLayoutFormat getFormat() const { return ElfNone; } + bool isPushConstant() const { return false; } + bool isShaderRecord() const { return false; } + bool hasBufferReference() const { return false; } + bool hasBufferReferenceAlign() const { return false; } + bool isNonUniform() const { return false; } +#else + bool hasOffset() const + { + return layoutOffset != layoutNotSet; + } + bool isNonPerspective() const { return nopersp; } + bool hasIndex() const + { + return layoutIndex != layoutIndexEnd; + } + unsigned getIndex() const { return layoutIndex; } + bool hasComponent() const + { + return layoutComponent != layoutComponentEnd; + } + bool hasStream() const + { + return layoutStream != layoutStreamEnd; + } + bool hasFormat() const + { + return layoutFormat != ElfNone; + } + bool hasXfb() const + { + return hasXfbBuffer() || + hasXfbStride() || + hasXfbOffset(); + } + bool hasXfbBuffer() const + { + return layoutXfbBuffer != layoutXfbBufferEnd; + } + bool hasXfbStride() const + { + return layoutXfbStride != layoutXfbStrideEnd; + } + bool hasXfbOffset() const + { + return layoutXfbOffset != layoutXfbOffsetEnd; + } + bool hasAttachment() const + { + return layoutAttachment != layoutAttachmentEnd; + } + TLayoutFormat getFormat() const { return layoutFormat; } + bool isPushConstant() const { return layoutPushConstant; } + bool isShaderRecord() const { return layoutShaderRecord; } + bool hasBufferReference() const { return layoutBufferReference; } + bool hasBufferReferenceAlign() const + { + return layoutBufferReferenceAlign != layoutBufferReferenceAlignEnd; + } + bool isNonUniform() const + { + return nonUniform; + } +#endif + bool hasSpecConstantId() const + { + // Not the same thing as being a specialization constant, this + // is just whether or not it was declared with an ID. + return layoutSpecConstantId != layoutSpecConstantIdEnd; + } + bool isSpecConstant() const + { + // True if type is a specialization constant, whether or not it + // had a specialization-constant ID, and false if it is not a + // true front-end constant. + return specConstant; + } + bool isFrontEndConstant() const + { + // True if the front-end knows the final constant value. + // This allows front-end constant folding. + return storage == EvqConst && ! specConstant; + } + bool isConstant() const + { + // True if is either kind of constant; specialization or regular. + return isFrontEndConstant() || isSpecConstant(); + } + void makeSpecConstant() + { + storage = EvqConst; + specConstant = true; + } + static const char* getLayoutPackingString(TLayoutPacking packing) + { + switch (packing) { + case ElpStd140: return "std140"; +#ifndef GLSLANG_WEB + case ElpPacked: return "packed"; + case ElpShared: return "shared"; + case ElpStd430: return "std430"; + case ElpScalar: return "scalar"; +#endif + default: return "none"; + } + } + static const char* getLayoutMatrixString(TLayoutMatrix m) + { + switch (m) { + case ElmColumnMajor: return "column_major"; + case ElmRowMajor: return "row_major"; + default: return "none"; + } + } +#ifdef GLSLANG_WEB + static const char* getLayoutFormatString(TLayoutFormat f) { return "none"; } +#else + static const char* getLayoutFormatString(TLayoutFormat f) + { + switch (f) { + case ElfRgba32f: return "rgba32f"; + case ElfRgba16f: return "rgba16f"; + case ElfRg32f: return "rg32f"; + case ElfRg16f: return "rg16f"; + case ElfR11fG11fB10f: return "r11f_g11f_b10f"; + case ElfR32f: return "r32f"; + case ElfR16f: return "r16f"; + case ElfRgba16: return "rgba16"; + case ElfRgb10A2: return "rgb10_a2"; + case ElfRgba8: return "rgba8"; + case ElfRg16: return "rg16"; + case ElfRg8: return "rg8"; + case ElfR16: return "r16"; + case ElfR8: return "r8"; + case ElfRgba16Snorm: return "rgba16_snorm"; + case ElfRgba8Snorm: return "rgba8_snorm"; + case ElfRg16Snorm: return "rg16_snorm"; + case ElfRg8Snorm: return "rg8_snorm"; + case ElfR16Snorm: return "r16_snorm"; + case ElfR8Snorm: return "r8_snorm"; + + case ElfRgba32i: return "rgba32i"; + case ElfRgba16i: return "rgba16i"; + case ElfRgba8i: return "rgba8i"; + case ElfRg32i: return "rg32i"; + case ElfRg16i: return "rg16i"; + case ElfRg8i: return "rg8i"; + case ElfR32i: return "r32i"; + case ElfR16i: return "r16i"; + case ElfR8i: return "r8i"; + + case ElfRgba32ui: return "rgba32ui"; + case ElfRgba16ui: return "rgba16ui"; + case ElfRgba8ui: return "rgba8ui"; + case ElfRg32ui: return "rg32ui"; + case ElfRg16ui: return "rg16ui"; + case ElfRgb10a2ui: return "rgb10_a2ui"; + case ElfRg8ui: return "rg8ui"; + case ElfR32ui: return "r32ui"; + case ElfR16ui: return "r16ui"; + case ElfR8ui: return "r8ui"; + default: return "none"; + } + } + static const char* getLayoutDepthString(TLayoutDepth d) + { + switch (d) { + case EldAny: return "depth_any"; + case EldGreater: return "depth_greater"; + case EldLess: return "depth_less"; + case EldUnchanged: return "depth_unchanged"; + default: return "none"; + } + } + static const char* getBlendEquationString(TBlendEquationShift e) + { + switch (e) { + case EBlendMultiply: return "blend_support_multiply"; + case EBlendScreen: return "blend_support_screen"; + case EBlendOverlay: return "blend_support_overlay"; + case EBlendDarken: return "blend_support_darken"; + case EBlendLighten: return "blend_support_lighten"; + case EBlendColordodge: return "blend_support_colordodge"; + case EBlendColorburn: return "blend_support_colorburn"; + case EBlendHardlight: return "blend_support_hardlight"; + case EBlendSoftlight: return "blend_support_softlight"; + case EBlendDifference: return "blend_support_difference"; + case EBlendExclusion: return "blend_support_exclusion"; + case EBlendHslHue: return "blend_support_hsl_hue"; + case EBlendHslSaturation: return "blend_support_hsl_saturation"; + case EBlendHslColor: return "blend_support_hsl_color"; + case EBlendHslLuminosity: return "blend_support_hsl_luminosity"; + case EBlendAllEquations: return "blend_support_all_equations"; + default: return "unknown"; + } + } + static const char* getGeometryString(TLayoutGeometry geometry) + { + switch (geometry) { + case ElgPoints: return "points"; + case ElgLines: return "lines"; + case ElgLinesAdjacency: return "lines_adjacency"; + case ElgLineStrip: return "line_strip"; + case ElgTriangles: return "triangles"; + case ElgTrianglesAdjacency: return "triangles_adjacency"; + case ElgTriangleStrip: return "triangle_strip"; + case ElgQuads: return "quads"; + case ElgIsolines: return "isolines"; + default: return "none"; + } + } + static const char* getVertexSpacingString(TVertexSpacing spacing) + { + switch (spacing) { + case EvsEqual: return "equal_spacing"; + case EvsFractionalEven: return "fractional_even_spacing"; + case EvsFractionalOdd: return "fractional_odd_spacing"; + default: return "none"; + } + } + static const char* getVertexOrderString(TVertexOrder order) + { + switch (order) { + case EvoCw: return "cw"; + case EvoCcw: return "ccw"; + default: return "none"; + } + } + static int mapGeometryToSize(TLayoutGeometry geometry) + { + switch (geometry) { + case ElgPoints: return 1; + case ElgLines: return 2; + case ElgLinesAdjacency: return 4; + case ElgTriangles: return 3; + case ElgTrianglesAdjacency: return 6; + default: return 0; + } + } + static const char* getInterlockOrderingString(TInterlockOrdering order) + { + switch (order) { + case EioPixelInterlockOrdered: return "pixel_interlock_ordered"; + case EioPixelInterlockUnordered: return "pixel_interlock_unordered"; + case EioSampleInterlockOrdered: return "sample_interlock_ordered"; + case EioSampleInterlockUnordered: return "sample_interlock_unordered"; + case EioShadingRateInterlockOrdered: return "shading_rate_interlock_ordered"; + case EioShadingRateInterlockUnordered: return "shading_rate_interlock_unordered"; + default: return "none"; + } + } +#endif +}; + +// Qualifiers that don't need to be keep per object. They have shader scope, not object scope. +// So, they will not be part of TType, TQualifier, etc. +struct TShaderQualifiers { + TLayoutGeometry geometry; // geometry/tessellation shader in/out primitives + bool pixelCenterInteger; // fragment shader + bool originUpperLeft; // fragment shader + int invocations; + int vertices; // for tessellation "vertices", geometry & mesh "max_vertices" + TVertexSpacing spacing; + TVertexOrder order; + bool pointMode; + int localSize[3]; // compute shader + bool localSizeNotDefault[3]; // compute shader + int localSizeSpecId[3]; // compute shader specialization id for gl_WorkGroupSize +#ifndef GLSLANG_WEB + bool earlyFragmentTests; // fragment input + bool postDepthCoverage; // fragment input + TLayoutDepth layoutDepth; + bool blendEquation; // true if any blend equation was specified + int numViews; // multiview extenstions + TInterlockOrdering interlockOrdering; + bool layoutOverrideCoverage; // true if layout override_coverage set + bool layoutDerivativeGroupQuads; // true if layout derivative_group_quadsNV set + bool layoutDerivativeGroupLinear; // true if layout derivative_group_linearNV set + int primitives; // mesh shader "max_primitives"DerivativeGroupLinear; // true if layout derivative_group_linearNV set + TLayoutDepth getDepth() const { return layoutDepth; } +#else + TLayoutDepth getDepth() const { return EldNone; } +#endif + + void init() + { + geometry = ElgNone; + originUpperLeft = false; + pixelCenterInteger = false; + invocations = TQualifier::layoutNotSet; + vertices = TQualifier::layoutNotSet; + spacing = EvsNone; + order = EvoNone; + pointMode = false; + localSize[0] = 1; + localSize[1] = 1; + localSize[2] = 1; + localSizeNotDefault[0] = false; + localSizeNotDefault[1] = false; + localSizeNotDefault[2] = false; + localSizeSpecId[0] = TQualifier::layoutNotSet; + localSizeSpecId[1] = TQualifier::layoutNotSet; + localSizeSpecId[2] = TQualifier::layoutNotSet; +#ifndef GLSLANG_WEB + earlyFragmentTests = false; + postDepthCoverage = false; + layoutDepth = EldNone; + blendEquation = false; + numViews = TQualifier::layoutNotSet; + layoutOverrideCoverage = false; + layoutDerivativeGroupQuads = false; + layoutDerivativeGroupLinear = false; + primitives = TQualifier::layoutNotSet; + interlockOrdering = EioNone; +#endif + } + +#ifdef GLSLANG_WEB + bool hasBlendEquation() const { return false; } +#else + bool hasBlendEquation() const { return blendEquation; } +#endif + + // Merge in characteristics from the 'src' qualifier. They can override when + // set, but never erase when not set. + void merge(const TShaderQualifiers& src) + { + if (src.geometry != ElgNone) + geometry = src.geometry; + if (src.pixelCenterInteger) + pixelCenterInteger = src.pixelCenterInteger; + if (src.originUpperLeft) + originUpperLeft = src.originUpperLeft; + if (src.invocations != TQualifier::layoutNotSet) + invocations = src.invocations; + if (src.vertices != TQualifier::layoutNotSet) + vertices = src.vertices; + if (src.spacing != EvsNone) + spacing = src.spacing; + if (src.order != EvoNone) + order = src.order; + if (src.pointMode) + pointMode = true; + for (int i = 0; i < 3; ++i) { + if (src.localSize[i] > 1) + localSize[i] = src.localSize[i]; + } + for (int i = 0; i < 3; ++i) { + localSizeNotDefault[i] = src.localSizeNotDefault[i] || localSizeNotDefault[i]; + } + for (int i = 0; i < 3; ++i) { + if (src.localSizeSpecId[i] != TQualifier::layoutNotSet) + localSizeSpecId[i] = src.localSizeSpecId[i]; + } +#ifndef GLSLANG_WEB + if (src.earlyFragmentTests) + earlyFragmentTests = true; + if (src.postDepthCoverage) + postDepthCoverage = true; + if (src.layoutDepth) + layoutDepth = src.layoutDepth; + if (src.blendEquation) + blendEquation = src.blendEquation; + if (src.numViews != TQualifier::layoutNotSet) + numViews = src.numViews; + if (src.layoutOverrideCoverage) + layoutOverrideCoverage = src.layoutOverrideCoverage; + if (src.layoutDerivativeGroupQuads) + layoutDerivativeGroupQuads = src.layoutDerivativeGroupQuads; + if (src.layoutDerivativeGroupLinear) + layoutDerivativeGroupLinear = src.layoutDerivativeGroupLinear; + if (src.primitives != TQualifier::layoutNotSet) + primitives = src.primitives; + if (src.interlockOrdering != EioNone) + interlockOrdering = src.interlockOrdering; +#endif + } +}; + +// +// TPublicType is just temporarily used while parsing and not quite the same +// information kept per node in TType. Due to the bison stack, it can't have +// types that it thinks have non-trivial constructors. It should +// just be used while recognizing the grammar, not anything else. +// Once enough is known about the situation, the proper information +// moved into a TType, or the parse context, etc. +// +class TPublicType { +public: + TBasicType basicType; + TSampler sampler; + TQualifier qualifier; + TShaderQualifiers shaderQualifiers; + int vectorSize : 4; + int matrixCols : 4; + int matrixRows : 4; + bool coopmat : 1; + TArraySizes* arraySizes; + const TType* userDef; + TSourceLoc loc; + TArraySizes* typeParameters; + +#ifdef GLSLANG_WEB + bool isCoopmat() const { return false; } +#else + bool isCoopmat() const { return coopmat; } +#endif + + void initType(const TSourceLoc& l) + { + basicType = EbtVoid; + vectorSize = 1; + matrixRows = 0; + matrixCols = 0; + arraySizes = nullptr; + userDef = nullptr; + loc = l; + typeParameters = nullptr; + coopmat = false; + } + + void initQualifiers(bool global = false) + { + qualifier.clear(); + if (global) + qualifier.storage = EvqGlobal; + } + + void init(const TSourceLoc& l, bool global = false) + { + initType(l); + sampler.clear(); + initQualifiers(global); + shaderQualifiers.init(); + } + + void setVector(int s) + { + matrixRows = 0; + matrixCols = 0; + vectorSize = s; + } + + void setMatrix(int c, int r) + { + matrixRows = r; + matrixCols = c; + vectorSize = 0; + } + + bool isScalar() const + { + return matrixCols == 0 && vectorSize == 1 && arraySizes == nullptr && userDef == nullptr; + } + + // "Image" is a superset of "Subpass" + bool isImage() const { return basicType == EbtSampler && sampler.isImage(); } + bool isSubpass() const { return basicType == EbtSampler && sampler.isSubpass(); } +}; + +// +// Base class for things that have a type. +// +class TType { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + // for "empty" type (no args) or simple scalar/vector/matrix + explicit TType(TBasicType t = EbtVoid, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0, + bool isVector = false) : + basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1), coopmat(false), + arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr) + { + sampler.clear(); + qualifier.clear(); + qualifier.storage = q; + assert(!(isMatrix() && vectorSize != 0)); // prevent vectorSize != 0 on matrices + } + // for explicit precision qualifier + TType(TBasicType t, TStorageQualifier q, TPrecisionQualifier p, int vs = 1, int mc = 0, int mr = 0, + bool isVector = false) : + basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1), coopmat(false), + arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr) + { + sampler.clear(); + qualifier.clear(); + qualifier.storage = q; + qualifier.precision = p; + assert(p >= EpqNone && p <= EpqHigh); + assert(!(isMatrix() && vectorSize != 0)); // prevent vectorSize != 0 on matrices + } + // for turning a TPublicType into a TType, using a shallow copy + explicit TType(const TPublicType& p) : + basicType(p.basicType), + vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), vector1(false), coopmat(p.coopmat), + arraySizes(p.arraySizes), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(p.typeParameters) + { + if (basicType == EbtSampler) + sampler = p.sampler; + else + sampler.clear(); + qualifier = p.qualifier; + if (p.userDef) { + if (p.userDef->basicType == EbtReference) { + basicType = EbtReference; + referentType = p.userDef->referentType; + } else { + structure = p.userDef->getWritableStruct(); // public type is short-lived; there are no sharing issues + } + typeName = NewPoolTString(p.userDef->getTypeName().c_str()); + } + if (p.isCoopmat() && p.typeParameters && p.typeParameters->getNumDims() > 0) { + int numBits = p.typeParameters->getDimSize(0); + if (p.basicType == EbtFloat && numBits == 16) { + basicType = EbtFloat16; + qualifier.precision = EpqNone; + } else if (p.basicType == EbtUint && numBits == 8) { + basicType = EbtUint8; + qualifier.precision = EpqNone; + } else if (p.basicType == EbtInt && numBits == 8) { + basicType = EbtInt8; + qualifier.precision = EpqNone; + } + } + } + // for construction of sampler types + TType(const TSampler& sampler, TStorageQualifier q = EvqUniform, TArraySizes* as = nullptr) : + basicType(EbtSampler), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false), + arraySizes(as), structure(nullptr), fieldName(nullptr), typeName(nullptr), + sampler(sampler), typeParameters(nullptr) + { + qualifier.clear(); + qualifier.storage = q; + } + // to efficiently make a dereferenced type + // without ever duplicating the outer structure that will be thrown away + // and using only shallow copy + TType(const TType& type, int derefIndex, bool rowMajor = false) + { + if (type.isArray()) { + shallowCopy(type); + if (type.getArraySizes()->getNumDims() == 1) { + arraySizes = nullptr; + } else { + // want our own copy of the array, so we can edit it + arraySizes = new TArraySizes; + arraySizes->copyDereferenced(*type.arraySizes); + } + } else if (type.basicType == EbtStruct || type.basicType == EbtBlock) { + // do a structure dereference + const TTypeList& memberList = *type.getStruct(); + shallowCopy(*memberList[derefIndex].type); + return; + } else { + // do a vector/matrix dereference + shallowCopy(type); + if (matrixCols > 0) { + // dereference from matrix to vector + if (rowMajor) + vectorSize = matrixCols; + else + vectorSize = matrixRows; + matrixCols = 0; + matrixRows = 0; + if (vectorSize == 1) + vector1 = true; + } else if (isVector()) { + // dereference from vector to scalar + vectorSize = 1; + vector1 = false; + } else if (isCoopMat()) { + coopmat = false; + typeParameters = nullptr; + } + } + } + // for making structures, ... + TType(TTypeList* userDef, const TString& n) : + basicType(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false), + arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr) + { + sampler.clear(); + qualifier.clear(); + typeName = NewPoolTString(n.c_str()); + } + // For interface blocks + TType(TTypeList* userDef, const TString& n, const TQualifier& q) : + basicType(EbtBlock), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false), + qualifier(q), arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr) + { + sampler.clear(); + typeName = NewPoolTString(n.c_str()); + } + // for block reference (first parameter must be EbtReference) + explicit TType(TBasicType t, const TType &p, const TString& n) : + basicType(t), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), + arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr) + { + assert(t == EbtReference); + typeName = NewPoolTString(n.c_str()); + qualifier.clear(); + qualifier.storage = p.qualifier.storage; + referentType = p.clone(); + } + virtual ~TType() {} + + // Not for use across pool pops; it will cause multiple instances of TType to point to the same information. + // This only works if that information (like a structure's list of types) does not change and + // the instances are sharing the same pool. + void shallowCopy(const TType& copyOf) + { + basicType = copyOf.basicType; + sampler = copyOf.sampler; + qualifier = copyOf.qualifier; + vectorSize = copyOf.vectorSize; + matrixCols = copyOf.matrixCols; + matrixRows = copyOf.matrixRows; + vector1 = copyOf.vector1; + arraySizes = copyOf.arraySizes; // copying the pointer only, not the contents + fieldName = copyOf.fieldName; + typeName = copyOf.typeName; + if (isStruct()) { + structure = copyOf.structure; + } else { + referentType = copyOf.referentType; + } + typeParameters = copyOf.typeParameters; + coopmat = copyOf.isCoopMat(); + } + + // Make complete copy of the whole type graph rooted at 'copyOf'. + void deepCopy(const TType& copyOf) + { + TMap copied; // to enable copying a type graph as a graph, not a tree + deepCopy(copyOf, copied); + } + + // Recursively make temporary + void makeTemporary() + { + getQualifier().makeTemporary(); + + if (isStruct()) + for (unsigned int i = 0; i < structure->size(); ++i) + (*structure)[i].type->makeTemporary(); + } + + TType* clone() const + { + TType *newType = new TType(); + newType->deepCopy(*this); + + return newType; + } + + void makeVector() { vector1 = true; } + + virtual void hideMember() { basicType = EbtVoid; vectorSize = 1; } + virtual bool hiddenMember() const { return basicType == EbtVoid; } + + virtual void setFieldName(const TString& n) { fieldName = NewPoolTString(n.c_str()); } + virtual const TString& getTypeName() const + { + assert(typeName); + return *typeName; + } + + virtual const TString& getFieldName() const + { + assert(fieldName); + return *fieldName; + } + TShaderInterface getShaderInterface() const + { + if (basicType != EbtBlock) + return EsiNone; + + switch (qualifier.storage) { + default: + return EsiNone; + case EvqVaryingIn: + return EsiInput; + case EvqVaryingOut: + return EsiOutput; + case EvqUniform: + case EvqBuffer: + return EsiUniform; + } + } + + virtual TBasicType getBasicType() const { return basicType; } + virtual const TSampler& getSampler() const { return sampler; } + virtual TSampler& getSampler() { return sampler; } + + virtual TQualifier& getQualifier() { return qualifier; } + virtual const TQualifier& getQualifier() const { return qualifier; } + + virtual int getVectorSize() const { return vectorSize; } // returns 1 for either scalar or vector of size 1, valid for both + virtual int getMatrixCols() const { return matrixCols; } + virtual int getMatrixRows() const { return matrixRows; } + virtual int getOuterArraySize() const { return arraySizes->getOuterSize(); } + virtual TIntermTyped* getOuterArrayNode() const { return arraySizes->getOuterNode(); } + virtual int getCumulativeArraySize() const { return arraySizes->getCumulativeSize(); } +#ifdef GLSLANG_WEB + bool isArrayOfArrays() const { return false; } +#else + bool isArrayOfArrays() const { return arraySizes != nullptr && arraySizes->getNumDims() > 1; } +#endif + virtual int getImplicitArraySize() const { return arraySizes->getImplicitSize(); } + virtual const TArraySizes* getArraySizes() const { return arraySizes; } + virtual TArraySizes* getArraySizes() { return arraySizes; } + virtual TType* getReferentType() const { return referentType; } + virtual const TArraySizes* getTypeParameters() const { return typeParameters; } + virtual TArraySizes* getTypeParameters() { return typeParameters; } + + virtual bool isScalar() const { return ! isVector() && ! isMatrix() && ! isStruct() && ! isArray(); } + virtual bool isScalarOrVec1() const { return isScalar() || vector1; } + virtual bool isVector() const { return vectorSize > 1 || vector1; } + virtual bool isMatrix() const { return matrixCols ? true : false; } + virtual bool isArray() const { return arraySizes != nullptr; } + virtual bool isSizedArray() const { return isArray() && arraySizes->isSized(); } + virtual bool isUnsizedArray() const { return isArray() && !arraySizes->isSized(); } + virtual bool isArrayVariablyIndexed() const { assert(isArray()); return arraySizes->isVariablyIndexed(); } + virtual void setArrayVariablyIndexed() { assert(isArray()); arraySizes->setVariablyIndexed(); } + virtual void updateImplicitArraySize(int size) { assert(isArray()); arraySizes->updateImplicitSize(size); } + virtual bool isStruct() const { return basicType == EbtStruct || basicType == EbtBlock; } + virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble || basicType == EbtFloat16; } + virtual bool isIntegerDomain() const + { + switch (basicType) { + case EbtInt8: + case EbtUint8: + case EbtInt16: + case EbtUint16: + case EbtInt: + case EbtUint: + case EbtInt64: + case EbtUint64: + case EbtAtomicUint: + return true; + default: + break; + } + return false; + } + virtual bool isOpaque() const { return basicType == EbtSampler +#ifndef GLSLANG_WEB + || basicType == EbtAtomicUint || basicType == EbtAccStruct || basicType == EbtRayQuery +#endif + ; } + virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; } + + // "Image" is a superset of "Subpass" + virtual bool isImage() const { return basicType == EbtSampler && getSampler().isImage(); } + virtual bool isSubpass() const { return basicType == EbtSampler && getSampler().isSubpass(); } + virtual bool isTexture() const { return basicType == EbtSampler && getSampler().isTexture(); } + // Check the block-name convention of creating a block without populating it's members: + virtual bool isUnusableName() const { return isStruct() && structure == nullptr; } + virtual bool isParameterized() const { return typeParameters != nullptr; } +#ifdef GLSLANG_WEB + bool isAtomic() const { return false; } + bool isCoopMat() const { return false; } + bool isReference() const { return false; } +#else + bool isAtomic() const { return basicType == EbtAtomicUint; } + bool isCoopMat() const { return coopmat; } + bool isReference() const { return getBasicType() == EbtReference; } +#endif + + // return true if this type contains any subtype which satisfies the given predicate. + template + bool contains(P predicate) const + { + if (predicate(this)) + return true; + + const auto hasa = [predicate](const TTypeLoc& tl) { return tl.type->contains(predicate); }; + + return isStruct() && std::any_of(structure->begin(), structure->end(), hasa); + } + + // Recursively checks if the type contains the given basic type + virtual bool containsBasicType(TBasicType checkType) const + { + return contains([checkType](const TType* t) { return t->basicType == checkType; } ); + } + + // Recursively check the structure for any arrays, needed for some error checks + virtual bool containsArray() const + { + return contains([](const TType* t) { return t->isArray(); } ); + } + + // Check the structure for any structures, needed for some error checks + virtual bool containsStructure() const + { + return contains([this](const TType* t) { return t != this && t->isStruct(); } ); + } + + // Recursively check the structure for any unsized arrays, needed for triggering a copyUp(). + virtual bool containsUnsizedArray() const + { + return contains([](const TType* t) { return t->isUnsizedArray(); } ); + } + + virtual bool containsOpaque() const + { + return contains([](const TType* t) { return t->isOpaque(); } ); + } + + // Recursively checks if the type contains a built-in variable + virtual bool containsBuiltIn() const + { + return contains([](const TType* t) { return t->isBuiltIn(); } ); + } + + virtual bool containsNonOpaque() const + { + const auto nonOpaque = [](const TType* t) { + switch (t->basicType) { + case EbtVoid: + case EbtFloat: + case EbtDouble: + case EbtFloat16: + case EbtInt8: + case EbtUint8: + case EbtInt16: + case EbtUint16: + case EbtInt: + case EbtUint: + case EbtInt64: + case EbtUint64: + case EbtBool: + case EbtReference: + return true; + default: + return false; + } + }; + + return contains(nonOpaque); + } + + virtual bool containsSpecializationSize() const + { + return contains([](const TType* t) { return t->isArray() && t->arraySizes->isOuterSpecialization(); } ); + } + +#ifdef GLSLANG_WEB + bool containsDouble() const { return false; } + bool contains16BitFloat() const { return false; } + bool contains64BitInt() const { return false; } + bool contains16BitInt() const { return false; } + bool contains8BitInt() const { return false; } + bool containsCoopMat() const { return false; } + bool containsReference() const { return false; } +#else + bool containsDouble() const + { + return containsBasicType(EbtDouble); + } + bool contains16BitFloat() const + { + return containsBasicType(EbtFloat16); + } + bool contains64BitInt() const + { + return containsBasicType(EbtInt64) || containsBasicType(EbtUint64); + } + bool contains16BitInt() const + { + return containsBasicType(EbtInt16) || containsBasicType(EbtUint16); + } + bool contains8BitInt() const + { + return containsBasicType(EbtInt8) || containsBasicType(EbtUint8); + } + bool containsCoopMat() const + { + return contains([](const TType* t) { return t->coopmat; } ); + } + bool containsReference() const + { + return containsBasicType(EbtReference); + } +#endif + + // Array editing methods. Array descriptors can be shared across + // type instances. This allows all uses of the same array + // to be updated at once. E.g., all nodes can be explicitly sized + // by tracking and correcting one implicit size. Or, all nodes + // can get the explicit size on a redeclaration that gives size. + // + // N.B.: Don't share with the shared symbol tables (symbols are + // marked as isReadOnly(). Such symbols with arrays that will be + // edited need to copyUp() on first use, so that + // A) the edits don't effect the shared symbol table, and + // B) the edits are shared across all users. + void updateArraySizes(const TType& type) + { + // For when we may already be sharing existing array descriptors, + // keeping the pointers the same, just updating the contents. + assert(arraySizes != nullptr); + assert(type.arraySizes != nullptr); + *arraySizes = *type.arraySizes; + } + void copyArraySizes(const TArraySizes& s) + { + // For setting a fresh new set of array sizes, not yet worrying about sharing. + arraySizes = new TArraySizes; + *arraySizes = s; + } + void transferArraySizes(TArraySizes* s) + { + // For setting an already allocated set of sizes that this type can use + // (no copy made). + arraySizes = s; + } + void clearArraySizes() + { + arraySizes = nullptr; + } + + // Add inner array sizes, to any existing sizes, via copy; the + // sizes passed in can still be reused for other purposes. + void copyArrayInnerSizes(const TArraySizes* s) + { + if (s != nullptr) { + if (arraySizes == nullptr) + copyArraySizes(*s); + else + arraySizes->addInnerSizes(*s); + } + } + void changeOuterArraySize(int s) { arraySizes->changeOuterSize(s); } + + // Recursively make the implicit array size the explicit array size. + // Expicit arrays are compile-time or link-time sized, never run-time sized. + // Sometimes, policy calls for an array to be run-time sized even if it was + // never variably indexed: Don't turn a 'skipNonvariablyIndexed' array into + // an explicit array. + void adoptImplicitArraySizes(bool skipNonvariablyIndexed) + { + if (isUnsizedArray() && !(skipNonvariablyIndexed || isArrayVariablyIndexed())) + changeOuterArraySize(getImplicitArraySize()); + // For multi-dim per-view arrays, set unsized inner dimension size to 1 + if (qualifier.isPerView() && arraySizes && arraySizes->isInnerUnsized()) + arraySizes->clearInnerUnsized(); + if (isStruct() && structure->size() > 0) { + int lastMember = (int)structure->size() - 1; + for (int i = 0; i < lastMember; ++i) + (*structure)[i].type->adoptImplicitArraySizes(false); + // implement the "last member of an SSBO" policy + (*structure)[lastMember].type->adoptImplicitArraySizes(getQualifier().storage == EvqBuffer); + } + } + + + void updateTypeParameters(const TType& type) + { + // For when we may already be sharing existing array descriptors, + // keeping the pointers the same, just updating the contents. + assert(typeParameters != nullptr); + assert(type.typeParameters != nullptr); + *typeParameters = *type.typeParameters; + } + void copyTypeParameters(const TArraySizes& s) + { + // For setting a fresh new set of type parameters, not yet worrying about sharing. + typeParameters = new TArraySizes; + *typeParameters = s; + } + void transferTypeParameters(TArraySizes* s) + { + // For setting an already allocated set of sizes that this type can use + // (no copy made). + typeParameters = s; + } + void clearTypeParameters() + { + typeParameters = nullptr; + } + + // Add inner array sizes, to any existing sizes, via copy; the + // sizes passed in can still be reused for other purposes. + void copyTypeParametersInnerSizes(const TArraySizes* s) + { + if (s != nullptr) { + if (typeParameters == nullptr) + copyTypeParameters(*s); + else + typeParameters->addInnerSizes(*s); + } + } + + + + const char* getBasicString() const + { + return TType::getBasicString(basicType); + } + + static const char* getBasicString(TBasicType t) + { + switch (t) { + case EbtFloat: return "float"; + case EbtInt: return "int"; + case EbtUint: return "uint"; + case EbtSampler: return "sampler/image"; +#ifndef GLSLANG_WEB + case EbtVoid: return "void"; + case EbtDouble: return "double"; + case EbtFloat16: return "float16_t"; + case EbtInt8: return "int8_t"; + case EbtUint8: return "uint8_t"; + case EbtInt16: return "int16_t"; + case EbtUint16: return "uint16_t"; + case EbtInt64: return "int64_t"; + case EbtUint64: return "uint64_t"; + case EbtBool: return "bool"; + case EbtAtomicUint: return "atomic_uint"; + case EbtStruct: return "structure"; + case EbtBlock: return "block"; + case EbtAccStruct: return "accelerationStructureNV"; + case EbtRayQuery: return "rayQueryEXT"; + case EbtReference: return "reference"; +#endif + default: return "unknown type"; + } + } + +#ifdef GLSLANG_WEB + TString getCompleteString() const { return ""; } + const char* getStorageQualifierString() const { return ""; } + const char* getBuiltInVariableString() const { return ""; } + const char* getPrecisionQualifierString() const { return ""; } + TString getBasicTypeString() const { return ""; } +#else + TString getCompleteString() const + { + TString typeString; + + const auto appendStr = [&](const char* s) { typeString.append(s); }; + const auto appendUint = [&](unsigned int u) { typeString.append(std::to_string(u).c_str()); }; + const auto appendInt = [&](int i) { typeString.append(std::to_string(i).c_str()); }; + + if (qualifier.hasLayout()) { + // To reduce noise, skip this if the only layout is an xfb_buffer + // with no triggering xfb_offset. + TQualifier noXfbBuffer = qualifier; + noXfbBuffer.layoutXfbBuffer = TQualifier::layoutXfbBufferEnd; + if (noXfbBuffer.hasLayout()) { + appendStr("layout("); + if (qualifier.hasAnyLocation()) { + appendStr(" location="); + appendUint(qualifier.layoutLocation); + if (qualifier.hasComponent()) { + appendStr(" component="); + appendUint(qualifier.layoutComponent); + } + if (qualifier.hasIndex()) { + appendStr(" index="); + appendUint(qualifier.layoutIndex); + } + } + if (qualifier.hasSet()) { + appendStr(" set="); + appendUint(qualifier.layoutSet); + } + if (qualifier.hasBinding()) { + appendStr(" binding="); + appendUint(qualifier.layoutBinding); + } + if (qualifier.hasStream()) { + appendStr(" stream="); + appendUint(qualifier.layoutStream); + } + if (qualifier.hasMatrix()) { + appendStr(" "); + appendStr(TQualifier::getLayoutMatrixString(qualifier.layoutMatrix)); + } + if (qualifier.hasPacking()) { + appendStr(" "); + appendStr(TQualifier::getLayoutPackingString(qualifier.layoutPacking)); + } + if (qualifier.hasOffset()) { + appendStr(" offset="); + appendInt(qualifier.layoutOffset); + } + if (qualifier.hasAlign()) { + appendStr(" align="); + appendInt(qualifier.layoutAlign); + } + if (qualifier.hasFormat()) { + appendStr(" "); + appendStr(TQualifier::getLayoutFormatString(qualifier.layoutFormat)); + } + if (qualifier.hasXfbBuffer() && qualifier.hasXfbOffset()) { + appendStr(" xfb_buffer="); + appendUint(qualifier.layoutXfbBuffer); + } + if (qualifier.hasXfbOffset()) { + appendStr(" xfb_offset="); + appendUint(qualifier.layoutXfbOffset); + } + if (qualifier.hasXfbStride()) { + appendStr(" xfb_stride="); + appendUint(qualifier.layoutXfbStride); + } + if (qualifier.hasAttachment()) { + appendStr(" input_attachment_index="); + appendUint(qualifier.layoutAttachment); + } + if (qualifier.hasSpecConstantId()) { + appendStr(" constant_id="); + appendUint(qualifier.layoutSpecConstantId); + } + if (qualifier.layoutPushConstant) + appendStr(" push_constant"); + if (qualifier.layoutBufferReference) + appendStr(" buffer_reference"); + if (qualifier.hasBufferReferenceAlign()) { + appendStr(" buffer_reference_align="); + appendUint(1u << qualifier.layoutBufferReferenceAlign); + } + + if (qualifier.layoutPassthrough) + appendStr(" passthrough"); + if (qualifier.layoutViewportRelative) + appendStr(" layoutViewportRelative"); + if (qualifier.layoutSecondaryViewportRelativeOffset != -2048) { + appendStr(" layoutSecondaryViewportRelativeOffset="); + appendInt(qualifier.layoutSecondaryViewportRelativeOffset); + } + if (qualifier.layoutShaderRecord) + appendStr(" shaderRecordNV"); + + appendStr(")"); + } + } + + if (qualifier.invariant) + appendStr(" invariant"); + if (qualifier.noContraction) + appendStr(" noContraction"); + if (qualifier.centroid) + appendStr(" centroid"); + if (qualifier.smooth) + appendStr(" smooth"); + if (qualifier.flat) + appendStr(" flat"); + if (qualifier.nopersp) + appendStr(" noperspective"); + if (qualifier.explicitInterp) + appendStr(" __explicitInterpAMD"); + if (qualifier.pervertexNV) + appendStr(" pervertexNV"); + if (qualifier.perPrimitiveNV) + appendStr(" perprimitiveNV"); + if (qualifier.perViewNV) + appendStr(" perviewNV"); + if (qualifier.perTaskNV) + appendStr(" taskNV"); + if (qualifier.patch) + appendStr(" patch"); + if (qualifier.sample) + appendStr(" sample"); + if (qualifier.coherent) + appendStr(" coherent"); + if (qualifier.devicecoherent) + appendStr(" devicecoherent"); + if (qualifier.queuefamilycoherent) + appendStr(" queuefamilycoherent"); + if (qualifier.workgroupcoherent) + appendStr(" workgroupcoherent"); + if (qualifier.subgroupcoherent) + appendStr(" subgroupcoherent"); + if (qualifier.shadercallcoherent) + appendStr(" shadercallcoherent"); + if (qualifier.nonprivate) + appendStr(" nonprivate"); + if (qualifier.volatil) + appendStr(" volatile"); + if (qualifier.restrict) + appendStr(" restrict"); + if (qualifier.readonly) + appendStr(" readonly"); + if (qualifier.writeonly) + appendStr(" writeonly"); + if (qualifier.specConstant) + appendStr(" specialization-constant"); + if (qualifier.nonUniform) + appendStr(" nonuniform"); + appendStr(" "); + appendStr(getStorageQualifierString()); + if (isArray()) { + for(int i = 0; i < (int)arraySizes->getNumDims(); ++i) { + int size = arraySizes->getDimSize(i); + if (size == UnsizedArraySize && i == 0 && arraySizes->isVariablyIndexed()) + appendStr(" runtime-sized array of"); + else { + if (size == UnsizedArraySize) { + appendStr(" unsized"); + if (i == 0) { + appendStr(" "); + appendInt(arraySizes->getImplicitSize()); + } + } else { + appendStr(" "); + appendInt(arraySizes->getDimSize(i)); + } + appendStr("-element array of"); + } + } + } + if (isParameterized()) { + appendStr("<"); + for(int i = 0; i < (int)typeParameters->getNumDims(); ++i) { + appendInt(typeParameters->getDimSize(i)); + if (i != (int)typeParameters->getNumDims() - 1) + appendStr(", "); + } + appendStr(">"); + } + if (qualifier.precision != EpqNone) { + appendStr(" "); + appendStr(getPrecisionQualifierString()); + } + if (isMatrix()) { + appendStr(" "); + appendInt(matrixCols); + appendStr("X"); + appendInt(matrixRows); + appendStr(" matrix of"); + } else if (isVector()) { + appendStr(" "); + appendInt(vectorSize); + appendStr("-component vector of"); + } + + appendStr(" "); + typeString.append(getBasicTypeString()); + + if (qualifier.builtIn != EbvNone) { + appendStr(" "); + appendStr(getBuiltInVariableString()); + } + + // Add struct/block members + if (isStruct() && structure) { + appendStr("{"); + bool hasHiddenMember = true; + for (size_t i = 0; i < structure->size(); ++i) { + if (! (*structure)[i].type->hiddenMember()) { + if (!hasHiddenMember) + appendStr(", "); + typeString.append((*structure)[i].type->getCompleteString()); + typeString.append(" "); + typeString.append((*structure)[i].type->getFieldName()); + hasHiddenMember = false; + } + } + appendStr("}"); + } + + return typeString; + } + + TString getBasicTypeString() const + { + if (basicType == EbtSampler) + return sampler.getString(); + else + return getBasicString(); + } + + const char* getStorageQualifierString() const { return GetStorageQualifierString(qualifier.storage); } + const char* getBuiltInVariableString() const { return GetBuiltInVariableString(qualifier.builtIn); } + const char* getPrecisionQualifierString() const { return GetPrecisionQualifierString(qualifier.precision); } +#endif + + const TTypeList* getStruct() const { assert(isStruct()); return structure; } + void setStruct(TTypeList* s) { assert(isStruct()); structure = s; } + TTypeList* getWritableStruct() const { assert(isStruct()); return structure; } // This should only be used when known to not be sharing with other threads + void setBasicType(const TBasicType& t) { basicType = t; } + + int computeNumComponents() const + { + int components = 0; + + if (getBasicType() == EbtStruct || getBasicType() == EbtBlock) { + for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++) + components += ((*tl).type)->computeNumComponents(); + } else if (matrixCols) + components = matrixCols * matrixRows; + else + components = vectorSize; + + if (arraySizes != nullptr) { + components *= arraySizes->getCumulativeSize(); + } + + return components; + } + + // append this type's mangled name to the passed in 'name' + void appendMangledName(TString& name) const + { + buildMangledName(name); + name += ';' ; + } + + // Do two structure types match? They could be declared independently, + // in different places, but still might satisfy the definition of matching. + // From the spec: + // + // "Structures must have the same name, sequence of type names, and + // type definitions, and member names to be considered the same type. + // This rule applies recursively for nested or embedded types." + // + bool sameStructType(const TType& right) const + { + // Most commonly, they are both nullptr, or the same pointer to the same actual structure + if ((!isStruct() && !right.isStruct()) || + (isStruct() && right.isStruct() && structure == right.structure)) + return true; + + // Both being nullptr was caught above, now they both have to be structures of the same number of elements + if (!isStruct() || !right.isStruct() || + structure->size() != right.structure->size()) + return false; + + // Structure names have to match + if (*typeName != *right.typeName) + return false; + + // Compare the names and types of all the members, which have to match + for (unsigned int i = 0; i < structure->size(); ++i) { + if ((*structure)[i].type->getFieldName() != (*right.structure)[i].type->getFieldName()) + return false; + + if (*(*structure)[i].type != *(*right.structure)[i].type) + return false; + } + + return true; + } + + bool sameReferenceType(const TType& right) const + { + if (isReference() != right.isReference()) + return false; + + if (!isReference() && !right.isReference()) + return true; + + assert(referentType != nullptr); + assert(right.referentType != nullptr); + + if (referentType == right.referentType) + return true; + + return *referentType == *right.referentType; + } + + // See if two types match, in all aspects except arrayness + bool sameElementType(const TType& right) const + { + return basicType == right.basicType && sameElementShape(right); + } + + // See if two type's arrayness match + bool sameArrayness(const TType& right) const + { + return ((arraySizes == nullptr && right.arraySizes == nullptr) || + (arraySizes != nullptr && right.arraySizes != nullptr && *arraySizes == *right.arraySizes)); + } + + // See if two type's arrayness match in everything except their outer dimension + bool sameInnerArrayness(const TType& right) const + { + assert(arraySizes != nullptr && right.arraySizes != nullptr); + return arraySizes->sameInnerArrayness(*right.arraySizes); + } + + // See if two type's parameters match + bool sameTypeParameters(const TType& right) const + { + return ((typeParameters == nullptr && right.typeParameters == nullptr) || + (typeParameters != nullptr && right.typeParameters != nullptr && *typeParameters == *right.typeParameters)); + } + + // See if two type's elements match in all ways except basic type + bool sameElementShape(const TType& right) const + { + return sampler == right.sampler && + vectorSize == right.vectorSize && + matrixCols == right.matrixCols && + matrixRows == right.matrixRows && + vector1 == right.vector1 && + isCoopMat() == right.isCoopMat() && + sameStructType(right) && + sameReferenceType(right); + } + + // See if a cooperative matrix type parameter with unspecified parameters is + // an OK function parameter + bool coopMatParameterOK(const TType& right) const + { + return isCoopMat() && right.isCoopMat() && (getBasicType() == right.getBasicType()) && + typeParameters == nullptr && right.typeParameters != nullptr; + } + + bool sameCoopMatBaseType(const TType &right) const { + bool rv = coopmat && right.coopmat; + if (getBasicType() == EbtFloat || getBasicType() == EbtFloat16) + rv = right.getBasicType() == EbtFloat || right.getBasicType() == EbtFloat16; + else if (getBasicType() == EbtUint || getBasicType() == EbtUint8) + rv = right.getBasicType() == EbtUint || right.getBasicType() == EbtUint8; + else if (getBasicType() == EbtInt || getBasicType() == EbtInt8) + rv = right.getBasicType() == EbtInt || right.getBasicType() == EbtInt8; + else + rv = false; + return rv; + } + + + // See if two types match in all ways (just the actual type, not qualification) + bool operator==(const TType& right) const + { + return sameElementType(right) && sameArrayness(right) && sameTypeParameters(right); + } + + bool operator!=(const TType& right) const + { + return ! operator==(right); + } + + unsigned int getBufferReferenceAlignment() const + { +#ifndef GLSLANG_WEB + if (getBasicType() == glslang::EbtReference) { + return getReferentType()->getQualifier().hasBufferReferenceAlign() ? + (1u << getReferentType()->getQualifier().layoutBufferReferenceAlign) : 16u; + } +#endif + return 0; + } + +protected: + // Require consumer to pick between deep copy and shallow copy. + TType(const TType& type); + TType& operator=(const TType& type); + + // Recursively copy a type graph, while preserving the graph-like + // quality. That is, don't make more than one copy of a structure that + // gets reused multiple times in the type graph. + void deepCopy(const TType& copyOf, TMap& copiedMap) + { + shallowCopy(copyOf); + + if (copyOf.arraySizes) { + arraySizes = new TArraySizes; + *arraySizes = *copyOf.arraySizes; + } + + if (copyOf.typeParameters) { + typeParameters = new TArraySizes; + *typeParameters = *copyOf.typeParameters; + } + + if (copyOf.isStruct() && copyOf.structure) { + auto prevCopy = copiedMap.find(copyOf.structure); + if (prevCopy != copiedMap.end()) + structure = prevCopy->second; + else { + structure = new TTypeList; + copiedMap[copyOf.structure] = structure; + for (unsigned int i = 0; i < copyOf.structure->size(); ++i) { + TTypeLoc typeLoc; + typeLoc.loc = (*copyOf.structure)[i].loc; + typeLoc.type = new TType(); + typeLoc.type->deepCopy(*(*copyOf.structure)[i].type, copiedMap); + structure->push_back(typeLoc); + } + } + } + + if (copyOf.fieldName) + fieldName = NewPoolTString(copyOf.fieldName->c_str()); + if (copyOf.typeName) + typeName = NewPoolTString(copyOf.typeName->c_str()); + } + + + void buildMangledName(TString&) const; + + TBasicType basicType : 8; + int vectorSize : 4; // 1 means either scalar or 1-component vector; see vector1 to disambiguate. + int matrixCols : 4; + int matrixRows : 4; + bool vector1 : 1; // Backward-compatible tracking of a 1-component vector distinguished from a scalar. + // GLSL 4.5 never has a 1-component vector; so this will always be false until such + // functionality is added. + // HLSL does have a 1-component vectors, so this will be true to disambiguate + // from a scalar. + bool coopmat : 1; + TQualifier qualifier; + + TArraySizes* arraySizes; // nullptr unless an array; can be shared across types + // A type can't be both a structure (EbtStruct/EbtBlock) and a reference (EbtReference), so + // conserve space by making these a union + union { + TTypeList* structure; // invalid unless this is a struct; can be shared across types + TType *referentType; // invalid unless this is an EbtReference + }; + TString *fieldName; // for structure field names + TString *typeName; // for structure type name + TSampler sampler; + TArraySizes* typeParameters;// nullptr unless a parameterized type; can be shared across types +}; + +} // end namespace glslang + +#endif // _TYPES_INCLUDED_ diff --git a/android/armeabi-v7a/include/glslang/Include/arrays.h b/android/armeabi-v7a/include/glslang/Include/arrays.h new file mode 100644 index 00000000..7f047d9f --- /dev/null +++ b/android/armeabi-v7a/include/glslang/Include/arrays.h @@ -0,0 +1,341 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +// +// Implement types for tracking GLSL arrays, arrays of arrays, etc. +// + +#ifndef _ARRAYS_INCLUDED +#define _ARRAYS_INCLUDED + +#include + +namespace glslang { + +// This is used to mean there is no size yet (unsized), it is waiting to get a size from somewhere else. +const int UnsizedArraySize = 0; + +class TIntermTyped; +extern bool SameSpecializationConstants(TIntermTyped*, TIntermTyped*); + +// Specialization constants need both a nominal size and a node that defines +// the specialization constant being used. Array types are the same when their +// size and specialization constant nodes are the same. +struct TArraySize { + unsigned int size; + TIntermTyped* node; // nullptr means no specialization constant node + bool operator==(const TArraySize& rhs) const + { + if (size != rhs.size) + return false; + if (node == nullptr || rhs.node == nullptr) + return node == rhs.node; + + return SameSpecializationConstants(node, rhs.node); + } +}; + +// +// TSmallArrayVector is used as the container for the set of sizes in TArraySizes. +// It has generic-container semantics, while TArraySizes has array-of-array semantics. +// That is, TSmallArrayVector should be more focused on mechanism and TArraySizes on policy. +// +struct TSmallArrayVector { + // + // TODO: memory: TSmallArrayVector is intended to be smaller. + // Almost all arrays could be handled by two sizes each fitting + // in 16 bits, needing a real vector only in the cases where there + // are more than 3 sizes or a size needing more than 16 bits. + // + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + TSmallArrayVector() : sizes(nullptr) { } + virtual ~TSmallArrayVector() { dealloc(); } + + // For breaking into two non-shared copies, independently modifiable. + TSmallArrayVector& operator=(const TSmallArrayVector& from) + { + if (from.sizes == nullptr) + sizes = nullptr; + else { + alloc(); + *sizes = *from.sizes; + } + + return *this; + } + + int size() const + { + if (sizes == nullptr) + return 0; + return (int)sizes->size(); + } + + unsigned int frontSize() const + { + assert(sizes != nullptr && sizes->size() > 0); + return sizes->front().size; + } + + TIntermTyped* frontNode() const + { + assert(sizes != nullptr && sizes->size() > 0); + return sizes->front().node; + } + + void changeFront(unsigned int s) + { + assert(sizes != nullptr); + // this should only happen for implicitly sized arrays, not specialization constants + assert(sizes->front().node == nullptr); + sizes->front().size = s; + } + + void push_back(unsigned int e, TIntermTyped* n) + { + alloc(); + TArraySize pair = { e, n }; + sizes->push_back(pair); + } + + void push_back(const TSmallArrayVector& newDims) + { + alloc(); + sizes->insert(sizes->end(), newDims.sizes->begin(), newDims.sizes->end()); + } + + void pop_front() + { + assert(sizes != nullptr && sizes->size() > 0); + if (sizes->size() == 1) + dealloc(); + else + sizes->erase(sizes->begin()); + } + + // 'this' should currently not be holding anything, and copyNonFront + // will make it hold a copy of all but the first element of rhs. + // (This would be useful for making a type that is dereferenced by + // one dimension.) + void copyNonFront(const TSmallArrayVector& rhs) + { + assert(sizes == nullptr); + if (rhs.size() > 1) { + alloc(); + sizes->insert(sizes->begin(), rhs.sizes->begin() + 1, rhs.sizes->end()); + } + } + + unsigned int getDimSize(int i) const + { + assert(sizes != nullptr && (int)sizes->size() > i); + return (*sizes)[i].size; + } + + void setDimSize(int i, unsigned int size) const + { + assert(sizes != nullptr && (int)sizes->size() > i); + assert((*sizes)[i].node == nullptr); + (*sizes)[i].size = size; + } + + TIntermTyped* getDimNode(int i) const + { + assert(sizes != nullptr && (int)sizes->size() > i); + return (*sizes)[i].node; + } + + bool operator==(const TSmallArrayVector& rhs) const + { + if (sizes == nullptr && rhs.sizes == nullptr) + return true; + if (sizes == nullptr || rhs.sizes == nullptr) + return false; + return *sizes == *rhs.sizes; + } + bool operator!=(const TSmallArrayVector& rhs) const { return ! operator==(rhs); } + +protected: + TSmallArrayVector(const TSmallArrayVector&); + + void alloc() + { + if (sizes == nullptr) + sizes = new TVector; + } + void dealloc() + { + delete sizes; + sizes = nullptr; + } + + TVector* sizes; // will either hold such a pointer, or in the future, hold the two array sizes +}; + +// +// Represent an array, or array of arrays, to arbitrary depth. This is not +// done through a hierarchy of types in a type tree, rather all contiguous arrayness +// in the type hierarchy is localized into this single cumulative object. +// +// The arrayness in TTtype is a pointer, so that it can be non-allocated and zero +// for the vast majority of types that are non-array types. +// +// Order Policy: these are all identical: +// - left to right order within a contiguous set of ...[..][..][..]... in the source language +// - index order 0, 1, 2, ... within the 'sizes' member below +// - outer-most to inner-most +// +struct TArraySizes { + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + TArraySizes() : implicitArraySize(1), variablyIndexed(false) { } + + // For breaking into two non-shared copies, independently modifiable. + TArraySizes& operator=(const TArraySizes& from) + { + implicitArraySize = from.implicitArraySize; + variablyIndexed = from.variablyIndexed; + sizes = from.sizes; + + return *this; + } + + // translate from array-of-array semantics to container semantics + int getNumDims() const { return sizes.size(); } + int getDimSize(int dim) const { return sizes.getDimSize(dim); } + TIntermTyped* getDimNode(int dim) const { return sizes.getDimNode(dim); } + void setDimSize(int dim, int size) { sizes.setDimSize(dim, size); } + int getOuterSize() const { return sizes.frontSize(); } + TIntermTyped* getOuterNode() const { return sizes.frontNode(); } + int getCumulativeSize() const + { + int size = 1; + for (int d = 0; d < sizes.size(); ++d) { + // this only makes sense in paths that have a known array size + assert(sizes.getDimSize(d) != UnsizedArraySize); + size *= sizes.getDimSize(d); + } + return size; + } + void addInnerSize() { addInnerSize((unsigned)UnsizedArraySize); } + void addInnerSize(int s) { addInnerSize((unsigned)s, nullptr); } + void addInnerSize(int s, TIntermTyped* n) { sizes.push_back((unsigned)s, n); } + void addInnerSize(TArraySize pair) { + sizes.push_back(pair.size, pair.node); + } + void addInnerSizes(const TArraySizes& s) { sizes.push_back(s.sizes); } + void changeOuterSize(int s) { sizes.changeFront((unsigned)s); } + int getImplicitSize() const { return implicitArraySize; } + void updateImplicitSize(int s) { implicitArraySize = std::max(implicitArraySize, s); } + bool isInnerUnsized() const + { + for (int d = 1; d < sizes.size(); ++d) { + if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize) + return true; + } + + return false; + } + bool clearInnerUnsized() + { + for (int d = 1; d < sizes.size(); ++d) { + if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize) + setDimSize(d, 1); + } + + return false; + } + bool isInnerSpecialization() const + { + for (int d = 1; d < sizes.size(); ++d) { + if (sizes.getDimNode(d) != nullptr) + return true; + } + + return false; + } + bool isOuterSpecialization() + { + return sizes.getDimNode(0) != nullptr; + } + + bool hasUnsized() const { return getOuterSize() == UnsizedArraySize || isInnerUnsized(); } + bool isSized() const { return getOuterSize() != UnsizedArraySize; } + void dereference() { sizes.pop_front(); } + void copyDereferenced(const TArraySizes& rhs) + { + assert(sizes.size() == 0); + if (rhs.sizes.size() > 1) + sizes.copyNonFront(rhs.sizes); + } + + bool sameInnerArrayness(const TArraySizes& rhs) const + { + if (sizes.size() != rhs.sizes.size()) + return false; + + for (int d = 1; d < sizes.size(); ++d) { + if (sizes.getDimSize(d) != rhs.sizes.getDimSize(d) || + sizes.getDimNode(d) != rhs.sizes.getDimNode(d)) + return false; + } + + return true; + } + + void setVariablyIndexed() { variablyIndexed = true; } + bool isVariablyIndexed() const { return variablyIndexed; } + + bool operator==(const TArraySizes& rhs) const { return sizes == rhs.sizes; } + bool operator!=(const TArraySizes& rhs) const { return sizes != rhs.sizes; } + +protected: + TSmallArrayVector sizes; + + TArraySizes(const TArraySizes&); + + // For tracking maximum referenced compile-time constant index. + // Applies only to the outer-most dimension. Potentially becomes + // the implicit size of the array, if not variably indexed and + // otherwise legal. + int implicitArraySize; + bool variablyIndexed; // true if array is indexed with a non compile-time constant +}; + +} // end namespace glslang + +#endif // _ARRAYS_INCLUDED_ diff --git a/android/armeabi-v7a/include/glslang/Include/glslang_c_interface.h b/android/armeabi-v7a/include/glslang/Include/glslang_c_interface.h new file mode 100644 index 00000000..5a450e0e --- /dev/null +++ b/android/armeabi-v7a/include/glslang/Include/glslang_c_interface.h @@ -0,0 +1,232 @@ +/** + This code is based on the glslang_c_interface implementation by Viktor Latypov +**/ + +/** +BSD 2-Clause License + +Copyright (c) 2019, Viktor Latypov +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**/ + +#ifndef GLSLANG_C_IFACE_H_INCLUDED +#define GLSLANG_C_IFACE_H_INCLUDED + +#include +#include + +#include "glslang_c_shader_types.h" + +typedef struct glslang_shader_s glslang_shader_t; +typedef struct glslang_program_s glslang_program_t; + +/* TLimits counterpart */ +typedef struct glslang_limits_s { + bool non_inductive_for_loops; + bool while_loops; + bool do_while_loops; + bool general_uniform_indexing; + bool general_attribute_matrix_vector_indexing; + bool general_varying_indexing; + bool general_sampler_indexing; + bool general_variable_indexing; + bool general_constant_matrix_vector_indexing; +} glslang_limits_t; + +/* TBuiltInResource counterpart */ +typedef struct glslang_resource_s { + int max_lights; + int max_clip_planes; + int max_texture_units; + int max_texture_coords; + int max_vertex_attribs; + int max_vertex_uniform_components; + int max_varying_floats; + int max_vertex_texture_image_units; + int max_combined_texture_image_units; + int max_texture_image_units; + int max_fragment_uniform_components; + int max_draw_buffers; + int max_vertex_uniform_vectors; + int max_varying_vectors; + int max_fragment_uniform_vectors; + int max_vertex_output_vectors; + int max_fragment_input_vectors; + int min_program_texel_offset; + int max_program_texel_offset; + int max_clip_distances; + int max_compute_work_group_count_x; + int max_compute_work_group_count_y; + int max_compute_work_group_count_z; + int max_compute_work_group_size_x; + int max_compute_work_group_size_y; + int max_compute_work_group_size_z; + int max_compute_uniform_components; + int max_compute_texture_image_units; + int max_compute_image_uniforms; + int max_compute_atomic_counters; + int max_compute_atomic_counter_buffers; + int max_varying_components; + int max_vertex_output_components; + int max_geometry_input_components; + int max_geometry_output_components; + int max_fragment_input_components; + int max_image_units; + int max_combined_image_units_and_fragment_outputs; + int max_combined_shader_output_resources; + int max_image_samples; + int max_vertex_image_uniforms; + int max_tess_control_image_uniforms; + int max_tess_evaluation_image_uniforms; + int max_geometry_image_uniforms; + int max_fragment_image_uniforms; + int max_combined_image_uniforms; + int max_geometry_texture_image_units; + int max_geometry_output_vertices; + int max_geometry_total_output_components; + int max_geometry_uniform_components; + int max_geometry_varying_components; + int max_tess_control_input_components; + int max_tess_control_output_components; + int max_tess_control_texture_image_units; + int max_tess_control_uniform_components; + int max_tess_control_total_output_components; + int max_tess_evaluation_input_components; + int max_tess_evaluation_output_components; + int max_tess_evaluation_texture_image_units; + int max_tess_evaluation_uniform_components; + int max_tess_patch_components; + int max_patch_vertices; + int max_tess_gen_level; + int max_viewports; + int max_vertex_atomic_counters; + int max_tess_control_atomic_counters; + int max_tess_evaluation_atomic_counters; + int max_geometry_atomic_counters; + int max_fragment_atomic_counters; + int max_combined_atomic_counters; + int max_atomic_counter_bindings; + int max_vertex_atomic_counter_buffers; + int max_tess_control_atomic_counter_buffers; + int max_tess_evaluation_atomic_counter_buffers; + int max_geometry_atomic_counter_buffers; + int max_fragment_atomic_counter_buffers; + int max_combined_atomic_counter_buffers; + int max_atomic_counter_buffer_size; + int max_transform_feedback_buffers; + int max_transform_feedback_interleaved_components; + int max_cull_distances; + int max_combined_clip_and_cull_distances; + int max_samples; + int max_mesh_output_vertices_nv; + int max_mesh_output_primitives_nv; + int max_mesh_work_group_size_x_nv; + int max_mesh_work_group_size_y_nv; + int max_mesh_work_group_size_z_nv; + int max_task_work_group_size_x_nv; + int max_task_work_group_size_y_nv; + int max_task_work_group_size_z_nv; + int max_mesh_view_count_nv; + + glslang_limits_t limits; +} glslang_resource_t; + +typedef struct glslang_input_s { + glslang_source_t language; + glslang_stage_t stage; + glslang_client_t client; + glslang_target_client_version_t client_version; + glslang_target_language_t target_language; + glslang_target_language_version_t target_language_version; + /** Shader source code */ + const char* code; + int default_version; + glslang_profile_t default_profile; + int force_default_version_and_profile; + int forward_compatible; + glslang_messages_t messages; + const glslang_resource_t* resource; +} glslang_input_t; + +/* Inclusion result structure allocated by C include_local/include_system callbacks */ +typedef struct glsl_include_result_s { + /* Header file name or NULL if inclusion failed */ + const char* header_name; + + /* Header contents or NULL */ + const char* header_data; + size_t header_length; + +} glsl_include_result_t; + +/* Callback for local file inclusion */ +typedef glsl_include_result_t* (*glsl_include_local_func)(void* ctx, const char* header_name, const char* includer_name, + size_t include_depth); + +/* Callback for system file inclusion */ +typedef glsl_include_result_t* (*glsl_include_system_func)(void* ctx, const char* header_name, + const char* includer_name, size_t include_depth); + +/* Callback for include result destruction */ +typedef int (*glsl_free_include_result_func)(void* ctx, glsl_include_result_t* result); + +/* Collection of callbacks for GLSL preprocessor */ +typedef struct glsl_include_callbacks_s { + glsl_include_system_func include_system; + glsl_include_local_func include_local; + glsl_free_include_result_func free_include_result; +} glsl_include_callbacks_t; + +#ifdef __cplusplus +extern "C" { +#endif + +int glslang_initialize_process(); +void glslang_finalize_process(); + +glslang_shader_t* glslang_shader_create(const glslang_input_t* input); +void glslang_shader_delete(glslang_shader_t* shader); +int glslang_shader_preprocess(glslang_shader_t* shader, const glslang_input_t* input); +int glslang_shader_parse(glslang_shader_t* shader, const glslang_input_t* input); +const char* glslang_shader_get_preprocessed_code(glslang_shader_t* shader); +const char* glslang_shader_get_info_log(glslang_shader_t* shader); +const char* glslang_shader_get_info_debug_log(glslang_shader_t* shader); + +glslang_program_t* glslang_program_create(); +void glslang_program_delete(glslang_program_t* program); +void glslang_program_add_shader(glslang_program_t* program, glslang_shader_t* shader); +int glslang_program_link(glslang_program_t* program, int messages); // glslang_messages_t +void glslang_program_SPIRV_generate(glslang_program_t* program, glslang_stage_t stage); +size_t glslang_program_SPIRV_get_size(glslang_program_t* program); +void glslang_program_SPIRV_get(glslang_program_t* program, unsigned int*); +unsigned int* glslang_program_SPIRV_get_ptr(glslang_program_t* program); +const char* glslang_program_SPIRV_get_messages(glslang_program_t* program); +const char* glslang_program_get_info_log(glslang_program_t* program); +const char* glslang_program_get_info_debug_log(glslang_program_t* program); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifdef GLSLANG_C_IFACE_INCLUDED */ diff --git a/android/armeabi-v7a/include/glslang/Include/glslang_c_shader_types.h b/android/armeabi-v7a/include/glslang/Include/glslang_c_shader_types.h new file mode 100644 index 00000000..769f4c4a --- /dev/null +++ b/android/armeabi-v7a/include/glslang/Include/glslang_c_shader_types.h @@ -0,0 +1,182 @@ +/** + This code is based on the glslang_c_interface implementation by Viktor Latypov +**/ + +/** +BSD 2-Clause License + +Copyright (c) 2019, Viktor Latypov +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**/ + +#ifndef C_SHADER_TYPES_H_INCLUDED +#define C_SHADER_TYPES_H_INCLUDED + +#define LAST_ELEMENT_MARKER(x) x + +/* EShLanguage counterpart */ +typedef enum { + GLSLANG_STAGE_VERTEX, + GLSLANG_STAGE_TESSCONTROL, + GLSLANG_STAGE_TESSEVALUATION, + GLSLANG_STAGE_GEOMETRY, + GLSLANG_STAGE_FRAGMENT, + GLSLANG_STAGE_COMPUTE, + GLSLANG_STAGE_RAYGEN_NV, + GLSLANG_STAGE_INTERSECT_NV, + GLSLANG_STAGE_ANYHIT_NV, + GLSLANG_STAGE_CLOSESTHIT_NV, + GLSLANG_STAGE_MISS_NV, + GLSLANG_STAGE_CALLABLE_NV, + GLSLANG_STAGE_TASK_NV, + GLSLANG_STAGE_MESH_NV, + LAST_ELEMENT_MARKER(GLSLANG_STAGE_COUNT), +} glslang_stage_t; // would be better as stage, but this is ancient now + +/* EShLanguageMask counterpart */ +typedef enum { + GLSLANG_STAGE_VERTEX_MASK = (1 << GLSLANG_STAGE_VERTEX), + GLSLANG_STAGE_TESSCONTROL_MASK = (1 << GLSLANG_STAGE_TESSCONTROL), + GLSLANG_STAGE_TESSEVALUATION_MASK = (1 << GLSLANG_STAGE_TESSEVALUATION), + GLSLANG_STAGE_GEOMETRY_MASK = (1 << GLSLANG_STAGE_GEOMETRY), + GLSLANG_STAGE_FRAGMENT_MASK = (1 << GLSLANG_STAGE_FRAGMENT), + GLSLANG_STAGE_COMPUTE_MASK = (1 << GLSLANG_STAGE_COMPUTE), + GLSLANG_STAGE_RAYGEN_NV_MASK = (1 << GLSLANG_STAGE_RAYGEN_NV), + GLSLANG_STAGE_INTERSECT_NV_MASK = (1 << GLSLANG_STAGE_INTERSECT_NV), + GLSLANG_STAGE_ANYHIT_NV_MASK = (1 << GLSLANG_STAGE_ANYHIT_NV), + GLSLANG_STAGE_CLOSESTHIT_NV_MASK = (1 << GLSLANG_STAGE_CLOSESTHIT_NV), + GLSLANG_STAGE_MISS_NV_MASK = (1 << GLSLANG_STAGE_MISS_NV), + GLSLANG_STAGE_CALLABLE_NV_MASK = (1 << GLSLANG_STAGE_CALLABLE_NV), + GLSLANG_STAGE_TASK_NV_MASK = (1 << GLSLANG_STAGE_TASK_NV), + GLSLANG_STAGE_MESH_NV_MASK = (1 << GLSLANG_STAGE_MESH_NV), + LAST_ELEMENT_MARKER(GLSLANG_STAGE_MASK_COUNT), +} glslang_stage_mask_t; + +/* EShSource counterpart */ +typedef enum { + GLSLANG_SOURCE_NONE, + GLSLANG_SOURCE_GLSL, + GLSLANG_SOURCE_HLSL, + LAST_ELEMENT_MARKER(GLSLANG_SOURCE_COUNT), +} glslang_source_t; + +/* EShClient counterpart */ +typedef enum { + GLSLANG_CLIENT_NONE, + GLSLANG_CLIENT_VULKAN, + GLSLANG_CLIENT_OPENGL, + LAST_ELEMENT_MARKER(GLSLANG_CLIENT_COUNT), +} glslang_client_t; + +/* EShTargetLanguage counterpart */ +typedef enum { + GLSLANG_TARGET_NONE, + GLSLANG_TARGET_SPV, + LAST_ELEMENT_MARKER(GLSLANG_TARGET_COUNT), +} glslang_target_language_t; + +/* SH_TARGET_ClientVersion counterpart */ +typedef enum { + GLSLANG_TARGET_VULKAN_1_0 = (1 << 22), + GLSLANG_TARGET_VULKAN_1_1 = (1 << 22) | (1 << 12), + GLSLANG_TARGET_OPENGL_450 = 450, + LAST_ELEMENT_MARKER(GLSLANG_TARGET_CLIENT_VERSION_COUNT), +} glslang_target_client_version_t; + +/* SH_TARGET_LanguageVersion counterpart */ +typedef enum { + GLSLANG_TARGET_SPV_1_0 = (1 << 16), + GLSLANG_TARGET_SPV_1_1 = (1 << 16) | (1 << 8), + GLSLANG_TARGET_SPV_1_2 = (1 << 16) | (2 << 8), + GLSLANG_TARGET_SPV_1_3 = (1 << 16) | (3 << 8), + GLSLANG_TARGET_SPV_1_4 = (1 << 16) | (4 << 8), + GLSLANG_TARGET_SPV_1_5 = (1 << 16) | (5 << 8), + LAST_ELEMENT_MARKER(GLSLANG_TARGET_LANGUAGE_VERSION_COUNT), +} glslang_target_language_version_t; + +/* EShExecutable counterpart */ +typedef enum { GLSLANG_EX_VERTEX_FRAGMENT, GLSLANG_EX_FRAGMENT } glslang_executable_t; + +/* EShOptimizationLevel counterpart */ +typedef enum { + GLSLANG_OPT_NO_GENERATION, + GLSLANG_OPT_NONE, + GLSLANG_OPT_SIMPLE, + GLSLANG_OPT_FULL, + LAST_ELEMENT_MARKER(GLSLANG_OPT_LEVEL_COUNT), +} glslang_optimization_level_t; + +/* EShTextureSamplerTransformMode counterpart */ +typedef enum { + GLSLANG_TEX_SAMP_TRANS_KEEP, + GLSLANG_TEX_SAMP_TRANS_UPGRADE_TEXTURE_REMOVE_SAMPLER, + LAST_ELEMENT_MARKER(GLSLANG_TEX_SAMP_TRANS_COUNT), +} glslang_texture_sampler_transform_mode_t; + +/* EShMessages counterpart */ +typedef enum { + GLSLANG_MSG_DEFAULT_BIT = 0, + GLSLANG_MSG_RELAXED_ERRORS_BIT = (1 << 0), + GLSLANG_MSG_SUPPRESS_WARNINGS_BIT = (1 << 1), + GLSLANG_MSG_AST_BIT = (1 << 2), + GLSLANG_MSG_SPV_RULES_BIT = (1 << 3), + GLSLANG_MSG_VULKAN_RULES_BIT = (1 << 4), + GLSLANG_MSG_ONLY_PREPROCESSOR_BIT = (1 << 5), + GLSLANG_MSG_READ_HLSL_BIT = (1 << 6), + GLSLANG_MSG_CASCADING_ERRORS_BIT = (1 << 7), + GLSLANG_MSG_KEEP_UNCALLED_BIT = (1 << 8), + GLSLANG_MSG_HLSL_OFFSETS_BIT = (1 << 9), + GLSLANG_MSG_DEBUG_INFO_BIT = (1 << 10), + GLSLANG_MSG_HLSL_ENABLE_16BIT_TYPES_BIT = (1 << 11), + GLSLANG_MSG_HLSL_LEGALIZATION_BIT = (1 << 12), + GLSLANG_MSG_HLSL_DX9_COMPATIBLE_BIT = (1 << 13), + GLSLANG_MSG_BUILTIN_SYMBOL_TABLE_BIT = (1 << 14), + LAST_ELEMENT_MARKER(GLSLANG_MSG_COUNT), +} glslang_messages_t; + +/* EShReflectionOptions counterpart */ +typedef enum { + GLSLANG_REFLECTION_DEFAULT_BIT = 0, + GLSLANG_REFLECTION_STRICT_ARRAY_SUFFIX_BIT = (1 << 0), + GLSLANG_REFLECTION_BASIC_ARRAY_SUFFIX_BIT = (1 << 1), + GLSLANG_REFLECTION_INTERMEDIATE_IOO_BIT = (1 << 2), + GLSLANG_REFLECTION_SEPARATE_BUFFERS_BIT = (1 << 3), + GLSLANG_REFLECTION_ALL_BLOCK_VARIABLES_BIT = (1 << 4), + GLSLANG_REFLECTION_UNWRAP_IO_BLOCKS_BIT = (1 << 5), + LAST_ELEMENT_MARKER(GLSLANG_REFLECTION_COUNT), +} glslang_reflection_options_t; + +/* EProfile counterpart (from Versions.h) */ +typedef enum { + GLSLANG_BAD_PROFILE = 0, + GLSLANG_NO_PROFILE = (1 << 0), + GLSLANG_CORE_PROFILE = (1 << 1), + GLSLANG_COMPATIBILITY_PROFILE = (1 << 2), + GLSLANG_ES_PROFILE = (1 << 3), + LAST_ELEMENT_MARKER(GLSLANG_PROFILE_COUNT), +} glslang_profile_t; + +#undef LAST_ELEMENT_MARKER + +#endif diff --git a/android/armeabi-v7a/include/glslang/Include/intermediate.h b/android/armeabi-v7a/include/glslang/Include/intermediate.h new file mode 100644 index 00000000..bf12fcf8 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/Include/intermediate.h @@ -0,0 +1,1805 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2016 LunarG, Inc. +// Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +// +// Definition of the in-memory high-level intermediate representation +// of shaders. This is a tree that parser creates. +// +// Nodes in the tree are defined as a hierarchy of classes derived from +// TIntermNode. Each is a node in a tree. There is no preset branching factor; +// each node can have it's own type of list of children. +// + +#ifndef __INTERMEDIATE_H +#define __INTERMEDIATE_H + +#if defined(_MSC_VER) && _MSC_VER >= 1900 + #pragma warning(disable : 4464) // relative include path contains '..' + #pragma warning(disable : 5026) // 'glslang::TIntermUnary': move constructor was implicitly defined as deleted +#endif + +#include "../Include/Common.h" +#include "../Include/Types.h" +#include "../Include/ConstantUnion.h" + +namespace glslang { + +class TIntermediate; + +// +// Operators used by the high-level (parse tree) representation. +// +enum TOperator { + EOpNull, // if in a node, should only mean a node is still being built + EOpSequence, // denotes a list of statements, or parameters, etc. + EOpLinkerObjects, // for aggregate node of objects the linker may need, if not reference by the rest of the AST + EOpFunctionCall, + EOpFunction, // For function definition + EOpParameters, // an aggregate listing the parameters to a function + + // + // Unary operators + // + + EOpNegative, + EOpLogicalNot, + EOpVectorLogicalNot, + EOpBitwiseNot, + + EOpPostIncrement, + EOpPostDecrement, + EOpPreIncrement, + EOpPreDecrement, + + EOpCopyObject, + + // (u)int* -> bool + EOpConvInt8ToBool, + EOpConvUint8ToBool, + EOpConvInt16ToBool, + EOpConvUint16ToBool, + EOpConvIntToBool, + EOpConvUintToBool, + EOpConvInt64ToBool, + EOpConvUint64ToBool, + + // float* -> bool + EOpConvFloat16ToBool, + EOpConvFloatToBool, + EOpConvDoubleToBool, + + // bool -> (u)int* + EOpConvBoolToInt8, + EOpConvBoolToUint8, + EOpConvBoolToInt16, + EOpConvBoolToUint16, + EOpConvBoolToInt, + EOpConvBoolToUint, + EOpConvBoolToInt64, + EOpConvBoolToUint64, + + // bool -> float* + EOpConvBoolToFloat16, + EOpConvBoolToFloat, + EOpConvBoolToDouble, + + // int8_t -> (u)int* + EOpConvInt8ToInt16, + EOpConvInt8ToInt, + EOpConvInt8ToInt64, + EOpConvInt8ToUint8, + EOpConvInt8ToUint16, + EOpConvInt8ToUint, + EOpConvInt8ToUint64, + + // uint8_t -> (u)int* + EOpConvUint8ToInt8, + EOpConvUint8ToInt16, + EOpConvUint8ToInt, + EOpConvUint8ToInt64, + EOpConvUint8ToUint16, + EOpConvUint8ToUint, + EOpConvUint8ToUint64, + + // int8_t -> float* + EOpConvInt8ToFloat16, + EOpConvInt8ToFloat, + EOpConvInt8ToDouble, + + // uint8_t -> float* + EOpConvUint8ToFloat16, + EOpConvUint8ToFloat, + EOpConvUint8ToDouble, + + // int16_t -> (u)int* + EOpConvInt16ToInt8, + EOpConvInt16ToInt, + EOpConvInt16ToInt64, + EOpConvInt16ToUint8, + EOpConvInt16ToUint16, + EOpConvInt16ToUint, + EOpConvInt16ToUint64, + + // uint16_t -> (u)int* + EOpConvUint16ToInt8, + EOpConvUint16ToInt16, + EOpConvUint16ToInt, + EOpConvUint16ToInt64, + EOpConvUint16ToUint8, + EOpConvUint16ToUint, + EOpConvUint16ToUint64, + + // int16_t -> float* + EOpConvInt16ToFloat16, + EOpConvInt16ToFloat, + EOpConvInt16ToDouble, + + // uint16_t -> float* + EOpConvUint16ToFloat16, + EOpConvUint16ToFloat, + EOpConvUint16ToDouble, + + // int32_t -> (u)int* + EOpConvIntToInt8, + EOpConvIntToInt16, + EOpConvIntToInt64, + EOpConvIntToUint8, + EOpConvIntToUint16, + EOpConvIntToUint, + EOpConvIntToUint64, + + // uint32_t -> (u)int* + EOpConvUintToInt8, + EOpConvUintToInt16, + EOpConvUintToInt, + EOpConvUintToInt64, + EOpConvUintToUint8, + EOpConvUintToUint16, + EOpConvUintToUint64, + + // int32_t -> float* + EOpConvIntToFloat16, + EOpConvIntToFloat, + EOpConvIntToDouble, + + // uint32_t -> float* + EOpConvUintToFloat16, + EOpConvUintToFloat, + EOpConvUintToDouble, + + // int64_t -> (u)int* + EOpConvInt64ToInt8, + EOpConvInt64ToInt16, + EOpConvInt64ToInt, + EOpConvInt64ToUint8, + EOpConvInt64ToUint16, + EOpConvInt64ToUint, + EOpConvInt64ToUint64, + + // uint64_t -> (u)int* + EOpConvUint64ToInt8, + EOpConvUint64ToInt16, + EOpConvUint64ToInt, + EOpConvUint64ToInt64, + EOpConvUint64ToUint8, + EOpConvUint64ToUint16, + EOpConvUint64ToUint, + + // int64_t -> float* + EOpConvInt64ToFloat16, + EOpConvInt64ToFloat, + EOpConvInt64ToDouble, + + // uint64_t -> float* + EOpConvUint64ToFloat16, + EOpConvUint64ToFloat, + EOpConvUint64ToDouble, + + // float16_t -> (u)int* + EOpConvFloat16ToInt8, + EOpConvFloat16ToInt16, + EOpConvFloat16ToInt, + EOpConvFloat16ToInt64, + EOpConvFloat16ToUint8, + EOpConvFloat16ToUint16, + EOpConvFloat16ToUint, + EOpConvFloat16ToUint64, + + // float16_t -> float* + EOpConvFloat16ToFloat, + EOpConvFloat16ToDouble, + + // float -> (u)int* + EOpConvFloatToInt8, + EOpConvFloatToInt16, + EOpConvFloatToInt, + EOpConvFloatToInt64, + EOpConvFloatToUint8, + EOpConvFloatToUint16, + EOpConvFloatToUint, + EOpConvFloatToUint64, + + // float -> float* + EOpConvFloatToFloat16, + EOpConvFloatToDouble, + + // float64 _t-> (u)int* + EOpConvDoubleToInt8, + EOpConvDoubleToInt16, + EOpConvDoubleToInt, + EOpConvDoubleToInt64, + EOpConvDoubleToUint8, + EOpConvDoubleToUint16, + EOpConvDoubleToUint, + EOpConvDoubleToUint64, + + // float64_t -> float* + EOpConvDoubleToFloat16, + EOpConvDoubleToFloat, + + // uint64_t <-> pointer + EOpConvUint64ToPtr, + EOpConvPtrToUint64, + + // uvec2 <-> pointer + EOpConvUvec2ToPtr, + EOpConvPtrToUvec2, + + // + // binary operations + // + + EOpAdd, + EOpSub, + EOpMul, + EOpDiv, + EOpMod, + EOpRightShift, + EOpLeftShift, + EOpAnd, + EOpInclusiveOr, + EOpExclusiveOr, + EOpEqual, + EOpNotEqual, + EOpVectorEqual, + EOpVectorNotEqual, + EOpLessThan, + EOpGreaterThan, + EOpLessThanEqual, + EOpGreaterThanEqual, + EOpComma, + + EOpVectorTimesScalar, + EOpVectorTimesMatrix, + EOpMatrixTimesVector, + EOpMatrixTimesScalar, + + EOpLogicalOr, + EOpLogicalXor, + EOpLogicalAnd, + + EOpIndexDirect, + EOpIndexIndirect, + EOpIndexDirectStruct, + + EOpVectorSwizzle, + + EOpMethod, + EOpScoping, + + // + // Built-in functions mapped to operators + // + + EOpRadians, + EOpDegrees, + EOpSin, + EOpCos, + EOpTan, + EOpAsin, + EOpAcos, + EOpAtan, + EOpSinh, + EOpCosh, + EOpTanh, + EOpAsinh, + EOpAcosh, + EOpAtanh, + + EOpPow, + EOpExp, + EOpLog, + EOpExp2, + EOpLog2, + EOpSqrt, + EOpInverseSqrt, + + EOpAbs, + EOpSign, + EOpFloor, + EOpTrunc, + EOpRound, + EOpRoundEven, + EOpCeil, + EOpFract, + EOpModf, + EOpMin, + EOpMax, + EOpClamp, + EOpMix, + EOpStep, + EOpSmoothStep, + + EOpIsNan, + EOpIsInf, + + EOpFma, + + EOpFrexp, + EOpLdexp, + + EOpFloatBitsToInt, + EOpFloatBitsToUint, + EOpIntBitsToFloat, + EOpUintBitsToFloat, + EOpDoubleBitsToInt64, + EOpDoubleBitsToUint64, + EOpInt64BitsToDouble, + EOpUint64BitsToDouble, + EOpFloat16BitsToInt16, + EOpFloat16BitsToUint16, + EOpInt16BitsToFloat16, + EOpUint16BitsToFloat16, + EOpPackSnorm2x16, + EOpUnpackSnorm2x16, + EOpPackUnorm2x16, + EOpUnpackUnorm2x16, + EOpPackSnorm4x8, + EOpUnpackSnorm4x8, + EOpPackUnorm4x8, + EOpUnpackUnorm4x8, + EOpPackHalf2x16, + EOpUnpackHalf2x16, + EOpPackDouble2x32, + EOpUnpackDouble2x32, + EOpPackInt2x32, + EOpUnpackInt2x32, + EOpPackUint2x32, + EOpUnpackUint2x32, + EOpPackFloat2x16, + EOpUnpackFloat2x16, + EOpPackInt2x16, + EOpUnpackInt2x16, + EOpPackUint2x16, + EOpUnpackUint2x16, + EOpPackInt4x16, + EOpUnpackInt4x16, + EOpPackUint4x16, + EOpUnpackUint4x16, + EOpPack16, + EOpPack32, + EOpPack64, + EOpUnpack32, + EOpUnpack16, + EOpUnpack8, + + EOpLength, + EOpDistance, + EOpDot, + EOpCross, + EOpNormalize, + EOpFaceForward, + EOpReflect, + EOpRefract, + + EOpMin3, + EOpMax3, + EOpMid3, + + EOpDPdx, // Fragment only + EOpDPdy, // Fragment only + EOpFwidth, // Fragment only + EOpDPdxFine, // Fragment only + EOpDPdyFine, // Fragment only + EOpFwidthFine, // Fragment only + EOpDPdxCoarse, // Fragment only + EOpDPdyCoarse, // Fragment only + EOpFwidthCoarse, // Fragment only + + EOpInterpolateAtCentroid, // Fragment only + EOpInterpolateAtSample, // Fragment only + EOpInterpolateAtOffset, // Fragment only + EOpInterpolateAtVertex, + + EOpMatrixTimesMatrix, + EOpOuterProduct, + EOpDeterminant, + EOpMatrixInverse, + EOpTranspose, + + EOpFtransform, + + EOpNoise, + + EOpEmitVertex, // geometry only + EOpEndPrimitive, // geometry only + EOpEmitStreamVertex, // geometry only + EOpEndStreamPrimitive, // geometry only + + EOpBarrier, + EOpMemoryBarrier, + EOpMemoryBarrierAtomicCounter, + EOpMemoryBarrierBuffer, + EOpMemoryBarrierImage, + EOpMemoryBarrierShared, // compute only + EOpGroupMemoryBarrier, // compute only + + EOpBallot, + EOpReadInvocation, + EOpReadFirstInvocation, + + EOpAnyInvocation, + EOpAllInvocations, + EOpAllInvocationsEqual, + + EOpSubgroupGuardStart, + EOpSubgroupBarrier, + EOpSubgroupMemoryBarrier, + EOpSubgroupMemoryBarrierBuffer, + EOpSubgroupMemoryBarrierImage, + EOpSubgroupMemoryBarrierShared, // compute only + EOpSubgroupElect, + EOpSubgroupAll, + EOpSubgroupAny, + EOpSubgroupAllEqual, + EOpSubgroupBroadcast, + EOpSubgroupBroadcastFirst, + EOpSubgroupBallot, + EOpSubgroupInverseBallot, + EOpSubgroupBallotBitExtract, + EOpSubgroupBallotBitCount, + EOpSubgroupBallotInclusiveBitCount, + EOpSubgroupBallotExclusiveBitCount, + EOpSubgroupBallotFindLSB, + EOpSubgroupBallotFindMSB, + EOpSubgroupShuffle, + EOpSubgroupShuffleXor, + EOpSubgroupShuffleUp, + EOpSubgroupShuffleDown, + EOpSubgroupAdd, + EOpSubgroupMul, + EOpSubgroupMin, + EOpSubgroupMax, + EOpSubgroupAnd, + EOpSubgroupOr, + EOpSubgroupXor, + EOpSubgroupInclusiveAdd, + EOpSubgroupInclusiveMul, + EOpSubgroupInclusiveMin, + EOpSubgroupInclusiveMax, + EOpSubgroupInclusiveAnd, + EOpSubgroupInclusiveOr, + EOpSubgroupInclusiveXor, + EOpSubgroupExclusiveAdd, + EOpSubgroupExclusiveMul, + EOpSubgroupExclusiveMin, + EOpSubgroupExclusiveMax, + EOpSubgroupExclusiveAnd, + EOpSubgroupExclusiveOr, + EOpSubgroupExclusiveXor, + EOpSubgroupClusteredAdd, + EOpSubgroupClusteredMul, + EOpSubgroupClusteredMin, + EOpSubgroupClusteredMax, + EOpSubgroupClusteredAnd, + EOpSubgroupClusteredOr, + EOpSubgroupClusteredXor, + EOpSubgroupQuadBroadcast, + EOpSubgroupQuadSwapHorizontal, + EOpSubgroupQuadSwapVertical, + EOpSubgroupQuadSwapDiagonal, + + EOpSubgroupPartition, + EOpSubgroupPartitionedAdd, + EOpSubgroupPartitionedMul, + EOpSubgroupPartitionedMin, + EOpSubgroupPartitionedMax, + EOpSubgroupPartitionedAnd, + EOpSubgroupPartitionedOr, + EOpSubgroupPartitionedXor, + EOpSubgroupPartitionedInclusiveAdd, + EOpSubgroupPartitionedInclusiveMul, + EOpSubgroupPartitionedInclusiveMin, + EOpSubgroupPartitionedInclusiveMax, + EOpSubgroupPartitionedInclusiveAnd, + EOpSubgroupPartitionedInclusiveOr, + EOpSubgroupPartitionedInclusiveXor, + EOpSubgroupPartitionedExclusiveAdd, + EOpSubgroupPartitionedExclusiveMul, + EOpSubgroupPartitionedExclusiveMin, + EOpSubgroupPartitionedExclusiveMax, + EOpSubgroupPartitionedExclusiveAnd, + EOpSubgroupPartitionedExclusiveOr, + EOpSubgroupPartitionedExclusiveXor, + + EOpSubgroupGuardStop, + + EOpMinInvocations, + EOpMaxInvocations, + EOpAddInvocations, + EOpMinInvocationsNonUniform, + EOpMaxInvocationsNonUniform, + EOpAddInvocationsNonUniform, + EOpMinInvocationsInclusiveScan, + EOpMaxInvocationsInclusiveScan, + EOpAddInvocationsInclusiveScan, + EOpMinInvocationsInclusiveScanNonUniform, + EOpMaxInvocationsInclusiveScanNonUniform, + EOpAddInvocationsInclusiveScanNonUniform, + EOpMinInvocationsExclusiveScan, + EOpMaxInvocationsExclusiveScan, + EOpAddInvocationsExclusiveScan, + EOpMinInvocationsExclusiveScanNonUniform, + EOpMaxInvocationsExclusiveScanNonUniform, + EOpAddInvocationsExclusiveScanNonUniform, + EOpSwizzleInvocations, + EOpSwizzleInvocationsMasked, + EOpWriteInvocation, + EOpMbcnt, + + EOpCubeFaceIndex, + EOpCubeFaceCoord, + EOpTime, + + EOpAtomicAdd, + EOpAtomicMin, + EOpAtomicMax, + EOpAtomicAnd, + EOpAtomicOr, + EOpAtomicXor, + EOpAtomicExchange, + EOpAtomicCompSwap, + EOpAtomicLoad, + EOpAtomicStore, + + EOpAtomicCounterIncrement, // results in pre-increment value + EOpAtomicCounterDecrement, // results in post-decrement value + EOpAtomicCounter, + EOpAtomicCounterAdd, + EOpAtomicCounterSubtract, + EOpAtomicCounterMin, + EOpAtomicCounterMax, + EOpAtomicCounterAnd, + EOpAtomicCounterOr, + EOpAtomicCounterXor, + EOpAtomicCounterExchange, + EOpAtomicCounterCompSwap, + + EOpAny, + EOpAll, + + EOpCooperativeMatrixLoad, + EOpCooperativeMatrixStore, + EOpCooperativeMatrixMulAdd, + + EOpBeginInvocationInterlock, // Fragment only + EOpEndInvocationInterlock, // Fragment only + + EOpIsHelperInvocation, + + EOpDebugPrintf, + + // + // Branch + // + + EOpKill, // Fragment only + EOpReturn, + EOpBreak, + EOpContinue, + EOpCase, + EOpDefault, + EOpDemote, // Fragment only + + // + // Constructors + // + + EOpConstructGuardStart, + EOpConstructInt, // these first scalar forms also identify what implicit conversion is needed + EOpConstructUint, + EOpConstructInt8, + EOpConstructUint8, + EOpConstructInt16, + EOpConstructUint16, + EOpConstructInt64, + EOpConstructUint64, + EOpConstructBool, + EOpConstructFloat, + EOpConstructDouble, + // Keep vector and matrix constructors in a consistent relative order for + // TParseContext::constructBuiltIn, which converts between 8/16/32 bit + // vector constructors + EOpConstructVec2, + EOpConstructVec3, + EOpConstructVec4, + EOpConstructMat2x2, + EOpConstructMat2x3, + EOpConstructMat2x4, + EOpConstructMat3x2, + EOpConstructMat3x3, + EOpConstructMat3x4, + EOpConstructMat4x2, + EOpConstructMat4x3, + EOpConstructMat4x4, + EOpConstructDVec2, + EOpConstructDVec3, + EOpConstructDVec4, + EOpConstructBVec2, + EOpConstructBVec3, + EOpConstructBVec4, + EOpConstructI8Vec2, + EOpConstructI8Vec3, + EOpConstructI8Vec4, + EOpConstructU8Vec2, + EOpConstructU8Vec3, + EOpConstructU8Vec4, + EOpConstructI16Vec2, + EOpConstructI16Vec3, + EOpConstructI16Vec4, + EOpConstructU16Vec2, + EOpConstructU16Vec3, + EOpConstructU16Vec4, + EOpConstructIVec2, + EOpConstructIVec3, + EOpConstructIVec4, + EOpConstructUVec2, + EOpConstructUVec3, + EOpConstructUVec4, + EOpConstructI64Vec2, + EOpConstructI64Vec3, + EOpConstructI64Vec4, + EOpConstructU64Vec2, + EOpConstructU64Vec3, + EOpConstructU64Vec4, + EOpConstructDMat2x2, + EOpConstructDMat2x3, + EOpConstructDMat2x4, + EOpConstructDMat3x2, + EOpConstructDMat3x3, + EOpConstructDMat3x4, + EOpConstructDMat4x2, + EOpConstructDMat4x3, + EOpConstructDMat4x4, + EOpConstructIMat2x2, + EOpConstructIMat2x3, + EOpConstructIMat2x4, + EOpConstructIMat3x2, + EOpConstructIMat3x3, + EOpConstructIMat3x4, + EOpConstructIMat4x2, + EOpConstructIMat4x3, + EOpConstructIMat4x4, + EOpConstructUMat2x2, + EOpConstructUMat2x3, + EOpConstructUMat2x4, + EOpConstructUMat3x2, + EOpConstructUMat3x3, + EOpConstructUMat3x4, + EOpConstructUMat4x2, + EOpConstructUMat4x3, + EOpConstructUMat4x4, + EOpConstructBMat2x2, + EOpConstructBMat2x3, + EOpConstructBMat2x4, + EOpConstructBMat3x2, + EOpConstructBMat3x3, + EOpConstructBMat3x4, + EOpConstructBMat4x2, + EOpConstructBMat4x3, + EOpConstructBMat4x4, + EOpConstructFloat16, + EOpConstructF16Vec2, + EOpConstructF16Vec3, + EOpConstructF16Vec4, + EOpConstructF16Mat2x2, + EOpConstructF16Mat2x3, + EOpConstructF16Mat2x4, + EOpConstructF16Mat3x2, + EOpConstructF16Mat3x3, + EOpConstructF16Mat3x4, + EOpConstructF16Mat4x2, + EOpConstructF16Mat4x3, + EOpConstructF16Mat4x4, + EOpConstructStruct, + EOpConstructTextureSampler, + EOpConstructNonuniform, // expected to be transformed away, not present in final AST + EOpConstructReference, + EOpConstructCooperativeMatrix, + EOpConstructGuardEnd, + + // + // moves + // + + EOpAssign, + EOpAddAssign, + EOpSubAssign, + EOpMulAssign, + EOpVectorTimesMatrixAssign, + EOpVectorTimesScalarAssign, + EOpMatrixTimesScalarAssign, + EOpMatrixTimesMatrixAssign, + EOpDivAssign, + EOpModAssign, + EOpAndAssign, + EOpInclusiveOrAssign, + EOpExclusiveOrAssign, + EOpLeftShiftAssign, + EOpRightShiftAssign, + + // + // Array operators + // + + // Can apply to arrays, vectors, or matrices. + // Can be decomposed to a constant at compile time, but this does not always happen, + // due to link-time effects. So, consumer can expect either a link-time sized or + // run-time sized array. + EOpArrayLength, + + // + // Image operations + // + + EOpImageGuardBegin, + + EOpImageQuerySize, + EOpImageQuerySamples, + EOpImageLoad, + EOpImageStore, + EOpImageLoadLod, + EOpImageStoreLod, + EOpImageAtomicAdd, + EOpImageAtomicMin, + EOpImageAtomicMax, + EOpImageAtomicAnd, + EOpImageAtomicOr, + EOpImageAtomicXor, + EOpImageAtomicExchange, + EOpImageAtomicCompSwap, + EOpImageAtomicLoad, + EOpImageAtomicStore, + + EOpSubpassLoad, + EOpSubpassLoadMS, + EOpSparseImageLoad, + EOpSparseImageLoadLod, + + EOpImageGuardEnd, + + // + // Texture operations + // + + EOpTextureGuardBegin, + + EOpTextureQuerySize, + EOpTextureQueryLod, + EOpTextureQueryLevels, + EOpTextureQuerySamples, + + EOpSamplingGuardBegin, + + EOpTexture, + EOpTextureProj, + EOpTextureLod, + EOpTextureOffset, + EOpTextureFetch, + EOpTextureFetchOffset, + EOpTextureProjOffset, + EOpTextureLodOffset, + EOpTextureProjLod, + EOpTextureProjLodOffset, + EOpTextureGrad, + EOpTextureGradOffset, + EOpTextureProjGrad, + EOpTextureProjGradOffset, + EOpTextureGather, + EOpTextureGatherOffset, + EOpTextureGatherOffsets, + EOpTextureClamp, + EOpTextureOffsetClamp, + EOpTextureGradClamp, + EOpTextureGradOffsetClamp, + EOpTextureGatherLod, + EOpTextureGatherLodOffset, + EOpTextureGatherLodOffsets, + EOpFragmentMaskFetch, + EOpFragmentFetch, + + EOpSparseTextureGuardBegin, + + EOpSparseTexture, + EOpSparseTextureLod, + EOpSparseTextureOffset, + EOpSparseTextureFetch, + EOpSparseTextureFetchOffset, + EOpSparseTextureLodOffset, + EOpSparseTextureGrad, + EOpSparseTextureGradOffset, + EOpSparseTextureGather, + EOpSparseTextureGatherOffset, + EOpSparseTextureGatherOffsets, + EOpSparseTexelsResident, + EOpSparseTextureClamp, + EOpSparseTextureOffsetClamp, + EOpSparseTextureGradClamp, + EOpSparseTextureGradOffsetClamp, + EOpSparseTextureGatherLod, + EOpSparseTextureGatherLodOffset, + EOpSparseTextureGatherLodOffsets, + + EOpSparseTextureGuardEnd, + + EOpImageFootprintGuardBegin, + EOpImageSampleFootprintNV, + EOpImageSampleFootprintClampNV, + EOpImageSampleFootprintLodNV, + EOpImageSampleFootprintGradNV, + EOpImageSampleFootprintGradClampNV, + EOpImageFootprintGuardEnd, + EOpSamplingGuardEnd, + EOpTextureGuardEnd, + + // + // Integer operations + // + + EOpAddCarry, + EOpSubBorrow, + EOpUMulExtended, + EOpIMulExtended, + EOpBitfieldExtract, + EOpBitfieldInsert, + EOpBitFieldReverse, + EOpBitCount, + EOpFindLSB, + EOpFindMSB, + + EOpCountLeadingZeros, + EOpCountTrailingZeros, + EOpAbsDifference, + EOpAddSaturate, + EOpSubSaturate, + EOpAverage, + EOpAverageRounded, + EOpMul32x16, + + EOpTrace, + EOpReportIntersection, + EOpIgnoreIntersection, + EOpTerminateRay, + EOpExecuteCallable, + EOpWritePackedPrimitiveIndices4x8NV, + + // + // GL_EXT_ray_query operations + // + + EOpRayQueryInitialize, + EOpRayQueryTerminate, + EOpRayQueryGenerateIntersection, + EOpRayQueryConfirmIntersection, + EOpRayQueryProceed, + EOpRayQueryGetIntersectionType, + EOpRayQueryGetRayTMin, + EOpRayQueryGetRayFlags, + EOpRayQueryGetIntersectionT, + EOpRayQueryGetIntersectionInstanceCustomIndex, + EOpRayQueryGetIntersectionInstanceId, + EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset, + EOpRayQueryGetIntersectionGeometryIndex, + EOpRayQueryGetIntersectionPrimitiveIndex, + EOpRayQueryGetIntersectionBarycentrics, + EOpRayQueryGetIntersectionFrontFace, + EOpRayQueryGetIntersectionCandidateAABBOpaque, + EOpRayQueryGetIntersectionObjectRayDirection, + EOpRayQueryGetIntersectionObjectRayOrigin, + EOpRayQueryGetWorldRayDirection, + EOpRayQueryGetWorldRayOrigin, + EOpRayQueryGetIntersectionObjectToWorld, + EOpRayQueryGetIntersectionWorldToObject, + + // + // HLSL operations + // + + EOpClip, // discard if input value < 0 + EOpIsFinite, + EOpLog10, // base 10 log + EOpRcp, // 1/x + EOpSaturate, // clamp from 0 to 1 + EOpSinCos, // sin and cos in out parameters + EOpGenMul, // mul(x,y) on any of mat/vec/scalars + EOpDst, // x = 1, y=src0.y * src1.y, z=src0.z, w=src1.w + EOpInterlockedAdd, // atomic ops, but uses [optional] out arg instead of return + EOpInterlockedAnd, // ... + EOpInterlockedCompareExchange, // ... + EOpInterlockedCompareStore, // ... + EOpInterlockedExchange, // ... + EOpInterlockedMax, // ... + EOpInterlockedMin, // ... + EOpInterlockedOr, // ... + EOpInterlockedXor, // ... + EOpAllMemoryBarrierWithGroupSync, // memory barriers without non-hlsl AST equivalents + EOpDeviceMemoryBarrier, // ... + EOpDeviceMemoryBarrierWithGroupSync, // ... + EOpWorkgroupMemoryBarrier, // ... + EOpWorkgroupMemoryBarrierWithGroupSync, // ... + EOpEvaluateAttributeSnapped, // InterpolateAtOffset with int position on 16x16 grid + EOpF32tof16, // HLSL conversion: half of a PackHalf2x16 + EOpF16tof32, // HLSL conversion: half of an UnpackHalf2x16 + EOpLit, // HLSL lighting coefficient vector + EOpTextureBias, // HLSL texture bias: will be lowered to EOpTexture + EOpAsDouble, // slightly different from EOpUint64BitsToDouble + EOpD3DCOLORtoUBYTE4, // convert and swizzle 4-component color to UBYTE4 range + + EOpMethodSample, // Texture object methods. These are translated to existing + EOpMethodSampleBias, // AST methods, and exist to represent HLSL semantics until that + EOpMethodSampleCmp, // translation is performed. See HlslParseContext::decomposeSampleMethods(). + EOpMethodSampleCmpLevelZero, // ... + EOpMethodSampleGrad, // ... + EOpMethodSampleLevel, // ... + EOpMethodLoad, // ... + EOpMethodGetDimensions, // ... + EOpMethodGetSamplePosition, // ... + EOpMethodGather, // ... + EOpMethodCalculateLevelOfDetail, // ... + EOpMethodCalculateLevelOfDetailUnclamped, // ... + + // Load already defined above for textures + EOpMethodLoad2, // Structure buffer object methods. These are translated to existing + EOpMethodLoad3, // AST methods, and exist to represent HLSL semantics until that + EOpMethodLoad4, // translation is performed. See HlslParseContext::decomposeSampleMethods(). + EOpMethodStore, // ... + EOpMethodStore2, // ... + EOpMethodStore3, // ... + EOpMethodStore4, // ... + EOpMethodIncrementCounter, // ... + EOpMethodDecrementCounter, // ... + // EOpMethodAppend is defined for geo shaders below + EOpMethodConsume, + + // SM5 texture methods + EOpMethodGatherRed, // These are covered under the above EOpMethodSample comment about + EOpMethodGatherGreen, // translation to existing AST opcodes. They exist temporarily + EOpMethodGatherBlue, // because HLSL arguments are slightly different. + EOpMethodGatherAlpha, // ... + EOpMethodGatherCmp, // ... + EOpMethodGatherCmpRed, // ... + EOpMethodGatherCmpGreen, // ... + EOpMethodGatherCmpBlue, // ... + EOpMethodGatherCmpAlpha, // ... + + // geometry methods + EOpMethodAppend, // Geometry shader methods + EOpMethodRestartStrip, // ... + + // matrix + EOpMatrixSwizzle, // select multiple matrix components (non-column) + + // SM6 wave ops + EOpWaveGetLaneCount, // Will decompose to gl_SubgroupSize. + EOpWaveGetLaneIndex, // Will decompose to gl_SubgroupInvocationID. + EOpWaveActiveCountBits, // Will decompose to subgroupBallotBitCount(subgroupBallot()). + EOpWavePrefixCountBits, // Will decompose to subgroupBallotInclusiveBitCount(subgroupBallot()). + + // Shader Clock Ops + EOpReadClockSubgroupKHR, + EOpReadClockDeviceKHR, +}; + +class TIntermTraverser; +class TIntermOperator; +class TIntermAggregate; +class TIntermUnary; +class TIntermBinary; +class TIntermConstantUnion; +class TIntermSelection; +class TIntermSwitch; +class TIntermBranch; +class TIntermTyped; +class TIntermMethod; +class TIntermSymbol; +class TIntermLoop; + +} // end namespace glslang + +// +// Base class for the tree nodes +// +// (Put outside the glslang namespace, as it's used as part of the external interface.) +// +class TIntermNode { +public: + POOL_ALLOCATOR_NEW_DELETE(glslang::GetThreadPoolAllocator()) + + TIntermNode() { loc.init(); } + virtual const glslang::TSourceLoc& getLoc() const { return loc; } + virtual void setLoc(const glslang::TSourceLoc& l) { loc = l; } + virtual void traverse(glslang::TIntermTraverser*) = 0; + virtual glslang::TIntermTyped* getAsTyped() { return 0; } + virtual glslang::TIntermOperator* getAsOperator() { return 0; } + virtual glslang::TIntermConstantUnion* getAsConstantUnion() { return 0; } + virtual glslang::TIntermAggregate* getAsAggregate() { return 0; } + virtual glslang::TIntermUnary* getAsUnaryNode() { return 0; } + virtual glslang::TIntermBinary* getAsBinaryNode() { return 0; } + virtual glslang::TIntermSelection* getAsSelectionNode() { return 0; } + virtual glslang::TIntermSwitch* getAsSwitchNode() { return 0; } + virtual glslang::TIntermMethod* getAsMethodNode() { return 0; } + virtual glslang::TIntermSymbol* getAsSymbolNode() { return 0; } + virtual glslang::TIntermBranch* getAsBranchNode() { return 0; } + virtual glslang::TIntermLoop* getAsLoopNode() { return 0; } + + virtual const glslang::TIntermTyped* getAsTyped() const { return 0; } + virtual const glslang::TIntermOperator* getAsOperator() const { return 0; } + virtual const glslang::TIntermConstantUnion* getAsConstantUnion() const { return 0; } + virtual const glslang::TIntermAggregate* getAsAggregate() const { return 0; } + virtual const glslang::TIntermUnary* getAsUnaryNode() const { return 0; } + virtual const glslang::TIntermBinary* getAsBinaryNode() const { return 0; } + virtual const glslang::TIntermSelection* getAsSelectionNode() const { return 0; } + virtual const glslang::TIntermSwitch* getAsSwitchNode() const { return 0; } + virtual const glslang::TIntermMethod* getAsMethodNode() const { return 0; } + virtual const glslang::TIntermSymbol* getAsSymbolNode() const { return 0; } + virtual const glslang::TIntermBranch* getAsBranchNode() const { return 0; } + virtual const glslang::TIntermLoop* getAsLoopNode() const { return 0; } + virtual ~TIntermNode() { } + +protected: + TIntermNode(const TIntermNode&); + TIntermNode& operator=(const TIntermNode&); + glslang::TSourceLoc loc; +}; + +namespace glslang { + +// +// This is just to help yacc. +// +struct TIntermNodePair { + TIntermNode* node1; + TIntermNode* node2; +}; + +// +// Intermediate class for nodes that have a type. +// +class TIntermTyped : public TIntermNode { +public: + TIntermTyped(const TType& t) { type.shallowCopy(t); } + TIntermTyped(TBasicType basicType) { TType bt(basicType); type.shallowCopy(bt); } + virtual TIntermTyped* getAsTyped() { return this; } + virtual const TIntermTyped* getAsTyped() const { return this; } + virtual void setType(const TType& t) { type.shallowCopy(t); } + virtual const TType& getType() const { return type; } + virtual TType& getWritableType() { return type; } + + virtual TBasicType getBasicType() const { return type.getBasicType(); } + virtual TQualifier& getQualifier() { return type.getQualifier(); } + virtual const TQualifier& getQualifier() const { return type.getQualifier(); } + virtual void propagatePrecision(TPrecisionQualifier); + virtual int getVectorSize() const { return type.getVectorSize(); } + virtual int getMatrixCols() const { return type.getMatrixCols(); } + virtual int getMatrixRows() const { return type.getMatrixRows(); } + virtual bool isMatrix() const { return type.isMatrix(); } + virtual bool isArray() const { return type.isArray(); } + virtual bool isVector() const { return type.isVector(); } + virtual bool isScalar() const { return type.isScalar(); } + virtual bool isStruct() const { return type.isStruct(); } + virtual bool isFloatingDomain() const { return type.isFloatingDomain(); } + virtual bool isIntegerDomain() const { return type.isIntegerDomain(); } + bool isAtomic() const { return type.isAtomic(); } + bool isReference() const { return type.isReference(); } + TString getCompleteString() const { return type.getCompleteString(); } + +protected: + TIntermTyped& operator=(const TIntermTyped&); + TType type; +}; + +// +// Handle for, do-while, and while loops. +// +class TIntermLoop : public TIntermNode { +public: + TIntermLoop(TIntermNode* aBody, TIntermTyped* aTest, TIntermTyped* aTerminal, bool testFirst) : + body(aBody), + test(aTest), + terminal(aTerminal), + first(testFirst), + unroll(false), + dontUnroll(false), + dependency(0), + minIterations(0), + maxIterations(iterationsInfinite), + iterationMultiple(1), + peelCount(0), + partialCount(0) + { } + + virtual TIntermLoop* getAsLoopNode() { return this; } + virtual const TIntermLoop* getAsLoopNode() const { return this; } + virtual void traverse(TIntermTraverser*); + TIntermNode* getBody() const { return body; } + TIntermTyped* getTest() const { return test; } + TIntermTyped* getTerminal() const { return terminal; } + bool testFirst() const { return first; } + + void setUnroll() { unroll = true; } + void setDontUnroll() { + dontUnroll = true; + peelCount = 0; + partialCount = 0; + } + bool getUnroll() const { return unroll; } + bool getDontUnroll() const { return dontUnroll; } + + static const unsigned int dependencyInfinite = 0xFFFFFFFF; + static const unsigned int iterationsInfinite = 0xFFFFFFFF; + void setLoopDependency(int d) { dependency = d; } + int getLoopDependency() const { return dependency; } + + void setMinIterations(unsigned int v) { minIterations = v; } + unsigned int getMinIterations() const { return minIterations; } + void setMaxIterations(unsigned int v) { maxIterations = v; } + unsigned int getMaxIterations() const { return maxIterations; } + void setIterationMultiple(unsigned int v) { iterationMultiple = v; } + unsigned int getIterationMultiple() const { return iterationMultiple; } + void setPeelCount(unsigned int v) { + peelCount = v; + dontUnroll = false; + } + unsigned int getPeelCount() const { return peelCount; } + void setPartialCount(unsigned int v) { + partialCount = v; + dontUnroll = false; + } + unsigned int getPartialCount() const { return partialCount; } + +protected: + TIntermNode* body; // code to loop over + TIntermTyped* test; // exit condition associated with loop, could be 0 for 'for' loops + TIntermTyped* terminal; // exists for for-loops + bool first; // true for while and for, not for do-while + bool unroll; // true if unroll requested + bool dontUnroll; // true if request to not unroll + unsigned int dependency; // loop dependency hint; 0 means not set or unknown + unsigned int minIterations; // as per the SPIR-V specification + unsigned int maxIterations; // as per the SPIR-V specification + unsigned int iterationMultiple; // as per the SPIR-V specification + unsigned int peelCount; // as per the SPIR-V specification + unsigned int partialCount; // as per the SPIR-V specification +}; + +// +// Handle case, break, continue, return, and kill. +// +class TIntermBranch : public TIntermNode { +public: + TIntermBranch(TOperator op, TIntermTyped* e) : + flowOp(op), + expression(e) { } + virtual TIntermBranch* getAsBranchNode() { return this; } + virtual const TIntermBranch* getAsBranchNode() const { return this; } + virtual void traverse(TIntermTraverser*); + TOperator getFlowOp() const { return flowOp; } + TIntermTyped* getExpression() const { return expression; } + void setExpression(TIntermTyped* pExpression) { expression = pExpression; } +protected: + TOperator flowOp; + TIntermTyped* expression; +}; + +// +// Represent method names before seeing their calling signature +// or resolving them to operations. Just an expression as the base object +// and a textural name. +// +class TIntermMethod : public TIntermTyped { +public: + TIntermMethod(TIntermTyped* o, const TType& t, const TString& m) : TIntermTyped(t), object(o), method(m) { } + virtual TIntermMethod* getAsMethodNode() { return this; } + virtual const TIntermMethod* getAsMethodNode() const { return this; } + virtual const TString& getMethodName() const { return method; } + virtual TIntermTyped* getObject() const { return object; } + virtual void traverse(TIntermTraverser*); +protected: + TIntermTyped* object; + TString method; +}; + +// +// Nodes that correspond to symbols or constants in the source code. +// +class TIntermSymbol : public TIntermTyped { +public: + // if symbol is initialized as symbol(sym), the memory comes from the pool allocator of sym. If sym comes from + // per process threadPoolAllocator, then it causes increased memory usage per compile + // it is essential to use "symbol = sym" to assign to symbol + TIntermSymbol(int i, const TString& n, const TType& t) + : TIntermTyped(t), id(i), +#ifndef GLSLANG_WEB + flattenSubset(-1), +#endif + constSubtree(nullptr) + { name = n; } + virtual int getId() const { return id; } + virtual void changeId(int i) { id = i; } + virtual const TString& getName() const { return name; } + virtual void traverse(TIntermTraverser*); + virtual TIntermSymbol* getAsSymbolNode() { return this; } + virtual const TIntermSymbol* getAsSymbolNode() const { return this; } + void setConstArray(const TConstUnionArray& c) { constArray = c; } + const TConstUnionArray& getConstArray() const { return constArray; } + void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; } + TIntermTyped* getConstSubtree() const { return constSubtree; } +#ifndef GLSLANG_WEB + void setFlattenSubset(int subset) { flattenSubset = subset; } + int getFlattenSubset() const { return flattenSubset; } // -1 means full object +#endif + + // This is meant for cases where a node has already been constructed, and + // later on, it becomes necessary to switch to a different symbol. + virtual void switchId(int newId) { id = newId; } + +protected: + int id; // the unique id of the symbol this node represents +#ifndef GLSLANG_WEB + int flattenSubset; // how deeply the flattened object rooted at id has been dereferenced +#endif + TString name; // the name of the symbol this node represents + TConstUnionArray constArray; // if the symbol is a front-end compile-time constant, this is its value + TIntermTyped* constSubtree; +}; + +class TIntermConstantUnion : public TIntermTyped { +public: + TIntermConstantUnion(const TConstUnionArray& ua, const TType& t) : TIntermTyped(t), constArray(ua), literal(false) { } + const TConstUnionArray& getConstArray() const { return constArray; } + virtual TIntermConstantUnion* getAsConstantUnion() { return this; } + virtual const TIntermConstantUnion* getAsConstantUnion() const { return this; } + virtual void traverse(TIntermTraverser*); + virtual TIntermTyped* fold(TOperator, const TIntermTyped*) const; + virtual TIntermTyped* fold(TOperator, const TType&) const; + void setLiteral() { literal = true; } + void setExpression() { literal = false; } + bool isLiteral() const { return literal; } + +protected: + TIntermConstantUnion& operator=(const TIntermConstantUnion&); + + const TConstUnionArray constArray; + bool literal; // true if node represents a literal in the source code +}; + +// Represent the independent aspects of a texturing TOperator +struct TCrackedTextureOp { + bool query; + bool proj; + bool lod; + bool fetch; + bool offset; + bool offsets; + bool gather; + bool grad; + bool subpass; + bool lodClamp; + bool fragMask; +}; + +// +// Intermediate class for node types that hold operators. +// +class TIntermOperator : public TIntermTyped { +public: + virtual TIntermOperator* getAsOperator() { return this; } + virtual const TIntermOperator* getAsOperator() const { return this; } + TOperator getOp() const { return op; } + void setOp(TOperator newOp) { op = newOp; } + bool modifiesState() const; + bool isConstructor() const; + bool isTexture() const { return op > EOpTextureGuardBegin && op < EOpTextureGuardEnd; } + bool isSampling() const { return op > EOpSamplingGuardBegin && op < EOpSamplingGuardEnd; } +#ifdef GLSLANG_WEB + bool isImage() const { return false; } + bool isSparseTexture() const { return false; } + bool isImageFootprint() const { return false; } + bool isSparseImage() const { return false; } + bool isSubgroup() const { return false; } +#else + bool isImage() const { return op > EOpImageGuardBegin && op < EOpImageGuardEnd; } + bool isSparseTexture() const { return op > EOpSparseTextureGuardBegin && op < EOpSparseTextureGuardEnd; } + bool isImageFootprint() const { return op > EOpImageFootprintGuardBegin && op < EOpImageFootprintGuardEnd; } + bool isSparseImage() const { return op == EOpSparseImageLoad; } + bool isSubgroup() const { return op > EOpSubgroupGuardStart && op < EOpSubgroupGuardStop; } +#endif + + void setOperationPrecision(TPrecisionQualifier p) { operationPrecision = p; } + TPrecisionQualifier getOperationPrecision() const { return operationPrecision != EpqNone ? + operationPrecision : + type.getQualifier().precision; } + TString getCompleteString() const + { + TString cs = type.getCompleteString(); + if (getOperationPrecision() != type.getQualifier().precision) { + cs += ", operation at "; + cs += GetPrecisionQualifierString(getOperationPrecision()); + } + + return cs; + } + + // Crack the op into the individual dimensions of texturing operation. + void crackTexture(TSampler sampler, TCrackedTextureOp& cracked) const + { + cracked.query = false; + cracked.proj = false; + cracked.lod = false; + cracked.fetch = false; + cracked.offset = false; + cracked.offsets = false; + cracked.gather = false; + cracked.grad = false; + cracked.subpass = false; + cracked.lodClamp = false; + cracked.fragMask = false; + + switch (op) { + case EOpImageQuerySize: + case EOpImageQuerySamples: + case EOpTextureQuerySize: + case EOpTextureQueryLod: + case EOpTextureQueryLevels: + case EOpTextureQuerySamples: + case EOpSparseTexelsResident: + cracked.query = true; + break; + case EOpTexture: + case EOpSparseTexture: + break; + case EOpTextureProj: + cracked.proj = true; + break; + case EOpTextureLod: + case EOpSparseTextureLod: + cracked.lod = true; + break; + case EOpTextureOffset: + case EOpSparseTextureOffset: + cracked.offset = true; + break; + case EOpTextureFetch: + case EOpSparseTextureFetch: + cracked.fetch = true; + if (sampler.is1D() || (sampler.dim == Esd2D && ! sampler.isMultiSample()) || sampler.dim == Esd3D) + cracked.lod = true; + break; + case EOpTextureFetchOffset: + case EOpSparseTextureFetchOffset: + cracked.fetch = true; + cracked.offset = true; + if (sampler.is1D() || (sampler.dim == Esd2D && ! sampler.isMultiSample()) || sampler.dim == Esd3D) + cracked.lod = true; + break; + case EOpTextureProjOffset: + cracked.offset = true; + cracked.proj = true; + break; + case EOpTextureLodOffset: + case EOpSparseTextureLodOffset: + cracked.offset = true; + cracked.lod = true; + break; + case EOpTextureProjLod: + cracked.lod = true; + cracked.proj = true; + break; + case EOpTextureProjLodOffset: + cracked.offset = true; + cracked.lod = true; + cracked.proj = true; + break; + case EOpTextureGrad: + case EOpSparseTextureGrad: + cracked.grad = true; + break; + case EOpTextureGradOffset: + case EOpSparseTextureGradOffset: + cracked.grad = true; + cracked.offset = true; + break; + case EOpTextureProjGrad: + cracked.grad = true; + cracked.proj = true; + break; + case EOpTextureProjGradOffset: + cracked.grad = true; + cracked.offset = true; + cracked.proj = true; + break; +#ifndef GLSLANG_WEB + case EOpTextureClamp: + case EOpSparseTextureClamp: + cracked.lodClamp = true; + break; + case EOpTextureOffsetClamp: + case EOpSparseTextureOffsetClamp: + cracked.offset = true; + cracked.lodClamp = true; + break; + case EOpTextureGradClamp: + case EOpSparseTextureGradClamp: + cracked.grad = true; + cracked.lodClamp = true; + break; + case EOpTextureGradOffsetClamp: + case EOpSparseTextureGradOffsetClamp: + cracked.grad = true; + cracked.offset = true; + cracked.lodClamp = true; + break; + case EOpTextureGather: + case EOpSparseTextureGather: + cracked.gather = true; + break; + case EOpTextureGatherOffset: + case EOpSparseTextureGatherOffset: + cracked.gather = true; + cracked.offset = true; + break; + case EOpTextureGatherOffsets: + case EOpSparseTextureGatherOffsets: + cracked.gather = true; + cracked.offsets = true; + break; + case EOpTextureGatherLod: + case EOpSparseTextureGatherLod: + cracked.gather = true; + cracked.lod = true; + break; + case EOpTextureGatherLodOffset: + case EOpSparseTextureGatherLodOffset: + cracked.gather = true; + cracked.offset = true; + cracked.lod = true; + break; + case EOpTextureGatherLodOffsets: + case EOpSparseTextureGatherLodOffsets: + cracked.gather = true; + cracked.offsets = true; + cracked.lod = true; + break; + case EOpImageLoadLod: + case EOpImageStoreLod: + case EOpSparseImageLoadLod: + cracked.lod = true; + break; + case EOpFragmentMaskFetch: + cracked.subpass = sampler.dim == EsdSubpass; + cracked.fragMask = true; + break; + case EOpFragmentFetch: + cracked.subpass = sampler.dim == EsdSubpass; + cracked.fragMask = true; + break; + case EOpImageSampleFootprintNV: + break; + case EOpImageSampleFootprintClampNV: + cracked.lodClamp = true; + break; + case EOpImageSampleFootprintLodNV: + cracked.lod = true; + break; + case EOpImageSampleFootprintGradNV: + cracked.grad = true; + break; + case EOpImageSampleFootprintGradClampNV: + cracked.lodClamp = true; + cracked.grad = true; + break; + case EOpSubpassLoad: + case EOpSubpassLoadMS: + cracked.subpass = true; + break; +#endif + default: + break; + } + } + +protected: + TIntermOperator(TOperator o) : TIntermTyped(EbtFloat), op(o), operationPrecision(EpqNone) {} + TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o), operationPrecision(EpqNone) {} + TOperator op; + // The result precision is in the inherited TType, and is usually meant to be both + // the operation precision and the result precision. However, some more complex things, + // like built-in function calls, distinguish between the two, in which case non-EqpNone + // 'operationPrecision' overrides the result precision as far as operation precision + // is concerned. + TPrecisionQualifier operationPrecision; +}; + +// +// Nodes for all the basic binary math operators. +// +class TIntermBinary : public TIntermOperator { +public: + TIntermBinary(TOperator o) : TIntermOperator(o) {} + virtual void traverse(TIntermTraverser*); + virtual void setLeft(TIntermTyped* n) { left = n; } + virtual void setRight(TIntermTyped* n) { right = n; } + virtual TIntermTyped* getLeft() const { return left; } + virtual TIntermTyped* getRight() const { return right; } + virtual TIntermBinary* getAsBinaryNode() { return this; } + virtual const TIntermBinary* getAsBinaryNode() const { return this; } + virtual void updatePrecision(); +protected: + TIntermTyped* left; + TIntermTyped* right; +}; + +// +// Nodes for unary math operators. +// +class TIntermUnary : public TIntermOperator { +public: + TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {} + TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {} + virtual void traverse(TIntermTraverser*); + virtual void setOperand(TIntermTyped* o) { operand = o; } + virtual TIntermTyped* getOperand() { return operand; } + virtual const TIntermTyped* getOperand() const { return operand; } + virtual TIntermUnary* getAsUnaryNode() { return this; } + virtual const TIntermUnary* getAsUnaryNode() const { return this; } + virtual void updatePrecision(); +protected: + TIntermTyped* operand; +}; + +typedef TVector TIntermSequence; +typedef TVector TQualifierList; +// +// Nodes that operate on an arbitrary sized set of children. +// +class TIntermAggregate : public TIntermOperator { +public: + TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(nullptr) { } + TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(nullptr) { } + ~TIntermAggregate() { delete pragmaTable; } + virtual TIntermAggregate* getAsAggregate() { return this; } + virtual const TIntermAggregate* getAsAggregate() const { return this; } + virtual void setOperator(TOperator o) { op = o; } + virtual TIntermSequence& getSequence() { return sequence; } + virtual const TIntermSequence& getSequence() const { return sequence; } + virtual void setName(const TString& n) { name = n; } + virtual const TString& getName() const { return name; } + virtual void traverse(TIntermTraverser*); + virtual void setUserDefined() { userDefined = true; } + virtual bool isUserDefined() { return userDefined; } + virtual TQualifierList& getQualifierList() { return qualifier; } + virtual const TQualifierList& getQualifierList() const { return qualifier; } + void setOptimize(bool o) { optimize = o; } + void setDebug(bool d) { debug = d; } + bool getOptimize() const { return optimize; } + bool getDebug() const { return debug; } + void setPragmaTable(const TPragmaTable& pTable); + const TPragmaTable& getPragmaTable() const { return *pragmaTable; } +protected: + TIntermAggregate(const TIntermAggregate&); // disallow copy constructor + TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator + TIntermSequence sequence; + TQualifierList qualifier; + TString name; + bool userDefined; // used for user defined function names + bool optimize; + bool debug; + TPragmaTable* pragmaTable; +}; + +// +// For if tests. +// +class TIntermSelection : public TIntermTyped { +public: + TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) : + TIntermTyped(EbtVoid), condition(cond), trueBlock(trueB), falseBlock(falseB), + shortCircuit(true), + flatten(false), dontFlatten(false) {} + TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) : + TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB), + shortCircuit(true), + flatten(false), dontFlatten(false) {} + virtual void traverse(TIntermTraverser*); + virtual TIntermTyped* getCondition() const { return condition; } + virtual TIntermNode* getTrueBlock() const { return trueBlock; } + virtual TIntermNode* getFalseBlock() const { return falseBlock; } + virtual TIntermSelection* getAsSelectionNode() { return this; } + virtual const TIntermSelection* getAsSelectionNode() const { return this; } + + void setNoShortCircuit() { shortCircuit = false; } + bool getShortCircuit() const { return shortCircuit; } + + void setFlatten() { flatten = true; } + void setDontFlatten() { dontFlatten = true; } + bool getFlatten() const { return flatten; } + bool getDontFlatten() const { return dontFlatten; } + +protected: + TIntermTyped* condition; + TIntermNode* trueBlock; + TIntermNode* falseBlock; + bool shortCircuit; // normally all if-then-else and all GLSL ?: short-circuit, but HLSL ?: does not + bool flatten; // true if flatten requested + bool dontFlatten; // true if requested to not flatten +}; + +// +// For switch statements. Designed use is that a switch will have sequence of nodes +// that are either case/default nodes or a *single* node that represents all the code +// in between (if any) consecutive case/defaults. So, a traversal need only deal with +// 0 or 1 nodes per case/default statement. +// +class TIntermSwitch : public TIntermNode { +public: + TIntermSwitch(TIntermTyped* cond, TIntermAggregate* b) : condition(cond), body(b), + flatten(false), dontFlatten(false) {} + virtual void traverse(TIntermTraverser*); + virtual TIntermNode* getCondition() const { return condition; } + virtual TIntermAggregate* getBody() const { return body; } + virtual TIntermSwitch* getAsSwitchNode() { return this; } + virtual const TIntermSwitch* getAsSwitchNode() const { return this; } + + void setFlatten() { flatten = true; } + void setDontFlatten() { dontFlatten = true; } + bool getFlatten() const { return flatten; } + bool getDontFlatten() const { return dontFlatten; } + +protected: + TIntermTyped* condition; + TIntermAggregate* body; + bool flatten; // true if flatten requested + bool dontFlatten; // true if requested to not flatten +}; + +enum TVisit +{ + EvPreVisit, + EvInVisit, + EvPostVisit +}; + +// +// For traversing the tree. User should derive from this, +// put their traversal specific data in it, and then pass +// it to a Traverse method. +// +// When using this, just fill in the methods for nodes you want visited. +// Return false from a pre-visit to skip visiting that node's subtree. +// +// Explicitly set postVisit to true if you want post visiting, otherwise, +// filled in methods will only be called at pre-visit time (before processing +// the subtree). Similarly for inVisit for in-order visiting of nodes with +// multiple children. +// +// If you only want post-visits, explicitly turn off preVisit (and inVisit) +// and turn on postVisit. +// +// In general, for the visit*() methods, return true from interior nodes +// to have the traversal continue on to children. +// +// If you process children yourself, or don't want them processed, return false. +// +class TIntermTraverser { +public: + POOL_ALLOCATOR_NEW_DELETE(glslang::GetThreadPoolAllocator()) + TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) : + preVisit(preVisit), + inVisit(inVisit), + postVisit(postVisit), + rightToLeft(rightToLeft), + depth(0), + maxDepth(0) { } + virtual ~TIntermTraverser() { } + + virtual void visitSymbol(TIntermSymbol*) { } + virtual void visitConstantUnion(TIntermConstantUnion*) { } + virtual bool visitBinary(TVisit, TIntermBinary*) { return true; } + virtual bool visitUnary(TVisit, TIntermUnary*) { return true; } + virtual bool visitSelection(TVisit, TIntermSelection*) { return true; } + virtual bool visitAggregate(TVisit, TIntermAggregate*) { return true; } + virtual bool visitLoop(TVisit, TIntermLoop*) { return true; } + virtual bool visitBranch(TVisit, TIntermBranch*) { return true; } + virtual bool visitSwitch(TVisit, TIntermSwitch*) { return true; } + + int getMaxDepth() const { return maxDepth; } + + void incrementDepth(TIntermNode *current) + { + depth++; + maxDepth = (std::max)(maxDepth, depth); + path.push_back(current); + } + + void decrementDepth() + { + depth--; + path.pop_back(); + } + + TIntermNode *getParentNode() + { + return path.size() == 0 ? NULL : path.back(); + } + + const bool preVisit; + const bool inVisit; + const bool postVisit; + const bool rightToLeft; + +protected: + TIntermTraverser& operator=(TIntermTraverser&); + + int depth; + int maxDepth; + + // All the nodes from root to the current node's parent during traversing. + TVector path; +}; + +// KHR_vulkan_glsl says "Two arrays sized with specialization constants are the same type only if +// sized with the same symbol, involving no operations" +inline bool SameSpecializationConstants(TIntermTyped* node1, TIntermTyped* node2) +{ + return node1->getAsSymbolNode() && node2->getAsSymbolNode() && + node1->getAsSymbolNode()->getId() == node2->getAsSymbolNode()->getId(); +} + +} // end namespace glslang + +#endif // __INTERMEDIATE_H diff --git a/android/armeabi-v7a/include/glslang/Include/revision.h b/android/armeabi-v7a/include/glslang/Include/revision.h new file mode 100644 index 00000000..744c2fb4 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/Include/revision.h @@ -0,0 +1,3 @@ +// This header is generated by the make-revision script. + +#define GLSLANG_PATCH_LEVEL 3743 diff --git a/android/armeabi-v7a/include/glslang/MachineIndependent/Initialize.h b/android/armeabi-v7a/include/glslang/MachineIndependent/Initialize.h new file mode 100644 index 00000000..ac8ec33e --- /dev/null +++ b/android/armeabi-v7a/include/glslang/MachineIndependent/Initialize.h @@ -0,0 +1,112 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013-2016 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _INITIALIZE_INCLUDED_ +#define _INITIALIZE_INCLUDED_ + +#include "../Include/ResourceLimits.h" +#include "../Include/Common.h" +#include "../Include/ShHandle.h" +#include "SymbolTable.h" +#include "Versions.h" + +namespace glslang { + +// +// This is made to hold parseable strings for almost all the built-in +// functions and variables for one specific combination of version +// and profile. (Some still need to be added programmatically.) +// This is a base class for language-specific derivations, which +// can be used for language independent builtins. +// +// The strings are organized by +// commonBuiltins: intersection of all stages' built-ins, processed just once +// stageBuiltins[]: anything a stage needs that's not in commonBuiltins +// +class TBuiltInParseables { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + TBuiltInParseables(); + virtual ~TBuiltInParseables(); + virtual void initialize(int version, EProfile, const SpvVersion& spvVersion) = 0; + virtual void initialize(const TBuiltInResource& resources, int version, EProfile, const SpvVersion& spvVersion, EShLanguage) = 0; + virtual const TString& getCommonString() const { return commonBuiltins; } + virtual const TString& getStageString(EShLanguage language) const { return stageBuiltins[language]; } + + virtual void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable) = 0; + virtual void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources) = 0; + +protected: + TString commonBuiltins; + TString stageBuiltins[EShLangCount]; +}; + +// +// This is a GLSL specific derivation of TBuiltInParseables. To present a stable +// interface and match other similar code, it is called TBuiltIns, rather +// than TBuiltInParseablesGlsl. +// +class TBuiltIns : public TBuiltInParseables { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + TBuiltIns(); + virtual ~TBuiltIns(); + void initialize(int version, EProfile, const SpvVersion& spvVersion); + void initialize(const TBuiltInResource& resources, int version, EProfile, const SpvVersion& spvVersion, EShLanguage); + + void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable); + void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources); + +protected: + void addTabledBuiltins(int version, EProfile profile, const SpvVersion& spvVersion); + void relateTabledBuiltins(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage, TSymbolTable&); + void add2ndGenerationSamplingImaging(int version, EProfile profile, const SpvVersion& spvVersion); + void addSubpassSampling(TSampler, const TString& typeName, int version, EProfile profile); + void addQueryFunctions(TSampler, const TString& typeName, int version, EProfile profile); + void addImageFunctions(TSampler, const TString& typeName, int version, EProfile profile); + void addSamplingFunctions(TSampler, const TString& typeName, int version, EProfile profile); + void addGatherFunctions(TSampler, const TString& typeName, int version, EProfile profile); + + // Helpers for making textual representations of the permutations + // of texturing/imaging functions. + const char* postfixes[5]; + const char* prefixes[EbtNumTypes]; + int dimMap[EsdNumDims]; +}; + +} // end namespace glslang + +#endif // _INITIALIZE_INCLUDED_ diff --git a/android/armeabi-v7a/include/glslang/MachineIndependent/LiveTraverser.h b/android/armeabi-v7a/include/glslang/MachineIndependent/LiveTraverser.h new file mode 100644 index 00000000..7333bc96 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/MachineIndependent/LiveTraverser.h @@ -0,0 +1,138 @@ +// +// Copyright (C) 2016 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#pragma once + +#include "../Include/Common.h" +#include "reflection.h" +#include "localintermediate.h" + +#include "gl_types.h" + +#include +#include + +namespace glslang { + +// +// The traverser: mostly pass through, except +// - processing function-call nodes to push live functions onto the stack of functions to process +// - processing selection nodes to trim semantically dead code +// +// This is in the glslang namespace directly so it can be a friend of TReflection. +// This can be derived from to implement reflection database traversers or +// binding mappers: anything that wants to traverse the live subset of the tree. +// + +class TLiveTraverser : public TIntermTraverser { +public: + TLiveTraverser(const TIntermediate& i, bool traverseAll = false, + bool preVisit = true, bool inVisit = false, bool postVisit = false) : + TIntermTraverser(preVisit, inVisit, postVisit), + intermediate(i), traverseAll(traverseAll) + { } + + // + // Given a function name, find its subroot in the tree, and push it onto the stack of + // functions left to process. + // + void pushFunction(const TString& name) + { + TIntermSequence& globals = intermediate.getTreeRoot()->getAsAggregate()->getSequence(); + for (unsigned int f = 0; f < globals.size(); ++f) { + TIntermAggregate* candidate = globals[f]->getAsAggregate(); + if (candidate && candidate->getOp() == EOpFunction && candidate->getName() == name) { + functions.push_back(candidate); + break; + } + } + } + + typedef std::list TFunctionStack; + TFunctionStack functions; + +protected: + // To catch which function calls are not dead, and hence which functions must be visited. + virtual bool visitAggregate(TVisit, TIntermAggregate* node) + { + if (!traverseAll) + if (node->getOp() == EOpFunctionCall) + addFunctionCall(node); + + return true; // traverse this subtree + } + + // To prune semantically dead paths. + virtual bool visitSelection(TVisit /* visit */, TIntermSelection* node) + { + if (traverseAll) + return true; // traverse all code + + TIntermConstantUnion* constant = node->getCondition()->getAsConstantUnion(); + if (constant) { + // cull the path that is dead + if (constant->getConstArray()[0].getBConst() == true && node->getTrueBlock()) + node->getTrueBlock()->traverse(this); + if (constant->getConstArray()[0].getBConst() == false && node->getFalseBlock()) + node->getFalseBlock()->traverse(this); + + return false; // don't traverse any more, we did it all above + } else + return true; // traverse the whole subtree + } + + // Track live functions as well as uniforms, so that we don't visit dead functions + // and only visit each function once. + void addFunctionCall(TIntermAggregate* call) + { + // // just use the map to ensure we process each function at most once + if (liveFunctions.find(call->getName()) == liveFunctions.end()) { + liveFunctions.insert(call->getName()); + pushFunction(call->getName()); + } + } + + const TIntermediate& intermediate; + typedef std::unordered_set TLiveFunctions; + TLiveFunctions liveFunctions; + bool traverseAll; + +private: + // prevent copy & copy construct + TLiveTraverser(TLiveTraverser&); + TLiveTraverser& operator=(TLiveTraverser&); +}; + +} // namespace glslang diff --git a/android/armeabi-v7a/include/glslang/MachineIndependent/ParseHelper.h b/android/armeabi-v7a/include/glslang/MachineIndependent/ParseHelper.h new file mode 100644 index 00000000..20df6405 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/MachineIndependent/ParseHelper.h @@ -0,0 +1,525 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +// +// This header defines a two-level parse-helper hierarchy, derived from +// TParseVersions: +// - TParseContextBase: sharable across multiple parsers +// - TParseContext: GLSL specific helper +// + +#ifndef _PARSER_HELPER_INCLUDED_ +#define _PARSER_HELPER_INCLUDED_ + +#include +#include + +#include "parseVersions.h" +#include "../Include/ShHandle.h" +#include "SymbolTable.h" +#include "localintermediate.h" +#include "Scan.h" +#include "attribute.h" + +namespace glslang { + +struct TPragma { + TPragma(bool o, bool d) : optimize(o), debug(d) { } + bool optimize; + bool debug; + TPragmaTable pragmaTable; +}; + +class TScanContext; +class TPpContext; + +typedef std::set TIdSetType; + +// +// Sharable code (as well as what's in TParseVersions) across +// parse helpers. +// +class TParseContextBase : public TParseVersions { +public: + TParseContextBase(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins, int version, + EProfile profile, const SpvVersion& spvVersion, EShLanguage language, + TInfoSink& infoSink, bool forwardCompatible, EShMessages messages, + const TString* entryPoint = nullptr) + : TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages), + scopeMangler("::"), + symbolTable(symbolTable), + statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0), + postEntryPointReturn(false), + contextPragma(true, false), + beginInvocationInterlockCount(0), endInvocationInterlockCount(0), + parsingBuiltins(parsingBuiltins), scanContext(nullptr), ppContext(nullptr), + limits(resources.limits), + globalUniformBlock(nullptr), + globalUniformBinding(TQualifier::layoutBindingEnd), + globalUniformSet(TQualifier::layoutSetEnd) + { + if (entryPoint != nullptr) + sourceEntryPointName = *entryPoint; + } + virtual ~TParseContextBase() { } + +#if !defined(GLSLANG_WEB) || defined(GLSLANG_WEB_DEVEL) + virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...); + virtual void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...); + virtual void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...); + virtual void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...); +#endif + + virtual void setLimits(const TBuiltInResource&) = 0; + + void checkIndex(const TSourceLoc&, const TType&, int& index); + + EShLanguage getLanguage() const { return language; } + void setScanContext(TScanContext* c) { scanContext = c; } + TScanContext* getScanContext() const { return scanContext; } + void setPpContext(TPpContext* c) { ppContext = c; } + TPpContext* getPpContext() const { return ppContext; } + + virtual void setLineCallback(const std::function& func) { lineCallback = func; } + virtual void setExtensionCallback(const std::function& func) { extensionCallback = func; } + virtual void setVersionCallback(const std::function& func) { versionCallback = func; } + virtual void setPragmaCallback(const std::function&)>& func) { pragmaCallback = func; } + virtual void setErrorCallback(const std::function& func) { errorCallback = func; } + + virtual void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) = 0; + virtual bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) = 0; + virtual bool lineDirectiveShouldSetNextLine() const = 0; + virtual void handlePragma(const TSourceLoc&, const TVector&) = 0; + + virtual bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) = 0; + + virtual void notifyVersion(int line, int version, const char* type_string) + { + if (versionCallback) + versionCallback(line, version, type_string); + } + virtual void notifyErrorDirective(int line, const char* error_message) + { + if (errorCallback) + errorCallback(line, error_message); + } + virtual void notifyLineDirective(int curLineNo, int newLineNo, bool hasSource, int sourceNum, const char* sourceName) + { + if (lineCallback) + lineCallback(curLineNo, newLineNo, hasSource, sourceNum, sourceName); + } + virtual void notifyExtensionDirective(int line, const char* extension, const char* behavior) + { + if (extensionCallback) + extensionCallback(line, extension, behavior); + } + +#ifdef ENABLE_HLSL + // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL) + virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr); +#endif + + // Potentially rename shader entry point function + void renameShaderFunction(TString*& name) const + { + // Replace the entry point name given in the shader with the real entry point name, + // if there is a substitution. + if (name != nullptr && *name == sourceEntryPointName && intermediate.getEntryPointName().size() > 0) + name = NewPoolTString(intermediate.getEntryPointName().c_str()); + } + + virtual bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*); + virtual void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*); + + const char* const scopeMangler; + + // Basic parsing state, easily accessible to the grammar + + TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile + int statementNestingLevel; // 0 if outside all flow control or compound statements + int loopNestingLevel; // 0 if outside all loops + int structNestingLevel; // 0 if outside blocks and structures + int controlFlowNestingLevel; // 0 if outside all flow control + const TType* currentFunctionType; // the return type of the function that's currently being parsed + bool functionReturnsValue; // true if a non-void function has a return + // if inside a function, true if the function is the entry point and this is after a return statement + bool postEntryPointReturn; + // case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting + TList switchSequenceStack; + // the statementNestingLevel the current switch statement is at, which must match the level of its case statements + TList switchLevel; + struct TPragma contextPragma; + int beginInvocationInterlockCount; + int endInvocationInterlockCount; + +protected: + TParseContextBase(TParseContextBase&); + TParseContextBase& operator=(TParseContextBase&); + + const bool parsingBuiltins; // true if parsing built-in symbols/functions + TVector linkageSymbols; // will be transferred to 'linkage', after all editing is done, order preserving + TScanContext* scanContext; + TPpContext* ppContext; + TBuiltInResource resources; + TLimits& limits; + TString sourceEntryPointName; + + // These, if set, will be called when a line, pragma ... is preprocessed. + // They will be called with any parameters to the original directive. + std::function lineCallback; + std::function&)> pragmaCallback; + std::function versionCallback; + std::function extensionCallback; + std::function errorCallback; + + // see implementation for detail + const TFunction* selectFunction(const TVector, const TFunction&, + std::function, + std::function, + /* output */ bool& tie); + + virtual void parseSwizzleSelector(const TSourceLoc&, const TString&, int size, + TSwizzleSelectors&); + + // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL) + TVariable* globalUniformBlock; // the actual block, inserted into the symbol table + unsigned int globalUniformBinding; // the block's binding number + unsigned int globalUniformSet; // the block's set number + int firstNewMember; // the index of the first member not yet inserted into the symbol table + // override this to set the language-specific name + virtual const char* getGlobalUniformBlockName() const { return ""; } + virtual void setUniformBlockDefaults(TType&) const { } + virtual void finalizeGlobalUniformBlockLayout(TVariable&) { } + virtual void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, TPrefixType prefix, + va_list args); + virtual void trackLinkage(TSymbol& symbol); + virtual void makeEditable(TSymbol*&); + virtual TVariable* getEditableVariable(const char* name); + virtual void finish(); +}; + +// +// Manage the state for when to respect precision qualifiers and when to warn about +// the defaults being different than might be expected. +// +class TPrecisionManager { +public: + TPrecisionManager() : obey(false), warn(false), explicitIntDefault(false), explicitFloatDefault(false){ } + virtual ~TPrecisionManager() {} + + void respectPrecisionQualifiers() { obey = true; } + bool respectingPrecisionQualifiers() const { return obey; } + bool shouldWarnAboutDefaults() const { return warn; } + void defaultWarningGiven() { warn = false; } + void warnAboutDefaults() { warn = true; } + void explicitIntDefaultSeen() + { + explicitIntDefault = true; + if (explicitFloatDefault) + warn = false; + } + void explicitFloatDefaultSeen() + { + explicitFloatDefault = true; + if (explicitIntDefault) + warn = false; + } + +protected: + bool obey; // respect precision qualifiers + bool warn; // need to give a warning about the defaults + bool explicitIntDefault; // user set the default for int/uint + bool explicitFloatDefault; // user set the default for float +}; + +// +// GLSL-specific parse helper. Should have GLSL in the name, but that's +// too big of a change for comparing branches at the moment, and perhaps +// impacts downstream consumers as well. +// +class TParseContext : public TParseContextBase { +public: + TParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins, int version, EProfile, const SpvVersion& spvVersion, EShLanguage, TInfoSink&, + bool forwardCompatible = false, EShMessages messages = EShMsgDefault, + const TString* entryPoint = nullptr); + virtual ~TParseContext(); + + bool obeyPrecisionQualifiers() const { return precisionManager.respectingPrecisionQualifiers(); } + void setPrecisionDefaults(); + + void setLimits(const TBuiltInResource&) override; + bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) override; + void parserError(const char* s); // for bison's yyerror + + void reservedErrorCheck(const TSourceLoc&, const TString&); + void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) override; + bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) override; + bool lineDirectiveShouldSetNextLine() const override; + bool builtInName(const TString&); + + void handlePragma(const TSourceLoc&, const TVector&) override; + TIntermTyped* handleVariable(const TSourceLoc&, TSymbol* symbol, const TString* string); + TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index); + void handleIndexLimits(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index); + +#ifndef GLSLANG_WEB + void makeEditable(TSymbol*&) override; + void ioArrayCheck(const TSourceLoc&, const TType&, const TString& identifier); +#endif + bool isIoResizeArray(const TType&) const; + void fixIoArraySize(const TSourceLoc&, TType&); + void handleIoResizeArrayAccess(const TSourceLoc&, TIntermTyped* base); + void checkIoArraysConsistency(const TSourceLoc&, bool tailOnly = false); + int getIoArrayImplicitSize(const TQualifier&, TString* featureString = nullptr) const; + void checkIoArrayConsistency(const TSourceLoc&, int requiredSize, const char* feature, TType&, const TString&); + + TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right); + TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode); + TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field); + void blockMemberExtensionCheck(const TSourceLoc&, const TIntermTyped* base, int member, const TString& memberName); + TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype); + TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&); + TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*); + TIntermTyped* handleBuiltInFunctionCall(TSourceLoc, TIntermNode* arguments, const TFunction& function); + void computeBuiltinPrecisions(TIntermTyped&, const TFunction&); + TIntermNode* handleReturnValue(const TSourceLoc&, TIntermTyped*); + void checkLocation(const TSourceLoc&, TOperator); + TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*); + void addInputArgumentConversions(const TFunction&, TIntermNode*&) const; + TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const; + void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&); + void nonOpBuiltInCheck(const TSourceLoc&, const TFunction&, TIntermAggregate&); + void userFunctionCallCheck(const TSourceLoc&, TIntermAggregate&); + void samplerConstructorLocationCheck(const TSourceLoc&, const char* token, TIntermNode*); + TFunction* handleConstructorCall(const TSourceLoc&, const TPublicType&); + void handlePrecisionQualifier(const TSourceLoc&, TQualifier&, TPrecisionQualifier); + void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier); + void memorySemanticsCheck(const TSourceLoc&, const TFunction&, const TIntermOperator& callNode); + + void assignError(const TSourceLoc&, const char* op, TString left, TString right); + void unaryOpError(const TSourceLoc&, const char* op, TString operand); + void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right); + void variableCheck(TIntermTyped*& nodePtr); + bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override; + void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override; + void constantValueCheck(TIntermTyped* node, const char* token); + void integerCheck(const TIntermTyped* node, const char* token); + void globalCheck(const TSourceLoc&, const char* token); + bool constructorError(const TSourceLoc&, TIntermNode*, TFunction&, TOperator, TType&); + bool constructorTextureSamplerError(const TSourceLoc&, const TFunction&); + void arraySizeCheck(const TSourceLoc&, TIntermTyped* expr, TArraySize&, const char *sizeType); + bool arrayQualifierError(const TSourceLoc&, const TQualifier&); + bool arrayError(const TSourceLoc&, const TType&); + void arraySizeRequiredCheck(const TSourceLoc&, const TArraySizes&); + void structArrayCheck(const TSourceLoc&, const TType& structure); + void arraySizesCheck(const TSourceLoc&, const TQualifier&, TArraySizes*, const TIntermTyped* initializer, bool lastMember); + void arrayOfArrayVersionCheck(const TSourceLoc&, const TArraySizes*); + bool voidErrorCheck(const TSourceLoc&, const TString&, TBasicType); + void boolCheck(const TSourceLoc&, const TIntermTyped*); + void boolCheck(const TSourceLoc&, const TPublicType&); + void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer); + void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier); + void accStructCheck(const TSourceLoc & loc, const TType & type, const TString & identifier); + void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier); + void memberQualifierCheck(glslang::TPublicType&); + void globalQualifierFixCheck(const TSourceLoc&, TQualifier&); + void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&); + bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType); + void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force); + void setDefaultPrecision(const TSourceLoc&, TPublicType&, TPrecisionQualifier); + int computeSamplerTypeIndex(TSampler&); + TPrecisionQualifier getDefaultPrecision(TPublicType&); + void precisionQualifierCheck(const TSourceLoc&, TBasicType, TQualifier&); + void parameterTypeCheck(const TSourceLoc&, TStorageQualifier qualifier, const TType& type); + bool containsFieldWithBasicType(const TType& type ,TBasicType basicType); + TSymbol* redeclareBuiltinVariable(const TSourceLoc&, const TString&, const TQualifier&, const TShaderQualifiers&); + void redeclareBuiltinBlock(const TSourceLoc&, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes); + void paramCheckFixStorage(const TSourceLoc&, const TStorageQualifier&, TType& type); + void paramCheckFix(const TSourceLoc&, const TQualifier&, TType& type); + void nestedBlockCheck(const TSourceLoc&); + void nestedStructCheck(const TSourceLoc&); + void arrayObjectCheck(const TSourceLoc&, const TType&, const char* op); + void opaqueCheck(const TSourceLoc&, const TType&, const char* op); + void referenceCheck(const TSourceLoc&, const TType&, const char* op); + void storage16BitAssignmentCheck(const TSourceLoc&, const TType&, const char* op); + void specializationCheck(const TSourceLoc&, const TType&, const char* op); + void structTypeCheck(const TSourceLoc&, TPublicType&); + void inductiveLoopCheck(const TSourceLoc&, TIntermNode* init, TIntermLoop* loop); + void arrayLimitCheck(const TSourceLoc&, const TString&, int size); + void limitCheck(const TSourceLoc&, int value, const char* limit, const char* feature); + + void inductiveLoopBodyCheck(TIntermNode*, int loopIndexId, TSymbolTable&); + void constantIndexExpressionCheck(TIntermNode*); + + void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&); + void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&, const TIntermTyped*); + void mergeObjectLayoutQualifiers(TQualifier& dest, const TQualifier& src, bool inheritOnly); + void layoutObjectCheck(const TSourceLoc&, const TSymbol&); + void layoutMemberLocationArrayCheck(const TSourceLoc&, bool memberWithLocation, TArraySizes* arraySizes); + void layoutTypeCheck(const TSourceLoc&, const TType&); + void layoutQualifierCheck(const TSourceLoc&, const TQualifier&); + void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&); + void fixOffset(const TSourceLoc&, TSymbol&); + + const TFunction* findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn); + const TFunction* findFunctionExact(const TSourceLoc& loc, const TFunction& call, bool& builtIn); + const TFunction* findFunction120(const TSourceLoc& loc, const TFunction& call, bool& builtIn); + const TFunction* findFunction400(const TSourceLoc& loc, const TFunction& call, bool& builtIn); + const TFunction* findFunctionExplicitTypes(const TSourceLoc& loc, const TFunction& call, bool& builtIn); + void declareTypeDefaults(const TSourceLoc&, const TPublicType&); + TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, const TPublicType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0); + TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&); + TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&); + TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset); + void inheritMemoryQualifiers(const TQualifier& from, TQualifier& to); + void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0); + void blockStageIoCheck(const TSourceLoc&, const TQualifier&); + void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName); + void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation); + void fixXfbOffsets(TQualifier&, TTypeList&); + void fixBlockUniformOffsets(TQualifier&, TTypeList&); + void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier); + void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&); + void invariantCheck(const TSourceLoc&, const TQualifier&); + void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&); + void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode); + TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body); + +#ifndef GLSLANG_WEB + TAttributeType attributeFromName(const TString& name) const; + TAttributes* makeAttributes(const TString& identifier) const; + TAttributes* makeAttributes(const TString& identifier, TIntermNode* node) const; + TAttributes* mergeAttributes(TAttributes*, TAttributes*) const; + + // Determine selection control from attributes + void handleSelectionAttributes(const TAttributes& attributes, TIntermNode*); + void handleSwitchAttributes(const TAttributes& attributes, TIntermNode*); + // Determine loop control from attributes + void handleLoopAttributes(const TAttributes& attributes, TIntermNode*); +#endif + + void checkAndResizeMeshViewDim(const TSourceLoc&, TType&, bool isBlockMember); + +protected: + void nonInitConstCheck(const TSourceLoc&, TString& identifier, TType& type); + void inheritGlobalDefaults(TQualifier& dst) const; + TVariable* makeInternalVariable(const char* name, const TType&) const; + TVariable* declareNonArray(const TSourceLoc&, const TString& identifier, const TType&); + void declareArray(const TSourceLoc&, const TString& identifier, const TType&, TSymbol*&); + void checkRuntimeSizable(const TSourceLoc&, const TIntermTyped&); + bool isRuntimeLength(const TIntermTyped&) const; + TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable); + TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer); +#ifndef GLSLANG_WEB + void finish() override; +#endif + +public: + // + // Generally, bison productions, the scanner, and the PP need read/write access to these; just give them direct access + // + + // Current state of parsing + bool inMain; // if inside a function, true if the function is main + const TString* blockName; + TQualifier currentBlockQualifier; + TPrecisionQualifier defaultPrecision[EbtNumTypes]; + TBuiltInResource resources; + TLimits& limits; + +protected: + TParseContext(TParseContext&); + TParseContext& operator=(TParseContext&); + + static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2 * 2 * 2 * 2)); // see computeSamplerTypeIndex() + TPrecisionQualifier defaultSamplerPrecision[maxSamplerIndex]; + TPrecisionManager precisionManager; + TQualifier globalBufferDefaults; + TQualifier globalUniformDefaults; + TQualifier globalInputDefaults; + TQualifier globalOutputDefaults; + TString currentCaller; // name of last function body entered (not valid when at global scope) +#ifndef GLSLANG_WEB + int* atomicUintOffsets; // to become an array of the right size to hold an offset per binding point + bool anyIndexLimits; + TIdSetType inductiveLoopIds; + TVector needsIndexLimitationChecking; + + // + // Geometry shader input arrays: + // - array sizing is based on input primitive and/or explicit size + // + // Tessellation control output arrays: + // - array sizing is based on output layout(vertices=...) and/or explicit size + // + // Both: + // - array sizing is retroactive + // - built-in block redeclarations interact with this + // + // Design: + // - use a per-context "resize-list", a list of symbols whose array sizes + // can be fixed + // + // - the resize-list starts empty at beginning of user-shader compilation, it does + // not have built-ins in it + // + // - on built-in array use: copyUp() symbol and add it to the resize-list + // + // - on user array declaration: add it to the resize-list + // + // - on block redeclaration: copyUp() symbol and add it to the resize-list + // * note, that appropriately gives an error if redeclaring a block that + // was already used and hence already copied-up + // + // - on seeing a layout declaration that sizes the array, fix everything in the + // resize-list, giving errors for mismatch + // + // - on seeing an array size declaration, give errors on mismatch between it and previous + // array-sizing declarations + // + TVector ioArraySymbolResizeList; +#endif +}; + +} // end namespace glslang + +#endif // _PARSER_HELPER_INCLUDED_ diff --git a/android/armeabi-v7a/include/glslang/MachineIndependent/RemoveTree.h b/android/armeabi-v7a/include/glslang/MachineIndependent/RemoveTree.h new file mode 100644 index 00000000..1ed01562 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/MachineIndependent/RemoveTree.h @@ -0,0 +1,41 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#pragma once + +namespace glslang { + +void RemoveAllTreeNodes(TIntermNode*); + +} // end namespace glslang diff --git a/android/armeabi-v7a/include/glslang/MachineIndependent/Scan.h b/android/armeabi-v7a/include/glslang/MachineIndependent/Scan.h new file mode 100644 index 00000000..24b75cf7 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/MachineIndependent/Scan.h @@ -0,0 +1,276 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +#ifndef _GLSLANG_SCAN_INCLUDED_ +#define _GLSLANG_SCAN_INCLUDED_ + +#include "Versions.h" + +namespace glslang { + +// Use a global end-of-input character, so no translation is needed across +// layers of encapsulation. Characters are all 8 bit, and positive, so there is +// no aliasing of character 255 onto -1, for example. +const int EndOfInput = -1; + +// +// A character scanner that seamlessly, on read-only strings, reads across an +// array of strings without assuming null termination. +// +class TInputScanner { +public: + TInputScanner(int n, const char* const s[], size_t L[], const char* const* names = nullptr, + int b = 0, int f = 0, bool single = false) : + numSources(n), + // up to this point, common usage is "char*", but now we need positive 8-bit characters + sources(reinterpret_cast(s)), + lengths(L), currentSource(0), currentChar(0), stringBias(b), finale(f), singleLogical(single), + endOfFileReached(false) + { + loc = new TSourceLoc[numSources]; + for (int i = 0; i < numSources; ++i) { + loc[i].init(i - stringBias); + } + if (names != nullptr) { + for (int i = 0; i < numSources; ++i) + loc[i].name = names[i] != nullptr ? NewPoolTString(names[i]) : nullptr; + } + loc[currentSource].line = 1; + logicalSourceLoc.init(1); + logicalSourceLoc.name = loc[0].name; + } + + virtual ~TInputScanner() + { + delete [] loc; + } + + // retrieve the next character and advance one character + int get() + { + int ret = peek(); + if (ret == EndOfInput) + return ret; + ++loc[currentSource].column; + ++logicalSourceLoc.column; + if (ret == '\n') { + ++loc[currentSource].line; + ++logicalSourceLoc.line; + logicalSourceLoc.column = 0; + loc[currentSource].column = 0; + } + advance(); + + return ret; + } + + // retrieve the next character, no advance + int peek() + { + if (currentSource >= numSources) { + endOfFileReached = true; + return EndOfInput; + } + // Make sure we do not read off the end of a string. + // N.B. Sources can have a length of 0. + int sourceToRead = currentSource; + size_t charToRead = currentChar; + while(charToRead >= lengths[sourceToRead]) { + charToRead = 0; + sourceToRead += 1; + if (sourceToRead >= numSources) { + return EndOfInput; + } + } + + // Here, we care about making negative valued characters positive + return sources[sourceToRead][charToRead]; + } + + // go back one character + void unget() + { + // Do not roll back once we've reached the end of the file. + if (endOfFileReached) + return; + + if (currentChar > 0) { + --currentChar; + --loc[currentSource].column; + --logicalSourceLoc.column; + if (loc[currentSource].column < 0) { + // We've moved back past a new line. Find the + // previous newline (or start of the file) to compute + // the column count on the now current line. + size_t chIndex = currentChar; + while (chIndex > 0) { + if (sources[currentSource][chIndex] == '\n') { + break; + } + --chIndex; + } + logicalSourceLoc.column = (int)(currentChar - chIndex); + loc[currentSource].column = (int)(currentChar - chIndex); + } + } else { + do { + --currentSource; + } while (currentSource > 0 && lengths[currentSource] == 0); + if (lengths[currentSource] == 0) { + // set to 0 if we've backed up to the start of an empty string + currentChar = 0; + } else + currentChar = lengths[currentSource] - 1; + } + if (peek() == '\n') { + --loc[currentSource].line; + --logicalSourceLoc.line; + } + } + + // for #line override + void setLine(int newLine) + { + logicalSourceLoc.line = newLine; + loc[getLastValidSourceIndex()].line = newLine; + } + + // for #line override in filename based parsing + void setFile(const char* filename) + { + TString* fn_tstr = NewPoolTString(filename); + logicalSourceLoc.name = fn_tstr; + loc[getLastValidSourceIndex()].name = fn_tstr; + } + + void setFile(const char* filename, int i) + { + TString* fn_tstr = NewPoolTString(filename); + if (i == getLastValidSourceIndex()) { + logicalSourceLoc.name = fn_tstr; + } + loc[i].name = fn_tstr; + } + + void setString(int newString) + { + logicalSourceLoc.string = newString; + loc[getLastValidSourceIndex()].string = newString; + logicalSourceLoc.name = nullptr; + loc[getLastValidSourceIndex()].name = nullptr; + } + + // for #include content indentation + void setColumn(int col) + { + logicalSourceLoc.column = col; + loc[getLastValidSourceIndex()].column = col; + } + + void setEndOfInput() + { + endOfFileReached = true; + currentSource = numSources; + } + + bool atEndOfInput() const { return endOfFileReached; } + + const TSourceLoc& getSourceLoc() const + { + if (singleLogical) { + return logicalSourceLoc; + } else { + return loc[std::max(0, std::min(currentSource, numSources - finale - 1))]; + } + } + // Returns the index (starting from 0) of the most recent valid source string we are reading from. + int getLastValidSourceIndex() const { return std::min(currentSource, numSources - 1); } + + void consumeWhiteSpace(bool& foundNonSpaceTab); + bool consumeComment(); + void consumeWhitespaceComment(bool& foundNonSpaceTab); + bool scanVersion(int& version, EProfile& profile, bool& notFirstToken); + +protected: + + // advance one character + void advance() + { + ++currentChar; + if (currentChar >= lengths[currentSource]) { + ++currentSource; + if (currentSource < numSources) { + loc[currentSource].string = loc[currentSource - 1].string + 1; + loc[currentSource].line = 1; + loc[currentSource].column = 0; + } + while (currentSource < numSources && lengths[currentSource] == 0) { + ++currentSource; + if (currentSource < numSources) { + loc[currentSource].string = loc[currentSource - 1].string + 1; + loc[currentSource].line = 1; + loc[currentSource].column = 0; + } + } + currentChar = 0; + } + } + + int numSources; // number of strings in source + const unsigned char* const *sources; // array of strings; must be converted to positive values on use, to avoid aliasing with -1 as EndOfInput + const size_t *lengths; // length of each string + int currentSource; + size_t currentChar; + + // This is for reporting what string/line an error occurred on, and can be overridden by #line. + // It remembers the last state of each source string as it is left for the next one, so unget() + // can restore that state. + TSourceLoc* loc; // an array + + int stringBias; // the first string that is the user's string number 0 + int finale; // number of internal strings after user's last string + + TSourceLoc logicalSourceLoc; + bool singleLogical; // treats the strings as a single logical string. + // locations will be reported from the first string. + + // Set to true once peek() returns EndOfFile, so that we won't roll back + // once we've reached EndOfFile. + bool endOfFileReached; +}; + +} // end namespace glslang + +#endif // _GLSLANG_SCAN_INCLUDED_ diff --git a/android/armeabi-v7a/include/glslang/MachineIndependent/ScanContext.h b/android/armeabi-v7a/include/glslang/MachineIndependent/ScanContext.h new file mode 100644 index 00000000..74b2b3c7 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/MachineIndependent/ScanContext.h @@ -0,0 +1,93 @@ +// +// Copyright (C) 2013 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +// +// This holds context specific to the GLSL scanner, which +// sits between the preprocessor scanner and parser. +// + +#pragma once + +#include "ParseHelper.h" + +namespace glslang { + +class TPpContext; +class TPpToken; +class TParserToken; + +class TScanContext { +public: + explicit TScanContext(TParseContextBase& pc) : + parseContext(pc), + afterType(false), afterStruct(false), + field(false), afterBuffer(false) { } + virtual ~TScanContext() { } + + static void fillInKeywordMap(); + static void deleteKeywordMap(); + + int tokenize(TPpContext*, TParserToken&); + +protected: + TScanContext(TScanContext&); + TScanContext& operator=(TScanContext&); + + int tokenizeIdentifier(); + int identifierOrType(); + int reservedWord(); + int identifierOrReserved(bool reserved); + int es30ReservedFromGLSL(int version); + int nonreservedKeyword(int esVersion, int nonEsVersion); + int precisionKeyword(); + int matNxM(); + int dMat(); + int firstGenerationImage(bool inEs310); + int secondGenerationImage(); + + TParseContextBase& parseContext; + bool afterType; // true if we've recognized a type, so can only be looking for an identifier + bool afterStruct; // true if we've recognized the STRUCT keyword, so can only be looking for an identifier + bool field; // true if we're on a field, right after a '.' + bool afterBuffer; // true if we've recognized the BUFFER keyword + TSourceLoc loc; + TParserToken* parserToken; + TPpToken* ppToken; + + const char* tokenText; + int keyword; +}; + +} // end namespace glslang diff --git a/android/armeabi-v7a/include/glslang/MachineIndependent/SymbolTable.h b/android/armeabi-v7a/include/glslang/MachineIndependent/SymbolTable.h new file mode 100644 index 00000000..40ca3da5 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/MachineIndependent/SymbolTable.h @@ -0,0 +1,885 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _SYMBOL_TABLE_INCLUDED_ +#define _SYMBOL_TABLE_INCLUDED_ + +// +// Symbol table for parsing. Has these design characteristics: +// +// * Same symbol table can be used to compile many shaders, to preserve +// effort of creating and loading with the large numbers of built-in +// symbols. +// +// --> This requires a copy mechanism, so initial pools used to create +// the shared information can be popped. Done through "clone" +// methods. +// +// * Name mangling will be used to give each function a unique name +// so that symbol table lookups are never ambiguous. This allows +// a simpler symbol table structure. +// +// * Pushing and popping of scope, so symbol table will really be a stack +// of symbol tables. Searched from the top, with new inserts going into +// the top. +// +// * Constants: Compile time constant symbols will keep their values +// in the symbol table. The parser can substitute constants at parse +// time, including doing constant folding and constant propagation. +// +// * No temporaries: Temporaries made from operations (+, --, .xy, etc.) +// are tracked in the intermediate representation, not the symbol table. +// + +#include "../Include/Common.h" +#include "../Include/intermediate.h" +#include "../Include/InfoSink.h" + +namespace glslang { + +// +// Symbol base class. (Can build functions or variables out of these...) +// + +class TVariable; +class TFunction; +class TAnonMember; + +typedef TVector TExtensionList; + +class TSymbol { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + explicit TSymbol(const TString *n) : name(n), extensions(0), writable(true) { } + virtual TSymbol* clone() const = 0; + virtual ~TSymbol() { } // rely on all symbol owned memory coming from the pool + + virtual const TString& getName() const { return *name; } + virtual void changeName(const TString* newName) { name = newName; } + virtual void addPrefix(const char* prefix) + { + TString newName(prefix); + newName.append(*name); + changeName(NewPoolTString(newName.c_str())); + } + virtual const TString& getMangledName() const { return getName(); } + virtual TFunction* getAsFunction() { return 0; } + virtual const TFunction* getAsFunction() const { return 0; } + virtual TVariable* getAsVariable() { return 0; } + virtual const TVariable* getAsVariable() const { return 0; } + virtual const TAnonMember* getAsAnonMember() const { return 0; } + virtual const TType& getType() const = 0; + virtual TType& getWritableType() = 0; + virtual void setUniqueId(int id) { uniqueId = id; } + virtual int getUniqueId() const { return uniqueId; } + virtual void setExtensions(int numExts, const char* const exts[]) + { + assert(extensions == 0); + assert(numExts > 0); + extensions = NewPoolObject(extensions); + for (int e = 0; e < numExts; ++e) + extensions->push_back(exts[e]); + } + virtual int getNumExtensions() const { return extensions == nullptr ? 0 : (int)extensions->size(); } + virtual const char** getExtensions() const { return extensions->data(); } + +#ifndef GLSLANG_WEB + virtual void dump(TInfoSink& infoSink, bool complete = false) const = 0; + void dumpExtensions(TInfoSink& infoSink) const; +#endif + + virtual bool isReadOnly() const { return ! writable; } + virtual void makeReadOnly() { writable = false; } + +protected: + explicit TSymbol(const TSymbol&); + TSymbol& operator=(const TSymbol&); + + const TString *name; + unsigned int uniqueId; // For cross-scope comparing during code generation + + // For tracking what extensions must be present + // (don't use if correct version/profile is present). + TExtensionList* extensions; // an array of pointers to existing constant char strings + + // + // N.B.: Non-const functions that will be generally used should assert on this, + // to avoid overwriting shared symbol-table information. + // + bool writable; +}; + +// +// Variable class, meaning a symbol that's not a function. +// +// There could be a separate class hierarchy for Constant variables; +// Only one of int, bool, or float, (or none) is correct for +// any particular use, but it's easy to do this way, and doesn't +// seem worth having separate classes, and "getConst" can't simply return +// different values for different types polymorphically, so this is +// just simple and pragmatic. +// +class TVariable : public TSymbol { +public: + TVariable(const TString *name, const TType& t, bool uT = false ) + : TSymbol(name), + userType(uT), + constSubtree(nullptr), + memberExtensions(nullptr), + anonId(-1) + { type.shallowCopy(t); } + virtual TVariable* clone() const; + virtual ~TVariable() { } + + virtual TVariable* getAsVariable() { return this; } + virtual const TVariable* getAsVariable() const { return this; } + virtual const TType& getType() const { return type; } + virtual TType& getWritableType() { assert(writable); return type; } + virtual bool isUserType() const { return userType; } + virtual const TConstUnionArray& getConstArray() const { return constArray; } + virtual TConstUnionArray& getWritableConstArray() { assert(writable); return constArray; } + virtual void setConstArray(const TConstUnionArray& array) { constArray = array; } + virtual void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; } + virtual TIntermTyped* getConstSubtree() const { return constSubtree; } + virtual void setAnonId(int i) { anonId = i; } + virtual int getAnonId() const { return anonId; } + + virtual void setMemberExtensions(int member, int numExts, const char* const exts[]) + { + assert(type.isStruct()); + assert(numExts > 0); + if (memberExtensions == nullptr) { + memberExtensions = NewPoolObject(memberExtensions); + memberExtensions->resize(type.getStruct()->size()); + } + for (int e = 0; e < numExts; ++e) + (*memberExtensions)[member].push_back(exts[e]); + } + virtual bool hasMemberExtensions() const { return memberExtensions != nullptr; } + virtual int getNumMemberExtensions(int member) const + { + return memberExtensions == nullptr ? 0 : (int)(*memberExtensions)[member].size(); + } + virtual const char** getMemberExtensions(int member) const { return (*memberExtensions)[member].data(); } + +#ifndef GLSLANG_WEB + virtual void dump(TInfoSink& infoSink, bool complete = false) const; +#endif + +protected: + explicit TVariable(const TVariable&); + TVariable& operator=(const TVariable&); + + TType type; + bool userType; + + // we are assuming that Pool Allocator will free the memory allocated to unionArray + // when this object is destroyed + + TConstUnionArray constArray; // for compile-time constant value + TIntermTyped* constSubtree; // for specialization constant computation + TVector* memberExtensions; // per-member extension list, allocated only when needed + int anonId; // the ID used for anonymous blocks: TODO: see if uniqueId could serve a dual purpose +}; + +// +// The function sub-class of symbols and the parser will need to +// share this definition of a function parameter. +// +struct TParameter { + TString *name; + TType* type; + TIntermTyped* defaultValue; + void copyParam(const TParameter& param) + { + if (param.name) + name = NewPoolTString(param.name->c_str()); + else + name = 0; + type = param.type->clone(); + defaultValue = param.defaultValue; + } + TBuiltInVariable getDeclaredBuiltIn() const { return type->getQualifier().declaredBuiltIn; } +}; + +// +// The function sub-class of a symbol. +// +class TFunction : public TSymbol { +public: + explicit TFunction(TOperator o) : + TSymbol(0), + op(o), + defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0) { } + TFunction(const TString *name, const TType& retType, TOperator tOp = EOpNull) : + TSymbol(name), + mangledName(*name + '('), + op(tOp), + defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0) + { + returnType.shallowCopy(retType); + declaredBuiltIn = retType.getQualifier().builtIn; + } + virtual TFunction* clone() const override; + virtual ~TFunction(); + + virtual TFunction* getAsFunction() override { return this; } + virtual const TFunction* getAsFunction() const override { return this; } + + // Install 'p' as the (non-'this') last parameter. + // Non-'this' parameters are reflected in both the list of parameters and the + // mangled name. + virtual void addParameter(TParameter& p) + { + assert(writable); + parameters.push_back(p); + p.type->appendMangledName(mangledName); + + if (p.defaultValue != nullptr) + defaultParamCount++; + } + + // Install 'this' as the first parameter. + // 'this' is reflected in the list of parameters, but not the mangled name. + virtual void addThisParameter(TType& type, const char* name) + { + TParameter p = { NewPoolTString(name), new TType, nullptr }; + p.type->shallowCopy(type); + parameters.insert(parameters.begin(), p); + } + + virtual void addPrefix(const char* prefix) override + { + TSymbol::addPrefix(prefix); + mangledName.insert(0, prefix); + } + + virtual void removePrefix(const TString& prefix) + { + assert(mangledName.compare(0, prefix.size(), prefix) == 0); + mangledName.erase(0, prefix.size()); + } + + virtual const TString& getMangledName() const override { return mangledName; } + virtual const TType& getType() const override { return returnType; } + virtual TBuiltInVariable getDeclaredBuiltInType() const { return declaredBuiltIn; } + virtual TType& getWritableType() override { return returnType; } + virtual void relateToOperator(TOperator o) { assert(writable); op = o; } + virtual TOperator getBuiltInOp() const { return op; } + virtual void setDefined() { assert(writable); defined = true; } + virtual bool isDefined() const { return defined; } + virtual void setPrototyped() { assert(writable); prototyped = true; } + virtual bool isPrototyped() const { return prototyped; } + virtual void setImplicitThis() { assert(writable); implicitThis = true; } + virtual bool hasImplicitThis() const { return implicitThis; } + virtual void setIllegalImplicitThis() { assert(writable); illegalImplicitThis = true; } + virtual bool hasIllegalImplicitThis() const { return illegalImplicitThis; } + + // Return total number of parameters + virtual int getParamCount() const { return static_cast(parameters.size()); } + // Return number of parameters with default values. + virtual int getDefaultParamCount() const { return defaultParamCount; } + // Return number of fixed parameters (without default values) + virtual int getFixedParamCount() const { return getParamCount() - getDefaultParamCount(); } + + virtual TParameter& operator[](int i) { assert(writable); return parameters[i]; } + virtual const TParameter& operator[](int i) const { return parameters[i]; } + +#ifndef GLSLANG_WEB + virtual void dump(TInfoSink& infoSink, bool complete = false) const override; +#endif + +protected: + explicit TFunction(const TFunction&); + TFunction& operator=(const TFunction&); + + typedef TVector TParamList; + TParamList parameters; + TType returnType; + TBuiltInVariable declaredBuiltIn; + + TString mangledName; + TOperator op; + bool defined; + bool prototyped; + bool implicitThis; // True if this function is allowed to see all members of 'this' + bool illegalImplicitThis; // True if this function is not supposed to have access to dynamic members of 'this', + // even if it finds member variables in the symbol table. + // This is important for a static member function that has member variables in scope, + // but is not allowed to use them, or see hidden symbols instead. + int defaultParamCount; +}; + +// +// Members of anonymous blocks are a kind of TSymbol. They are not hidden in +// the symbol table behind a container; rather they are visible and point to +// their anonymous container. (The anonymous container is found through the +// member, not the other way around.) +// +class TAnonMember : public TSymbol { +public: + TAnonMember(const TString* n, unsigned int m, TVariable& a, int an) : TSymbol(n), anonContainer(a), memberNumber(m), anonId(an) { } + virtual TAnonMember* clone() const override; + virtual ~TAnonMember() { } + + virtual const TAnonMember* getAsAnonMember() const override { return this; } + virtual const TVariable& getAnonContainer() const { return anonContainer; } + virtual unsigned int getMemberNumber() const { return memberNumber; } + + virtual const TType& getType() const override + { + const TTypeList& types = *anonContainer.getType().getStruct(); + return *types[memberNumber].type; + } + + virtual TType& getWritableType() override + { + assert(writable); + const TTypeList& types = *anonContainer.getType().getStruct(); + return *types[memberNumber].type; + } + + virtual void setExtensions(int numExts, const char* const exts[]) override + { + anonContainer.setMemberExtensions(memberNumber, numExts, exts); + } + virtual int getNumExtensions() const override { return anonContainer.getNumMemberExtensions(memberNumber); } + virtual const char** getExtensions() const override { return anonContainer.getMemberExtensions(memberNumber); } + + virtual int getAnonId() const { return anonId; } +#ifndef GLSLANG_WEB + virtual void dump(TInfoSink& infoSink, bool complete = false) const override; +#endif + +protected: + explicit TAnonMember(const TAnonMember&); + TAnonMember& operator=(const TAnonMember&); + + TVariable& anonContainer; + unsigned int memberNumber; + int anonId; +}; + +class TSymbolTableLevel { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + TSymbolTableLevel() : defaultPrecision(0), anonId(0), thisLevel(false) { } + ~TSymbolTableLevel(); + + bool insert(TSymbol& symbol, bool separateNameSpaces) + { + // + // returning true means symbol was added to the table with no semantic errors + // + const TString& name = symbol.getName(); + if (name == "") { + symbol.getAsVariable()->setAnonId(anonId++); + // An empty name means an anonymous container, exposing its members to the external scope. + // Give it a name and insert its members in the symbol table, pointing to the container. + char buf[20]; + snprintf(buf, 20, "%s%d", AnonymousPrefix, symbol.getAsVariable()->getAnonId()); + symbol.changeName(NewPoolTString(buf)); + + return insertAnonymousMembers(symbol, 0); + } else { + // Check for redefinition errors: + // - STL itself will tell us if there is a direct name collision, with name mangling, at this level + // - additionally, check for function-redefining-variable name collisions + const TString& insertName = symbol.getMangledName(); + if (symbol.getAsFunction()) { + // make sure there isn't a variable of this name + if (! separateNameSpaces && level.find(name) != level.end()) + return false; + + // insert, and whatever happens is okay + level.insert(tLevelPair(insertName, &symbol)); + + return true; + } else + return level.insert(tLevelPair(insertName, &symbol)).second; + } + } + + // Add more members to an already inserted aggregate object + bool amend(TSymbol& symbol, int firstNewMember) + { + // See insert() for comments on basic explanation of insert. + // This operates similarly, but more simply. + // Only supporting amend of anonymous blocks so far. + if (IsAnonymous(symbol.getName())) + return insertAnonymousMembers(symbol, firstNewMember); + else + return false; + } + + bool insertAnonymousMembers(TSymbol& symbol, int firstMember) + { + const TTypeList& types = *symbol.getAsVariable()->getType().getStruct(); + for (unsigned int m = firstMember; m < types.size(); ++m) { + TAnonMember* member = new TAnonMember(&types[m].type->getFieldName(), m, *symbol.getAsVariable(), symbol.getAsVariable()->getAnonId()); + if (! level.insert(tLevelPair(member->getMangledName(), member)).second) + return false; + } + + return true; + } + + TSymbol* find(const TString& name) const + { + tLevel::const_iterator it = level.find(name); + if (it == level.end()) + return 0; + else + return (*it).second; + } + + void findFunctionNameList(const TString& name, TVector& list) + { + size_t parenAt = name.find_first_of('('); + TString base(name, 0, parenAt + 1); + + tLevel::const_iterator begin = level.lower_bound(base); + base[parenAt] = ')'; // assume ')' is lexically after '(' + tLevel::const_iterator end = level.upper_bound(base); + for (tLevel::const_iterator it = begin; it != end; ++it) + list.push_back(it->second->getAsFunction()); + } + + // See if there is already a function in the table having the given non-function-style name. + bool hasFunctionName(const TString& name) const + { + tLevel::const_iterator candidate = level.lower_bound(name); + if (candidate != level.end()) { + const TString& candidateName = (*candidate).first; + TString::size_type parenAt = candidateName.find_first_of('('); + if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0) + + return true; + } + + return false; + } + + // See if there is a variable at this level having the given non-function-style name. + // Return true if name is found, and set variable to true if the name was a variable. + bool findFunctionVariableName(const TString& name, bool& variable) const + { + tLevel::const_iterator candidate = level.lower_bound(name); + if (candidate != level.end()) { + const TString& candidateName = (*candidate).first; + TString::size_type parenAt = candidateName.find_first_of('('); + if (parenAt == candidateName.npos) { + // not a mangled name + if (candidateName == name) { + // found a variable name match + variable = true; + return true; + } + } else { + // a mangled name + if (candidateName.compare(0, parenAt, name) == 0) { + // found a function name match + variable = false; + return true; + } + } + } + + return false; + } + + // Use this to do a lazy 'push' of precision defaults the first time + // a precision statement is seen in a new scope. Leave it at 0 for + // when no push was needed. Thus, it is not the current defaults, + // it is what to restore the defaults to when popping a level. + void setPreviousDefaultPrecisions(const TPrecisionQualifier *p) + { + // can call multiple times at one scope, will only latch on first call, + // as we're tracking the previous scope's values, not the current values + if (defaultPrecision != 0) + return; + + defaultPrecision = new TPrecisionQualifier[EbtNumTypes]; + for (int t = 0; t < EbtNumTypes; ++t) + defaultPrecision[t] = p[t]; + } + + void getPreviousDefaultPrecisions(TPrecisionQualifier *p) + { + // can be called for table level pops that didn't set the + // defaults + if (defaultPrecision == 0 || p == 0) + return; + + for (int t = 0; t < EbtNumTypes; ++t) + p[t] = defaultPrecision[t]; + } + + void relateToOperator(const char* name, TOperator op); + void setFunctionExtensions(const char* name, int num, const char* const extensions[]); +#ifndef GLSLANG_WEB + void dump(TInfoSink& infoSink, bool complete = false) const; +#endif + TSymbolTableLevel* clone() const; + void readOnly(); + + void setThisLevel() { thisLevel = true; } + bool isThisLevel() const { return thisLevel; } + +protected: + explicit TSymbolTableLevel(TSymbolTableLevel&); + TSymbolTableLevel& operator=(TSymbolTableLevel&); + + typedef std::map, pool_allocator > > tLevel; + typedef const tLevel::value_type tLevelPair; + typedef std::pair tInsertResult; + + tLevel level; // named mappings + TPrecisionQualifier *defaultPrecision; + int anonId; + bool thisLevel; // True if this level of the symbol table is a structure scope containing member function + // that are supposed to see anonymous access to member variables. +}; + +class TSymbolTable { +public: + TSymbolTable() : uniqueId(0), noBuiltInRedeclarations(false), separateNameSpaces(false), adoptedLevels(0) + { + // + // This symbol table cannot be used until push() is called. + // + } + ~TSymbolTable() + { + // this can be called explicitly; safest to code it so it can be called multiple times + + // don't deallocate levels passed in from elsewhere + while (table.size() > adoptedLevels) + pop(0); + } + + void adoptLevels(TSymbolTable& symTable) + { + for (unsigned int level = 0; level < symTable.table.size(); ++level) { + table.push_back(symTable.table[level]); + ++adoptedLevels; + } + uniqueId = symTable.uniqueId; + noBuiltInRedeclarations = symTable.noBuiltInRedeclarations; + separateNameSpaces = symTable.separateNameSpaces; + } + + // + // While level adopting is generic, the methods below enact a the following + // convention for levels: + // 0: common built-ins shared across all stages, all compiles, only one copy for all symbol tables + // 1: per-stage built-ins, shared across all compiles, but a different copy per stage + // 2: built-ins specific to a compile, like resources that are context-dependent, or redeclared built-ins + // 3: user-shader globals + // +protected: + static const int globalLevel = 3; + bool isSharedLevel(int level) { return level <= 1; } // exclude all per-compile levels + bool isBuiltInLevel(int level) { return level <= 2; } // exclude user globals + bool isGlobalLevel(int level) { return level <= globalLevel; } // include user globals +public: + bool isEmpty() { return table.size() == 0; } + bool atBuiltInLevel() { return isBuiltInLevel(currentLevel()); } + bool atGlobalLevel() { return isGlobalLevel(currentLevel()); } + + void setNoBuiltInRedeclarations() { noBuiltInRedeclarations = true; } + void setSeparateNameSpaces() { separateNameSpaces = true; } + + void push() + { + table.push_back(new TSymbolTableLevel); + } + + // Make a new symbol-table level to represent the scope introduced by a structure + // containing member functions, such that the member functions can find anonymous + // references to member variables. + // + // 'thisSymbol' should have a name of "" to trigger anonymous structure-member + // symbol finds. + void pushThis(TSymbol& thisSymbol) + { + assert(thisSymbol.getName().size() == 0); + table.push_back(new TSymbolTableLevel); + table.back()->setThisLevel(); + insert(thisSymbol); + } + + void pop(TPrecisionQualifier *p) + { + table[currentLevel()]->getPreviousDefaultPrecisions(p); + delete table.back(); + table.pop_back(); + } + + // + // Insert a visible symbol into the symbol table so it can + // be found later by name. + // + // Returns false if the was a name collision. + // + bool insert(TSymbol& symbol) + { + symbol.setUniqueId(++uniqueId); + + // make sure there isn't a function of this variable name + if (! separateNameSpaces && ! symbol.getAsFunction() && table[currentLevel()]->hasFunctionName(symbol.getName())) + return false; + + // check for not overloading or redefining a built-in function + if (noBuiltInRedeclarations) { + if (atGlobalLevel() && currentLevel() > 0) { + if (table[0]->hasFunctionName(symbol.getName())) + return false; + if (currentLevel() > 1 && table[1]->hasFunctionName(symbol.getName())) + return false; + } + } + + return table[currentLevel()]->insert(symbol, separateNameSpaces); + } + + // Add more members to an already inserted aggregate object + bool amend(TSymbol& symbol, int firstNewMember) + { + // See insert() for comments on basic explanation of insert. + // This operates similarly, but more simply. + return table[currentLevel()]->amend(symbol, firstNewMember); + } + + // + // To allocate an internal temporary, which will need to be uniquely + // identified by the consumer of the AST, but never need to + // found by doing a symbol table search by name, hence allowed an + // arbitrary name in the symbol with no worry of collision. + // + void makeInternalVariable(TSymbol& symbol) + { + symbol.setUniqueId(++uniqueId); + } + + // + // Copy a variable or anonymous member's structure from a shared level so that + // it can be added (soon after return) to the symbol table where it can be + // modified without impacting other users of the shared table. + // + TSymbol* copyUpDeferredInsert(TSymbol* shared) + { + if (shared->getAsVariable()) { + TSymbol* copy = shared->clone(); + copy->setUniqueId(shared->getUniqueId()); + return copy; + } else { + const TAnonMember* anon = shared->getAsAnonMember(); + assert(anon); + TVariable* container = anon->getAnonContainer().clone(); + container->changeName(NewPoolTString("")); + container->setUniqueId(anon->getAnonContainer().getUniqueId()); + return container; + } + } + + TSymbol* copyUp(TSymbol* shared) + { + TSymbol* copy = copyUpDeferredInsert(shared); + table[globalLevel]->insert(*copy, separateNameSpaces); + if (shared->getAsVariable()) + return copy; + else { + // return the copy of the anonymous member + return table[globalLevel]->find(shared->getName()); + } + } + + // Normal find of a symbol, that can optionally say whether the symbol was found + // at a built-in level or the current top-scope level. + TSymbol* find(const TString& name, bool* builtIn = 0, bool* currentScope = 0, int* thisDepthP = 0) + { + int level = currentLevel(); + TSymbol* symbol; + int thisDepth = 0; + do { + if (table[level]->isThisLevel()) + ++thisDepth; + symbol = table[level]->find(name); + --level; + } while (symbol == nullptr && level >= 0); + level++; + if (builtIn) + *builtIn = isBuiltInLevel(level); + if (currentScope) + *currentScope = isGlobalLevel(currentLevel()) || level == currentLevel(); // consider shared levels as "current scope" WRT user globals + if (thisDepthP != nullptr) { + if (! table[level]->isThisLevel()) + thisDepth = 0; + *thisDepthP = thisDepth; + } + + return symbol; + } + + // Find of a symbol that returns how many layers deep of nested + // structures-with-member-functions ('this' scopes) deep the symbol was + // found in. + TSymbol* find(const TString& name, int& thisDepth) + { + int level = currentLevel(); + TSymbol* symbol; + thisDepth = 0; + do { + if (table[level]->isThisLevel()) + ++thisDepth; + symbol = table[level]->find(name); + --level; + } while (symbol == 0 && level >= 0); + + if (! table[level + 1]->isThisLevel()) + thisDepth = 0; + + return symbol; + } + + bool isFunctionNameVariable(const TString& name) const + { + if (separateNameSpaces) + return false; + + int level = currentLevel(); + do { + bool variable; + bool found = table[level]->findFunctionVariableName(name, variable); + if (found) + return variable; + --level; + } while (level >= 0); + + return false; + } + + void findFunctionNameList(const TString& name, TVector& list, bool& builtIn) + { + // For user levels, return the set found in the first scope with a match + builtIn = false; + int level = currentLevel(); + do { + table[level]->findFunctionNameList(name, list); + --level; + } while (list.empty() && level >= globalLevel); + + if (! list.empty()) + return; + + // Gather across all built-in levels; they don't hide each other + builtIn = true; + do { + table[level]->findFunctionNameList(name, list); + --level; + } while (level >= 0); + } + + void relateToOperator(const char* name, TOperator op) + { + for (unsigned int level = 0; level < table.size(); ++level) + table[level]->relateToOperator(name, op); + } + + void setFunctionExtensions(const char* name, int num, const char* const extensions[]) + { + for (unsigned int level = 0; level < table.size(); ++level) + table[level]->setFunctionExtensions(name, num, extensions); + } + + void setVariableExtensions(const char* name, int numExts, const char* const extensions[]) + { + TSymbol* symbol = find(TString(name)); + if (symbol == nullptr) + return; + + symbol->setExtensions(numExts, extensions); + } + + void setVariableExtensions(const char* blockName, const char* name, int numExts, const char* const extensions[]) + { + TSymbol* symbol = find(TString(blockName)); + if (symbol == nullptr) + return; + TVariable* variable = symbol->getAsVariable(); + assert(variable != nullptr); + + const TTypeList& structure = *variable->getAsVariable()->getType().getStruct(); + for (int member = 0; member < (int)structure.size(); ++member) { + if (structure[member].type->getFieldName().compare(name) == 0) { + variable->setMemberExtensions(member, numExts, extensions); + return; + } + } + } + + int getMaxSymbolId() { return uniqueId; } +#ifndef GLSLANG_WEB + void dump(TInfoSink& infoSink, bool complete = false) const; +#endif + void copyTable(const TSymbolTable& copyOf); + + void setPreviousDefaultPrecisions(TPrecisionQualifier *p) { table[currentLevel()]->setPreviousDefaultPrecisions(p); } + + void readOnly() + { + for (unsigned int level = 0; level < table.size(); ++level) + table[level]->readOnly(); + } + +protected: + TSymbolTable(TSymbolTable&); + TSymbolTable& operator=(TSymbolTableLevel&); + + int currentLevel() const { return static_cast(table.size()) - 1; } + + std::vector table; + int uniqueId; // for unique identification in code generation + bool noBuiltInRedeclarations; + bool separateNameSpaces; + unsigned int adoptedLevels; +}; + +} // end namespace glslang + +#endif // _SYMBOL_TABLE_INCLUDED_ diff --git a/android/armeabi-v7a/include/glslang/MachineIndependent/Versions.h b/android/armeabi-v7a/include/glslang/MachineIndependent/Versions.h new file mode 100644 index 00000000..98a88e1d --- /dev/null +++ b/android/armeabi-v7a/include/glslang/MachineIndependent/Versions.h @@ -0,0 +1,327 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 LunarG, Inc. +// Copyright (C) 2017 ARM Limited. +// Copyright (C) 2015-2018 Google, Inc. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +#ifndef _VERSIONS_INCLUDED_ +#define _VERSIONS_INCLUDED_ + +#define LAST_ELEMENT_MARKER(x) x + +// +// Help manage multiple profiles, versions, extensions etc. +// + +// +// Profiles are set up for masking operations, so queries can be done on multiple +// profiles at the same time. +// +// Don't maintain an ordinal set of enums (0,1,2,3...) to avoid all possible +// defects from mixing the two different forms. +// +typedef enum { + EBadProfile = 0, + ENoProfile = (1 << 0), // only for desktop, before profiles showed up + ECoreProfile = (1 << 1), + ECompatibilityProfile = (1 << 2), + EEsProfile = (1 << 3), + LAST_ELEMENT_MARKER(EProfileCount), +} EProfile; + +namespace glslang { + +// +// Map from profile enum to externally readable text name. +// +inline const char* ProfileName(EProfile profile) +{ + switch (profile) { + case ENoProfile: return "none"; + case ECoreProfile: return "core"; + case ECompatibilityProfile: return "compatibility"; + case EEsProfile: return "es"; + default: return "unknown profile"; + } +} + +// +// What source rules, validation rules, target language, etc. are needed or +// desired for SPIR-V? +// +// 0 means a target or rule set is not enabled (ignore rules from that entity). +// Non-0 means to apply semantic rules arising from that version of its rule set. +// The union of all requested rule sets will be applied. +// +struct SpvVersion { + SpvVersion() : spv(0), vulkanGlsl(0), vulkan(0), openGl(0) {} + unsigned int spv; // the version of SPIR-V to target, as defined by "word 1" of the SPIR-V binary header + int vulkanGlsl; // the version of GLSL semantics for Vulkan, from GL_KHR_vulkan_glsl, for "#define VULKAN XXX" + int vulkan; // the version of Vulkan, for which SPIR-V execution environment rules to use + int openGl; // the version of GLSL semantics for OpenGL, from GL_ARB_gl_spirv, for "#define GL_SPIRV XXX" +}; + +// +// The behaviors from the GLSL "#extension extension_name : behavior" +// +typedef enum { + EBhMissing = 0, + EBhRequire, + EBhEnable, + EBhWarn, + EBhDisable, + EBhDisablePartial // use as initial state of an extension that is only partially implemented +} TExtensionBehavior; + +// +// Symbolic names for extensions. Strings may be directly used when calling the +// functions, but better to have the compiler do spelling checks. +// +const char* const E_GL_OES_texture_3D = "GL_OES_texture_3D"; +const char* const E_GL_OES_standard_derivatives = "GL_OES_standard_derivatives"; +const char* const E_GL_EXT_frag_depth = "GL_EXT_frag_depth"; +const char* const E_GL_OES_EGL_image_external = "GL_OES_EGL_image_external"; +const char* const E_GL_OES_EGL_image_external_essl3 = "GL_OES_EGL_image_external_essl3"; +const char* const E_GL_EXT_YUV_target = "GL_EXT_YUV_target"; +const char* const E_GL_EXT_shader_texture_lod = "GL_EXT_shader_texture_lod"; +const char* const E_GL_EXT_shadow_samplers = "GL_EXT_shadow_samplers"; + +const char* const E_GL_ARB_texture_rectangle = "GL_ARB_texture_rectangle"; +const char* const E_GL_3DL_array_objects = "GL_3DL_array_objects"; +const char* const E_GL_ARB_shading_language_420pack = "GL_ARB_shading_language_420pack"; +const char* const E_GL_ARB_texture_gather = "GL_ARB_texture_gather"; +const char* const E_GL_ARB_gpu_shader5 = "GL_ARB_gpu_shader5"; +const char* const E_GL_ARB_separate_shader_objects = "GL_ARB_separate_shader_objects"; +const char* const E_GL_ARB_compute_shader = "GL_ARB_compute_shader"; +const char* const E_GL_ARB_tessellation_shader = "GL_ARB_tessellation_shader"; +const char* const E_GL_ARB_enhanced_layouts = "GL_ARB_enhanced_layouts"; +const char* const E_GL_ARB_texture_cube_map_array = "GL_ARB_texture_cube_map_array"; +const char* const E_GL_ARB_texture_multisample = "GL_ARB_texture_multisample"; +const char* const E_GL_ARB_shader_texture_lod = "GL_ARB_shader_texture_lod"; +const char* const E_GL_ARB_explicit_attrib_location = "GL_ARB_explicit_attrib_location"; +const char* const E_GL_ARB_explicit_uniform_location = "GL_ARB_explicit_uniform_location"; +const char* const E_GL_ARB_shader_image_load_store = "GL_ARB_shader_image_load_store"; +const char* const E_GL_ARB_shader_atomic_counters = "GL_ARB_shader_atomic_counters"; +const char* const E_GL_ARB_shader_draw_parameters = "GL_ARB_shader_draw_parameters"; +const char* const E_GL_ARB_shader_group_vote = "GL_ARB_shader_group_vote"; +const char* const E_GL_ARB_derivative_control = "GL_ARB_derivative_control"; +const char* const E_GL_ARB_shader_texture_image_samples = "GL_ARB_shader_texture_image_samples"; +const char* const E_GL_ARB_viewport_array = "GL_ARB_viewport_array"; +const char* const E_GL_ARB_gpu_shader_int64 = "GL_ARB_gpu_shader_int64"; +const char* const E_GL_ARB_gpu_shader_fp64 = "GL_ARB_gpu_shader_fp64"; +const char* const E_GL_ARB_shader_ballot = "GL_ARB_shader_ballot"; +const char* const E_GL_ARB_sparse_texture2 = "GL_ARB_sparse_texture2"; +const char* const E_GL_ARB_sparse_texture_clamp = "GL_ARB_sparse_texture_clamp"; +const char* const E_GL_ARB_shader_stencil_export = "GL_ARB_shader_stencil_export"; +// const char* const E_GL_ARB_cull_distance = "GL_ARB_cull_distance"; // present for 4.5, but need extension control over block members +const char* const E_GL_ARB_post_depth_coverage = "GL_ARB_post_depth_coverage"; +const char* const E_GL_ARB_shader_viewport_layer_array = "GL_ARB_shader_viewport_layer_array"; +const char* const E_GL_ARB_fragment_shader_interlock = "GL_ARB_fragment_shader_interlock"; +const char* const E_GL_ARB_shader_clock = "GL_ARB_shader_clock"; +const char* const E_GL_ARB_uniform_buffer_object = "GL_ARB_uniform_buffer_object"; +const char* const E_GL_ARB_sample_shading = "GL_ARB_sample_shading"; +const char* const E_GL_ARB_shader_bit_encoding = "GL_ARB_shader_bit_encoding"; +const char* const E_GL_ARB_shader_image_size = "GL_ARB_shader_image_size"; +const char* const E_GL_ARB_shader_storage_buffer_object = "GL_ARB_shader_storage_buffer_object"; +const char* const E_GL_ARB_shading_language_packing = "GL_ARB_shading_language_packing"; +const char* const E_GL_ARB_texture_query_lod = "GL_ARB_texture_query_lod"; + +const char* const E_GL_KHR_shader_subgroup_basic = "GL_KHR_shader_subgroup_basic"; +const char* const E_GL_KHR_shader_subgroup_vote = "GL_KHR_shader_subgroup_vote"; +const char* const E_GL_KHR_shader_subgroup_arithmetic = "GL_KHR_shader_subgroup_arithmetic"; +const char* const E_GL_KHR_shader_subgroup_ballot = "GL_KHR_shader_subgroup_ballot"; +const char* const E_GL_KHR_shader_subgroup_shuffle = "GL_KHR_shader_subgroup_shuffle"; +const char* const E_GL_KHR_shader_subgroup_shuffle_relative = "GL_KHR_shader_subgroup_shuffle_relative"; +const char* const E_GL_KHR_shader_subgroup_clustered = "GL_KHR_shader_subgroup_clustered"; +const char* const E_GL_KHR_shader_subgroup_quad = "GL_KHR_shader_subgroup_quad"; +const char* const E_GL_KHR_memory_scope_semantics = "GL_KHR_memory_scope_semantics"; + +const char* const E_GL_EXT_shader_atomic_int64 = "GL_EXT_shader_atomic_int64"; + +const char* const E_GL_EXT_shader_non_constant_global_initializers = "GL_EXT_shader_non_constant_global_initializers"; +const char* const E_GL_EXT_shader_image_load_formatted = "GL_EXT_shader_image_load_formatted"; + +const char* const E_GL_EXT_shader_16bit_storage = "GL_EXT_shader_16bit_storage"; +const char* const E_GL_EXT_shader_8bit_storage = "GL_EXT_shader_8bit_storage"; + + +// EXT extensions +const char* const E_GL_EXT_device_group = "GL_EXT_device_group"; +const char* const E_GL_EXT_multiview = "GL_EXT_multiview"; +const char* const E_GL_EXT_post_depth_coverage = "GL_EXT_post_depth_coverage"; +const char* const E_GL_EXT_control_flow_attributes = "GL_EXT_control_flow_attributes"; +const char* const E_GL_EXT_nonuniform_qualifier = "GL_EXT_nonuniform_qualifier"; +const char* const E_GL_EXT_samplerless_texture_functions = "GL_EXT_samplerless_texture_functions"; +const char* const E_GL_EXT_scalar_block_layout = "GL_EXT_scalar_block_layout"; +const char* const E_GL_EXT_fragment_invocation_density = "GL_EXT_fragment_invocation_density"; +const char* const E_GL_EXT_buffer_reference = "GL_EXT_buffer_reference"; +const char* const E_GL_EXT_buffer_reference2 = "GL_EXT_buffer_reference2"; +const char* const E_GL_EXT_buffer_reference_uvec2 = "GL_EXT_buffer_reference_uvec2"; +const char* const E_GL_EXT_demote_to_helper_invocation = "GL_EXT_demote_to_helper_invocation"; +const char* const E_GL_EXT_shader_realtime_clock = "GL_EXT_shader_realtime_clock"; +const char* const E_GL_EXT_debug_printf = "GL_EXT_debug_printf"; +const char* const E_GL_EXT_ray_tracing = "GL_EXT_ray_tracing"; +const char* const E_GL_EXT_ray_query = "GL_EXT_ray_query"; +const char* const E_GL_EXT_ray_flags_primitive_culling = "GL_EXT_ray_flags_primitive_culling"; + +// Arrays of extensions for the above viewportEXTs duplications + +const char* const post_depth_coverageEXTs[] = { E_GL_ARB_post_depth_coverage, E_GL_EXT_post_depth_coverage }; +const int Num_post_depth_coverageEXTs = sizeof(post_depth_coverageEXTs) / sizeof(post_depth_coverageEXTs[0]); + +// OVR extensions +const char* const E_GL_OVR_multiview = "GL_OVR_multiview"; +const char* const E_GL_OVR_multiview2 = "GL_OVR_multiview2"; + +const char* const OVR_multiview_EXTs[] = { E_GL_OVR_multiview, E_GL_OVR_multiview2 }; +const int Num_OVR_multiview_EXTs = sizeof(OVR_multiview_EXTs) / sizeof(OVR_multiview_EXTs[0]); + +// #line and #include +const char* const E_GL_GOOGLE_cpp_style_line_directive = "GL_GOOGLE_cpp_style_line_directive"; +const char* const E_GL_GOOGLE_include_directive = "GL_GOOGLE_include_directive"; + +const char* const E_GL_AMD_shader_ballot = "GL_AMD_shader_ballot"; +const char* const E_GL_AMD_shader_trinary_minmax = "GL_AMD_shader_trinary_minmax"; +const char* const E_GL_AMD_shader_explicit_vertex_parameter = "GL_AMD_shader_explicit_vertex_parameter"; +const char* const E_GL_AMD_gcn_shader = "GL_AMD_gcn_shader"; +const char* const E_GL_AMD_gpu_shader_half_float = "GL_AMD_gpu_shader_half_float"; +const char* const E_GL_AMD_texture_gather_bias_lod = "GL_AMD_texture_gather_bias_lod"; +const char* const E_GL_AMD_gpu_shader_int16 = "GL_AMD_gpu_shader_int16"; +const char* const E_GL_AMD_shader_image_load_store_lod = "GL_AMD_shader_image_load_store_lod"; +const char* const E_GL_AMD_shader_fragment_mask = "GL_AMD_shader_fragment_mask"; +const char* const E_GL_AMD_gpu_shader_half_float_fetch = "GL_AMD_gpu_shader_half_float_fetch"; + +const char* const E_GL_INTEL_shader_integer_functions2 = "GL_INTEL_shader_integer_functions2"; + +const char* const E_GL_NV_sample_mask_override_coverage = "GL_NV_sample_mask_override_coverage"; +const char* const E_SPV_NV_geometry_shader_passthrough = "GL_NV_geometry_shader_passthrough"; +const char* const E_GL_NV_viewport_array2 = "GL_NV_viewport_array2"; +const char* const E_GL_NV_stereo_view_rendering = "GL_NV_stereo_view_rendering"; +const char* const E_GL_NVX_multiview_per_view_attributes = "GL_NVX_multiview_per_view_attributes"; +const char* const E_GL_NV_shader_atomic_int64 = "GL_NV_shader_atomic_int64"; +const char* const E_GL_NV_conservative_raster_underestimation = "GL_NV_conservative_raster_underestimation"; +const char* const E_GL_NV_shader_noperspective_interpolation = "GL_NV_shader_noperspective_interpolation"; +const char* const E_GL_NV_shader_subgroup_partitioned = "GL_NV_shader_subgroup_partitioned"; +const char* const E_GL_NV_shading_rate_image = "GL_NV_shading_rate_image"; +const char* const E_GL_NV_ray_tracing = "GL_NV_ray_tracing"; +const char* const E_GL_NV_fragment_shader_barycentric = "GL_NV_fragment_shader_barycentric"; +const char* const E_GL_NV_compute_shader_derivatives = "GL_NV_compute_shader_derivatives"; +const char* const E_GL_NV_shader_texture_footprint = "GL_NV_shader_texture_footprint"; +const char* const E_GL_NV_mesh_shader = "GL_NV_mesh_shader"; + +// Arrays of extensions for the above viewportEXTs duplications + +const char* const viewportEXTs[] = { E_GL_ARB_shader_viewport_layer_array, E_GL_NV_viewport_array2 }; +const int Num_viewportEXTs = sizeof(viewportEXTs) / sizeof(viewportEXTs[0]); + +const char* const E_GL_NV_cooperative_matrix = "GL_NV_cooperative_matrix"; +const char* const E_GL_NV_shader_sm_builtins = "GL_NV_shader_sm_builtins"; +const char* const E_GL_NV_integer_cooperative_matrix = "GL_NV_integer_cooperative_matrix"; + +// AEP +const char* const E_GL_ANDROID_extension_pack_es31a = "GL_ANDROID_extension_pack_es31a"; +const char* const E_GL_KHR_blend_equation_advanced = "GL_KHR_blend_equation_advanced"; +const char* const E_GL_OES_sample_variables = "GL_OES_sample_variables"; +const char* const E_GL_OES_shader_image_atomic = "GL_OES_shader_image_atomic"; +const char* const E_GL_OES_shader_multisample_interpolation = "GL_OES_shader_multisample_interpolation"; +const char* const E_GL_OES_texture_storage_multisample_2d_array = "GL_OES_texture_storage_multisample_2d_array"; +const char* const E_GL_EXT_geometry_shader = "GL_EXT_geometry_shader"; +const char* const E_GL_EXT_geometry_point_size = "GL_EXT_geometry_point_size"; +const char* const E_GL_EXT_gpu_shader5 = "GL_EXT_gpu_shader5"; +const char* const E_GL_EXT_primitive_bounding_box = "GL_EXT_primitive_bounding_box"; +const char* const E_GL_EXT_shader_io_blocks = "GL_EXT_shader_io_blocks"; +const char* const E_GL_EXT_tessellation_shader = "GL_EXT_tessellation_shader"; +const char* const E_GL_EXT_tessellation_point_size = "GL_EXT_tessellation_point_size"; +const char* const E_GL_EXT_texture_buffer = "GL_EXT_texture_buffer"; +const char* const E_GL_EXT_texture_cube_map_array = "GL_EXT_texture_cube_map_array"; + +// OES matching AEP +const char* const E_GL_OES_geometry_shader = "GL_OES_geometry_shader"; +const char* const E_GL_OES_geometry_point_size = "GL_OES_geometry_point_size"; +const char* const E_GL_OES_gpu_shader5 = "GL_OES_gpu_shader5"; +const char* const E_GL_OES_primitive_bounding_box = "GL_OES_primitive_bounding_box"; +const char* const E_GL_OES_shader_io_blocks = "GL_OES_shader_io_blocks"; +const char* const E_GL_OES_tessellation_shader = "GL_OES_tessellation_shader"; +const char* const E_GL_OES_tessellation_point_size = "GL_OES_tessellation_point_size"; +const char* const E_GL_OES_texture_buffer = "GL_OES_texture_buffer"; +const char* const E_GL_OES_texture_cube_map_array = "GL_OES_texture_cube_map_array"; + +// EXT +const char* const E_GL_EXT_shader_explicit_arithmetic_types = "GL_EXT_shader_explicit_arithmetic_types"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_int8 = "GL_EXT_shader_explicit_arithmetic_types_int8"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_int16 = "GL_EXT_shader_explicit_arithmetic_types_int16"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_int32 = "GL_EXT_shader_explicit_arithmetic_types_int32"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_int64 = "GL_EXT_shader_explicit_arithmetic_types_int64"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_float16 = "GL_EXT_shader_explicit_arithmetic_types_float16"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_float32 = "GL_EXT_shader_explicit_arithmetic_types_float32"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_float64 = "GL_EXT_shader_explicit_arithmetic_types_float64"; + +const char* const E_GL_EXT_shader_subgroup_extended_types_int8 = "GL_EXT_shader_subgroup_extended_types_int8"; +const char* const E_GL_EXT_shader_subgroup_extended_types_int16 = "GL_EXT_shader_subgroup_extended_types_int16"; +const char* const E_GL_EXT_shader_subgroup_extended_types_int64 = "GL_EXT_shader_subgroup_extended_types_int64"; +const char* const E_GL_EXT_shader_subgroup_extended_types_float16 = "GL_EXT_shader_subgroup_extended_types_float16"; + +// Arrays of extensions for the above AEP duplications + +const char* const AEP_geometry_shader[] = { E_GL_EXT_geometry_shader, E_GL_OES_geometry_shader }; +const int Num_AEP_geometry_shader = sizeof(AEP_geometry_shader)/sizeof(AEP_geometry_shader[0]); + +const char* const AEP_geometry_point_size[] = { E_GL_EXT_geometry_point_size, E_GL_OES_geometry_point_size }; +const int Num_AEP_geometry_point_size = sizeof(AEP_geometry_point_size)/sizeof(AEP_geometry_point_size[0]); + +const char* const AEP_gpu_shader5[] = { E_GL_EXT_gpu_shader5, E_GL_OES_gpu_shader5 }; +const int Num_AEP_gpu_shader5 = sizeof(AEP_gpu_shader5)/sizeof(AEP_gpu_shader5[0]); + +const char* const AEP_primitive_bounding_box[] = { E_GL_EXT_primitive_bounding_box, E_GL_OES_primitive_bounding_box }; +const int Num_AEP_primitive_bounding_box = sizeof(AEP_primitive_bounding_box)/sizeof(AEP_primitive_bounding_box[0]); + +const char* const AEP_shader_io_blocks[] = { E_GL_EXT_shader_io_blocks, E_GL_OES_shader_io_blocks }; +const int Num_AEP_shader_io_blocks = sizeof(AEP_shader_io_blocks)/sizeof(AEP_shader_io_blocks[0]); + +const char* const AEP_tessellation_shader[] = { E_GL_EXT_tessellation_shader, E_GL_OES_tessellation_shader }; +const int Num_AEP_tessellation_shader = sizeof(AEP_tessellation_shader)/sizeof(AEP_tessellation_shader[0]); + +const char* const AEP_tessellation_point_size[] = { E_GL_EXT_tessellation_point_size, E_GL_OES_tessellation_point_size }; +const int Num_AEP_tessellation_point_size = sizeof(AEP_tessellation_point_size)/sizeof(AEP_tessellation_point_size[0]); + +const char* const AEP_texture_buffer[] = { E_GL_EXT_texture_buffer, E_GL_OES_texture_buffer }; +const int Num_AEP_texture_buffer = sizeof(AEP_texture_buffer)/sizeof(AEP_texture_buffer[0]); + +const char* const AEP_texture_cube_map_array[] = { E_GL_EXT_texture_cube_map_array, E_GL_OES_texture_cube_map_array }; +const int Num_AEP_texture_cube_map_array = sizeof(AEP_texture_cube_map_array)/sizeof(AEP_texture_cube_map_array[0]); + +} // end namespace glslang + +#endif // _VERSIONS_INCLUDED_ diff --git a/android/armeabi-v7a/include/glslang/MachineIndependent/attribute.h b/android/armeabi-v7a/include/glslang/MachineIndependent/attribute.h new file mode 100644 index 00000000..38a943d2 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/MachineIndependent/attribute.h @@ -0,0 +1,149 @@ +// +// Copyright (C) 2017 LunarG, Inc. +// Copyright (C) 2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _ATTRIBUTE_INCLUDED_ +#define _ATTRIBUTE_INCLUDED_ + +#include "../Include/Common.h" +#include "../Include/ConstantUnion.h" + +namespace glslang { + + enum TAttributeType { + EatNone, + EatAllow_uav_condition, + EatBranch, + EatCall, + EatDomain, + EatEarlyDepthStencil, + EatFastOpt, + EatFlatten, + EatForceCase, + EatInstance, + EatMaxTessFactor, + EatNumThreads, + EatMaxVertexCount, + EatOutputControlPoints, + EatOutputTopology, + EatPartitioning, + EatPatchConstantFunc, + EatPatchSize, + EatUnroll, + EatLoop, + EatBinding, + EatGlobalBinding, + EatLocation, + EatInputAttachment, + EatBuiltIn, + EatPushConstant, + EatConstantId, + EatDependencyInfinite, + EatDependencyLength, + EatMinIterations, + EatMaxIterations, + EatIterationMultiple, + EatPeelCount, + EatPartialCount, + EatFormatRgba32f, + EatFormatRgba16f, + EatFormatR32f, + EatFormatRgba8, + EatFormatRgba8Snorm, + EatFormatRg32f, + EatFormatRg16f, + EatFormatR11fG11fB10f, + EatFormatR16f, + EatFormatRgba16, + EatFormatRgb10A2, + EatFormatRg16, + EatFormatRg8, + EatFormatR16, + EatFormatR8, + EatFormatRgba16Snorm, + EatFormatRg16Snorm, + EatFormatRg8Snorm, + EatFormatR16Snorm, + EatFormatR8Snorm, + EatFormatRgba32i, + EatFormatRgba16i, + EatFormatRgba8i, + EatFormatR32i, + EatFormatRg32i, + EatFormatRg16i, + EatFormatRg8i, + EatFormatR16i, + EatFormatR8i, + EatFormatRgba32ui, + EatFormatRgba16ui, + EatFormatRgba8ui, + EatFormatR32ui, + EatFormatRgb10a2ui, + EatFormatRg32ui, + EatFormatRg16ui, + EatFormatRg8ui, + EatFormatR16ui, + EatFormatR8ui, + EatFormatUnknown, + EatNonWritable, + EatNonReadable + }; + + class TIntermAggregate; + + struct TAttributeArgs { + TAttributeType name; + const TIntermAggregate* args; + + // Obtain attribute as integer + // Return false if it cannot be obtained + bool getInt(int& value, int argNum = 0) const; + + // Obtain attribute as string, with optional to-lower transform + // Return false if it cannot be obtained + bool getString(TString& value, int argNum = 0, bool convertToLower = true) const; + + // How many arguments were provided to the attribute? + int size() const; + + protected: + const TConstUnion* getConstUnion(TBasicType basicType, int argNum) const; + }; + + typedef TList TAttributes; + +} // end namespace glslang + +#endif // _ATTRIBUTE_INCLUDED_ diff --git a/android/armeabi-v7a/include/glslang/MachineIndependent/gl_types.h b/android/armeabi-v7a/include/glslang/MachineIndependent/gl_types.h new file mode 100644 index 00000000..b6f613bc --- /dev/null +++ b/android/armeabi-v7a/include/glslang/MachineIndependent/gl_types.h @@ -0,0 +1,210 @@ +/* +** Copyright (c) 2013 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +#pragma once + +#define GL_FLOAT 0x1406 +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 + +#define GL_DOUBLE 0x140A +#define GL_DOUBLE_VEC2 0x8FFC +#define GL_DOUBLE_VEC3 0x8FFD +#define GL_DOUBLE_VEC4 0x8FFE + +#define GL_INT 0x1404 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 + +#define GL_UNSIGNED_INT 0x1405 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 + +#define GL_INT64_ARB 0x140E +#define GL_INT64_VEC2_ARB 0x8FE9 +#define GL_INT64_VEC3_ARB 0x8FEA +#define GL_INT64_VEC4_ARB 0x8FEB + +#define GL_UNSIGNED_INT64_ARB 0x140F +#define GL_UNSIGNED_INT64_VEC2_ARB 0x8FE5 +#define GL_UNSIGNED_INT64_VEC3_ARB 0x8FE6 +#define GL_UNSIGNED_INT64_VEC4_ARB 0x8FE7 + +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 + +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A + +#define GL_DOUBLE_MAT2 0x8F46 +#define GL_DOUBLE_MAT3 0x8F47 +#define GL_DOUBLE_MAT4 0x8F48 +#define GL_DOUBLE_MAT2x3 0x8F49 +#define GL_DOUBLE_MAT2x4 0x8F4A +#define GL_DOUBLE_MAT3x2 0x8F4B +#define GL_DOUBLE_MAT3x4 0x8F4C +#define GL_DOUBLE_MAT4x2 0x8F4D +#define GL_DOUBLE_MAT4x3 0x8F4E + +// Those constants are borrowed from extension NV_gpu_shader5 +#define GL_FLOAT16_NV 0x8FF8 +#define GL_FLOAT16_VEC2_NV 0x8FF9 +#define GL_FLOAT16_VEC3_NV 0x8FFA +#define GL_FLOAT16_VEC4_NV 0x8FFB + +#define GL_FLOAT16_MAT2_AMD 0x91C5 +#define GL_FLOAT16_MAT3_AMD 0x91C6 +#define GL_FLOAT16_MAT4_AMD 0x91C7 +#define GL_FLOAT16_MAT2x3_AMD 0x91C8 +#define GL_FLOAT16_MAT2x4_AMD 0x91C9 +#define GL_FLOAT16_MAT3x2_AMD 0x91CA +#define GL_FLOAT16_MAT3x4_AMD 0x91CB +#define GL_FLOAT16_MAT4x2_AMD 0x91CC +#define GL_FLOAT16_MAT4x3_AMD 0x91CD + +#define GL_SAMPLER_1D 0x8B5D +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_SAMPLER_BUFFER 0x8DC2 +#define GL_SAMPLER_1D_ARRAY 0x8DC0 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_SAMPLER_1D_SHADOW 0x8B61 +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_SAMPLER_2D_RECT 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64 +#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 +#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B +#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D +#define GL_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D + +#define GL_FLOAT16_SAMPLER_1D_AMD 0x91CE +#define GL_FLOAT16_SAMPLER_2D_AMD 0x91CF +#define GL_FLOAT16_SAMPLER_3D_AMD 0x91D0 +#define GL_FLOAT16_SAMPLER_CUBE_AMD 0x91D1 +#define GL_FLOAT16_SAMPLER_2D_RECT_AMD 0x91D2 +#define GL_FLOAT16_SAMPLER_1D_ARRAY_AMD 0x91D3 +#define GL_FLOAT16_SAMPLER_2D_ARRAY_AMD 0x91D4 +#define GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_AMD 0x91D5 +#define GL_FLOAT16_SAMPLER_BUFFER_AMD 0x91D6 +#define GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_AMD 0x91D7 +#define GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_ARRAY_AMD 0x91D8 + +#define GL_FLOAT16_SAMPLER_1D_SHADOW_AMD 0x91D9 +#define GL_FLOAT16_SAMPLER_2D_SHADOW_AMD 0x91DA +#define GL_FLOAT16_SAMPLER_2D_RECT_SHADOW_AMD 0x91DB +#define GL_FLOAT16_SAMPLER_1D_ARRAY_SHADOW_AMD 0x91DC +#define GL_FLOAT16_SAMPLER_2D_ARRAY_SHADOW_AMD 0x91DD +#define GL_FLOAT16_SAMPLER_CUBE_SHADOW_AMD 0x91DE +#define GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_SHADOW_AMD 0x91DF + +#define GL_FLOAT16_IMAGE_1D_AMD 0x91E0 +#define GL_FLOAT16_IMAGE_2D_AMD 0x91E1 +#define GL_FLOAT16_IMAGE_3D_AMD 0x91E2 +#define GL_FLOAT16_IMAGE_2D_RECT_AMD 0x91E3 +#define GL_FLOAT16_IMAGE_CUBE_AMD 0x91E4 +#define GL_FLOAT16_IMAGE_1D_ARRAY_AMD 0x91E5 +#define GL_FLOAT16_IMAGE_2D_ARRAY_AMD 0x91E6 +#define GL_FLOAT16_IMAGE_CUBE_MAP_ARRAY_AMD 0x91E7 +#define GL_FLOAT16_IMAGE_BUFFER_AMD 0x91E8 +#define GL_FLOAT16_IMAGE_2D_MULTISAMPLE_AMD 0x91E9 +#define GL_FLOAT16_IMAGE_2D_MULTISAMPLE_ARRAY_AMD 0x91EA + +#define GL_INT_SAMPLER_1D 0x8DC9 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_INT_SAMPLER_2D_RECT 0x8DCD +#define GL_INT_SAMPLER_BUFFER 0x8DD0 +#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 +#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900E + +#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8 +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900F +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A + +#define GL_IMAGE_1D 0x904C +#define GL_IMAGE_2D 0x904D +#define GL_IMAGE_3D 0x904E +#define GL_IMAGE_2D_RECT 0x904F +#define GL_IMAGE_CUBE 0x9050 +#define GL_IMAGE_BUFFER 0x9051 +#define GL_IMAGE_1D_ARRAY 0x9052 +#define GL_IMAGE_2D_ARRAY 0x9053 +#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054 +#define GL_IMAGE_2D_MULTISAMPLE 0x9055 +#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056 +#define GL_INT_IMAGE_1D 0x9057 +#define GL_INT_IMAGE_2D 0x9058 +#define GL_INT_IMAGE_3D 0x9059 +#define GL_INT_IMAGE_2D_RECT 0x905A +#define GL_INT_IMAGE_CUBE 0x905B +#define GL_INT_IMAGE_BUFFER 0x905C +#define GL_INT_IMAGE_1D_ARRAY 0x905D +#define GL_INT_IMAGE_2D_ARRAY 0x905E +#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F +#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060 +#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061 +#define GL_UNSIGNED_INT_IMAGE_1D 0x9062 +#define GL_UNSIGNED_INT_IMAGE_2D 0x9063 +#define GL_UNSIGNED_INT_IMAGE_3D 0x9064 +#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065 +#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066 +#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067 +#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068 +#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069 +#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C + +#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB diff --git a/android/armeabi-v7a/include/glslang/MachineIndependent/glslang_tab.cpp.h b/android/armeabi-v7a/include/glslang/MachineIndependent/glslang_tab.cpp.h new file mode 100644 index 00000000..31c8f902 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/MachineIndependent/glslang_tab.cpp.h @@ -0,0 +1,521 @@ +/* A Bison parser, made by GNU Bison 3.0.4. */ + +/* Bison interface for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +#ifndef YY_YY_GLSLANG_TAB_CPP_H_INCLUDED +# define YY_YY_GLSLANG_TAB_CPP_H_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 1 +#endif +#if YYDEBUG +extern int yydebug; +#endif + +/* Token type. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + enum yytokentype + { + CONST = 258, + BOOL = 259, + INT = 260, + UINT = 261, + FLOAT = 262, + BVEC2 = 263, + BVEC3 = 264, + BVEC4 = 265, + IVEC2 = 266, + IVEC3 = 267, + IVEC4 = 268, + UVEC2 = 269, + UVEC3 = 270, + UVEC4 = 271, + VEC2 = 272, + VEC3 = 273, + VEC4 = 274, + MAT2 = 275, + MAT3 = 276, + MAT4 = 277, + MAT2X2 = 278, + MAT2X3 = 279, + MAT2X4 = 280, + MAT3X2 = 281, + MAT3X3 = 282, + MAT3X4 = 283, + MAT4X2 = 284, + MAT4X3 = 285, + MAT4X4 = 286, + SAMPLER2D = 287, + SAMPLER3D = 288, + SAMPLERCUBE = 289, + SAMPLER2DSHADOW = 290, + SAMPLERCUBESHADOW = 291, + SAMPLER2DARRAY = 292, + SAMPLER2DARRAYSHADOW = 293, + ISAMPLER2D = 294, + ISAMPLER3D = 295, + ISAMPLERCUBE = 296, + ISAMPLER2DARRAY = 297, + USAMPLER2D = 298, + USAMPLER3D = 299, + USAMPLERCUBE = 300, + USAMPLER2DARRAY = 301, + SAMPLER = 302, + SAMPLERSHADOW = 303, + TEXTURE2D = 304, + TEXTURE3D = 305, + TEXTURECUBE = 306, + TEXTURE2DARRAY = 307, + ITEXTURE2D = 308, + ITEXTURE3D = 309, + ITEXTURECUBE = 310, + ITEXTURE2DARRAY = 311, + UTEXTURE2D = 312, + UTEXTURE3D = 313, + UTEXTURECUBE = 314, + UTEXTURE2DARRAY = 315, + ATTRIBUTE = 316, + VARYING = 317, + FLOAT16_T = 318, + FLOAT32_T = 319, + DOUBLE = 320, + FLOAT64_T = 321, + INT64_T = 322, + UINT64_T = 323, + INT32_T = 324, + UINT32_T = 325, + INT16_T = 326, + UINT16_T = 327, + INT8_T = 328, + UINT8_T = 329, + I64VEC2 = 330, + I64VEC3 = 331, + I64VEC4 = 332, + U64VEC2 = 333, + U64VEC3 = 334, + U64VEC4 = 335, + I32VEC2 = 336, + I32VEC3 = 337, + I32VEC4 = 338, + U32VEC2 = 339, + U32VEC3 = 340, + U32VEC4 = 341, + I16VEC2 = 342, + I16VEC3 = 343, + I16VEC4 = 344, + U16VEC2 = 345, + U16VEC3 = 346, + U16VEC4 = 347, + I8VEC2 = 348, + I8VEC3 = 349, + I8VEC4 = 350, + U8VEC2 = 351, + U8VEC3 = 352, + U8VEC4 = 353, + DVEC2 = 354, + DVEC3 = 355, + DVEC4 = 356, + DMAT2 = 357, + DMAT3 = 358, + DMAT4 = 359, + F16VEC2 = 360, + F16VEC3 = 361, + F16VEC4 = 362, + F16MAT2 = 363, + F16MAT3 = 364, + F16MAT4 = 365, + F32VEC2 = 366, + F32VEC3 = 367, + F32VEC4 = 368, + F32MAT2 = 369, + F32MAT3 = 370, + F32MAT4 = 371, + F64VEC2 = 372, + F64VEC3 = 373, + F64VEC4 = 374, + F64MAT2 = 375, + F64MAT3 = 376, + F64MAT4 = 377, + DMAT2X2 = 378, + DMAT2X3 = 379, + DMAT2X4 = 380, + DMAT3X2 = 381, + DMAT3X3 = 382, + DMAT3X4 = 383, + DMAT4X2 = 384, + DMAT4X3 = 385, + DMAT4X4 = 386, + F16MAT2X2 = 387, + F16MAT2X3 = 388, + F16MAT2X4 = 389, + F16MAT3X2 = 390, + F16MAT3X3 = 391, + F16MAT3X4 = 392, + F16MAT4X2 = 393, + F16MAT4X3 = 394, + F16MAT4X4 = 395, + F32MAT2X2 = 396, + F32MAT2X3 = 397, + F32MAT2X4 = 398, + F32MAT3X2 = 399, + F32MAT3X3 = 400, + F32MAT3X4 = 401, + F32MAT4X2 = 402, + F32MAT4X3 = 403, + F32MAT4X4 = 404, + F64MAT2X2 = 405, + F64MAT2X3 = 406, + F64MAT2X4 = 407, + F64MAT3X2 = 408, + F64MAT3X3 = 409, + F64MAT3X4 = 410, + F64MAT4X2 = 411, + F64MAT4X3 = 412, + F64MAT4X4 = 413, + ATOMIC_UINT = 414, + ACCSTRUCTNV = 415, + ACCSTRUCTEXT = 416, + RAYQUERYEXT = 417, + FCOOPMATNV = 418, + ICOOPMATNV = 419, + UCOOPMATNV = 420, + SAMPLERCUBEARRAY = 421, + SAMPLERCUBEARRAYSHADOW = 422, + ISAMPLERCUBEARRAY = 423, + USAMPLERCUBEARRAY = 424, + SAMPLER1D = 425, + SAMPLER1DARRAY = 426, + SAMPLER1DARRAYSHADOW = 427, + ISAMPLER1D = 428, + SAMPLER1DSHADOW = 429, + SAMPLER2DRECT = 430, + SAMPLER2DRECTSHADOW = 431, + ISAMPLER2DRECT = 432, + USAMPLER2DRECT = 433, + SAMPLERBUFFER = 434, + ISAMPLERBUFFER = 435, + USAMPLERBUFFER = 436, + SAMPLER2DMS = 437, + ISAMPLER2DMS = 438, + USAMPLER2DMS = 439, + SAMPLER2DMSARRAY = 440, + ISAMPLER2DMSARRAY = 441, + USAMPLER2DMSARRAY = 442, + SAMPLEREXTERNALOES = 443, + SAMPLEREXTERNAL2DY2YEXT = 444, + ISAMPLER1DARRAY = 445, + USAMPLER1D = 446, + USAMPLER1DARRAY = 447, + F16SAMPLER1D = 448, + F16SAMPLER2D = 449, + F16SAMPLER3D = 450, + F16SAMPLER2DRECT = 451, + F16SAMPLERCUBE = 452, + F16SAMPLER1DARRAY = 453, + F16SAMPLER2DARRAY = 454, + F16SAMPLERCUBEARRAY = 455, + F16SAMPLERBUFFER = 456, + F16SAMPLER2DMS = 457, + F16SAMPLER2DMSARRAY = 458, + F16SAMPLER1DSHADOW = 459, + F16SAMPLER2DSHADOW = 460, + F16SAMPLER1DARRAYSHADOW = 461, + F16SAMPLER2DARRAYSHADOW = 462, + F16SAMPLER2DRECTSHADOW = 463, + F16SAMPLERCUBESHADOW = 464, + F16SAMPLERCUBEARRAYSHADOW = 465, + IMAGE1D = 466, + IIMAGE1D = 467, + UIMAGE1D = 468, + IMAGE2D = 469, + IIMAGE2D = 470, + UIMAGE2D = 471, + IMAGE3D = 472, + IIMAGE3D = 473, + UIMAGE3D = 474, + IMAGE2DRECT = 475, + IIMAGE2DRECT = 476, + UIMAGE2DRECT = 477, + IMAGECUBE = 478, + IIMAGECUBE = 479, + UIMAGECUBE = 480, + IMAGEBUFFER = 481, + IIMAGEBUFFER = 482, + UIMAGEBUFFER = 483, + IMAGE1DARRAY = 484, + IIMAGE1DARRAY = 485, + UIMAGE1DARRAY = 486, + IMAGE2DARRAY = 487, + IIMAGE2DARRAY = 488, + UIMAGE2DARRAY = 489, + IMAGECUBEARRAY = 490, + IIMAGECUBEARRAY = 491, + UIMAGECUBEARRAY = 492, + IMAGE2DMS = 493, + IIMAGE2DMS = 494, + UIMAGE2DMS = 495, + IMAGE2DMSARRAY = 496, + IIMAGE2DMSARRAY = 497, + UIMAGE2DMSARRAY = 498, + F16IMAGE1D = 499, + F16IMAGE2D = 500, + F16IMAGE3D = 501, + F16IMAGE2DRECT = 502, + F16IMAGECUBE = 503, + F16IMAGE1DARRAY = 504, + F16IMAGE2DARRAY = 505, + F16IMAGECUBEARRAY = 506, + F16IMAGEBUFFER = 507, + F16IMAGE2DMS = 508, + F16IMAGE2DMSARRAY = 509, + TEXTURECUBEARRAY = 510, + ITEXTURECUBEARRAY = 511, + UTEXTURECUBEARRAY = 512, + TEXTURE1D = 513, + ITEXTURE1D = 514, + UTEXTURE1D = 515, + TEXTURE1DARRAY = 516, + ITEXTURE1DARRAY = 517, + UTEXTURE1DARRAY = 518, + TEXTURE2DRECT = 519, + ITEXTURE2DRECT = 520, + UTEXTURE2DRECT = 521, + TEXTUREBUFFER = 522, + ITEXTUREBUFFER = 523, + UTEXTUREBUFFER = 524, + TEXTURE2DMS = 525, + ITEXTURE2DMS = 526, + UTEXTURE2DMS = 527, + TEXTURE2DMSARRAY = 528, + ITEXTURE2DMSARRAY = 529, + UTEXTURE2DMSARRAY = 530, + F16TEXTURE1D = 531, + F16TEXTURE2D = 532, + F16TEXTURE3D = 533, + F16TEXTURE2DRECT = 534, + F16TEXTURECUBE = 535, + F16TEXTURE1DARRAY = 536, + F16TEXTURE2DARRAY = 537, + F16TEXTURECUBEARRAY = 538, + F16TEXTUREBUFFER = 539, + F16TEXTURE2DMS = 540, + F16TEXTURE2DMSARRAY = 541, + SUBPASSINPUT = 542, + SUBPASSINPUTMS = 543, + ISUBPASSINPUT = 544, + ISUBPASSINPUTMS = 545, + USUBPASSINPUT = 546, + USUBPASSINPUTMS = 547, + F16SUBPASSINPUT = 548, + F16SUBPASSINPUTMS = 549, + LEFT_OP = 550, + RIGHT_OP = 551, + INC_OP = 552, + DEC_OP = 553, + LE_OP = 554, + GE_OP = 555, + EQ_OP = 556, + NE_OP = 557, + AND_OP = 558, + OR_OP = 559, + XOR_OP = 560, + MUL_ASSIGN = 561, + DIV_ASSIGN = 562, + ADD_ASSIGN = 563, + MOD_ASSIGN = 564, + LEFT_ASSIGN = 565, + RIGHT_ASSIGN = 566, + AND_ASSIGN = 567, + XOR_ASSIGN = 568, + OR_ASSIGN = 569, + SUB_ASSIGN = 570, + STRING_LITERAL = 571, + LEFT_PAREN = 572, + RIGHT_PAREN = 573, + LEFT_BRACKET = 574, + RIGHT_BRACKET = 575, + LEFT_BRACE = 576, + RIGHT_BRACE = 577, + DOT = 578, + COMMA = 579, + COLON = 580, + EQUAL = 581, + SEMICOLON = 582, + BANG = 583, + DASH = 584, + TILDE = 585, + PLUS = 586, + STAR = 587, + SLASH = 588, + PERCENT = 589, + LEFT_ANGLE = 590, + RIGHT_ANGLE = 591, + VERTICAL_BAR = 592, + CARET = 593, + AMPERSAND = 594, + QUESTION = 595, + INVARIANT = 596, + HIGH_PRECISION = 597, + MEDIUM_PRECISION = 598, + LOW_PRECISION = 599, + PRECISION = 600, + PACKED = 601, + RESOURCE = 602, + SUPERP = 603, + FLOATCONSTANT = 604, + INTCONSTANT = 605, + UINTCONSTANT = 606, + BOOLCONSTANT = 607, + IDENTIFIER = 608, + TYPE_NAME = 609, + CENTROID = 610, + IN = 611, + OUT = 612, + INOUT = 613, + STRUCT = 614, + VOID = 615, + WHILE = 616, + BREAK = 617, + CONTINUE = 618, + DO = 619, + ELSE = 620, + FOR = 621, + IF = 622, + DISCARD = 623, + RETURN = 624, + SWITCH = 625, + CASE = 626, + DEFAULT = 627, + UNIFORM = 628, + SHARED = 629, + BUFFER = 630, + FLAT = 631, + SMOOTH = 632, + LAYOUT = 633, + DOUBLECONSTANT = 634, + INT16CONSTANT = 635, + UINT16CONSTANT = 636, + FLOAT16CONSTANT = 637, + INT32CONSTANT = 638, + UINT32CONSTANT = 639, + INT64CONSTANT = 640, + UINT64CONSTANT = 641, + SUBROUTINE = 642, + DEMOTE = 643, + PAYLOADNV = 644, + PAYLOADINNV = 645, + HITATTRNV = 646, + CALLDATANV = 647, + CALLDATAINNV = 648, + PAYLOADEXT = 649, + PAYLOADINEXT = 650, + HITATTREXT = 651, + CALLDATAEXT = 652, + CALLDATAINEXT = 653, + PATCH = 654, + SAMPLE = 655, + NONUNIFORM = 656, + COHERENT = 657, + VOLATILE = 658, + RESTRICT = 659, + READONLY = 660, + WRITEONLY = 661, + DEVICECOHERENT = 662, + QUEUEFAMILYCOHERENT = 663, + WORKGROUPCOHERENT = 664, + SUBGROUPCOHERENT = 665, + NONPRIVATE = 666, + SHADERCALLCOHERENT = 667, + NOPERSPECTIVE = 668, + EXPLICITINTERPAMD = 669, + PERVERTEXNV = 670, + PERPRIMITIVENV = 671, + PERVIEWNV = 672, + PERTASKNV = 673, + PRECISE = 674 + }; +#endif + +/* Value type. */ +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED + +union YYSTYPE +{ +#line 97 "glslang.y" /* yacc.c:1909 */ + + struct { + glslang::TSourceLoc loc; + union { + glslang::TString *string; + int i; + unsigned int u; + long long i64; + unsigned long long u64; + bool b; + double d; + }; + glslang::TSymbol* symbol; + } lex; + struct { + glslang::TSourceLoc loc; + glslang::TOperator op; + union { + TIntermNode* intermNode; + glslang::TIntermNodePair nodePair; + glslang::TIntermTyped* intermTypedNode; + glslang::TAttributes* attributes; + }; + union { + glslang::TPublicType type; + glslang::TFunction* function; + glslang::TParameter param; + glslang::TTypeLoc typeLine; + glslang::TTypeList* typeList; + glslang::TArraySizes* arraySizes; + glslang::TIdentifierList* identifierList; + }; + glslang::TArraySizes* typeParameters; + } interm; + +#line 510 "glslang_tab.cpp.h" /* yacc.c:1909 */ +}; + +typedef union YYSTYPE YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif + + + +int yyparse (glslang::TParseContext* pParseContext); + +#endif /* !YY_YY_GLSLANG_TAB_CPP_H_INCLUDED */ diff --git a/android/armeabi-v7a/include/glslang/MachineIndependent/iomapper.h b/android/armeabi-v7a/include/glslang/MachineIndependent/iomapper.h new file mode 100644 index 00000000..13a8932b --- /dev/null +++ b/android/armeabi-v7a/include/glslang/MachineIndependent/iomapper.h @@ -0,0 +1,300 @@ +// +// Copyright (C) 2016 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef GLSLANG_WEB + +#ifndef _IOMAPPER_INCLUDED +#define _IOMAPPER_INCLUDED + +#include +#include "LiveTraverser.h" +#include +#include +// +// A reflection database and its interface, consistent with the OpenGL API reflection queries. +// + +class TInfoSink; + +namespace glslang { + +class TIntermediate; +struct TVarEntryInfo { + int id; + TIntermSymbol* symbol; + bool live; + int newBinding; + int newSet; + int newLocation; + int newComponent; + int newIndex; + EShLanguage stage; + struct TOrderById { + inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) { return l.id < r.id; } + }; + + struct TOrderByPriority { + // ordering: + // 1) has both binding and set + // 2) has binding but no set + // 3) has no binding but set + // 4) has no binding and no set + inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) { + const TQualifier& lq = l.symbol->getQualifier(); + const TQualifier& rq = r.symbol->getQualifier(); + + // simple rules: + // has binding gives 2 points + // has set gives 1 point + // who has the most points is more important. + int lPoints = (lq.hasBinding() ? 2 : 0) + (lq.hasSet() ? 1 : 0); + int rPoints = (rq.hasBinding() ? 2 : 0) + (rq.hasSet() ? 1 : 0); + + if (lPoints == rPoints) + return l.id < r.id; + return lPoints > rPoints; + } + }; +}; + +// Base class for shared TIoMapResolver services, used by several derivations. +struct TDefaultIoResolverBase : public glslang::TIoMapResolver { +public: + TDefaultIoResolverBase(const TIntermediate& intermediate); + typedef std::vector TSlotSet; + typedef std::unordered_map TSlotSetMap; + + // grow the reflection stage by stage + void notifyBinding(EShLanguage, TVarEntryInfo& /*ent*/) override {} + void notifyInOut(EShLanguage, TVarEntryInfo& /*ent*/) override {} + void beginNotifications(EShLanguage) override {} + void endNotifications(EShLanguage) override {} + void beginResolve(EShLanguage) override {} + void endResolve(EShLanguage) override {} + void beginCollect(EShLanguage) override {} + void endCollect(EShLanguage) override {} + void reserverResourceSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {} + void reserverStorageSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {} + int getBaseBinding(TResourceType res, unsigned int set) const; + const std::vector& getResourceSetBinding() const; + virtual TResourceType getResourceType(const glslang::TType& type) = 0; + bool doAutoBindingMapping() const; + bool doAutoLocationMapping() const; + TSlotSet::iterator findSlot(int set, int slot); + bool checkEmpty(int set, int slot); + bool validateInOut(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; } + int reserveSlot(int set, int slot, int size = 1); + int getFreeSlot(int set, int base, int size = 1); + int resolveSet(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + int resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override; + int resolveInOutComponent(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + int resolveInOutIndex(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + void addStage(EShLanguage stage) override { + if (stage < EShLangCount) + stageMask[stage] = true; + } + uint32_t computeTypeLocationSize(const TType& type, EShLanguage stage); + + TSlotSetMap slots; + bool hasError = false; + +protected: + TDefaultIoResolverBase(TDefaultIoResolverBase&); + TDefaultIoResolverBase& operator=(TDefaultIoResolverBase&); + const TIntermediate& intermediate; + int nextUniformLocation; + int nextInputLocation; + int nextOutputLocation; + bool stageMask[EShLangCount + 1]; + // Return descriptor set specific base if there is one, and the generic base otherwise. + int selectBaseBinding(int base, int descriptorSetBase) const { + return descriptorSetBase != -1 ? descriptorSetBase : base; + } + + static int getLayoutSet(const glslang::TType& type) { + if (type.getQualifier().hasSet()) + return type.getQualifier().layoutSet; + else + return 0; + } + + static bool isSamplerType(const glslang::TType& type) { + return type.getBasicType() == glslang::EbtSampler && type.getSampler().isPureSampler(); + } + + static bool isTextureType(const glslang::TType& type) { + return (type.getBasicType() == glslang::EbtSampler && + (type.getSampler().isTexture() || type.getSampler().isSubpass())); + } + + static bool isUboType(const glslang::TType& type) { + return type.getQualifier().storage == EvqUniform; + } + + static bool isImageType(const glslang::TType& type) { + return type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage(); + } + + static bool isSsboType(const glslang::TType& type) { + return type.getQualifier().storage == EvqBuffer; + } + + // Return true if this is a SRV (shader resource view) type: + static bool isSrvType(const glslang::TType& type) { + return isTextureType(type) || type.getQualifier().storage == EvqBuffer; + } + + // Return true if this is a UAV (unordered access view) type: + static bool isUavType(const glslang::TType& type) { + if (type.getQualifier().isReadOnly()) + return false; + return (type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage()) || + (type.getQualifier().storage == EvqBuffer); + } +}; + +// Defaulf I/O resolver for OpenGL +struct TDefaultGlslIoResolver : public TDefaultIoResolverBase { +public: + typedef std::map TVarSlotMap; // + typedef std::map TSlotMap; // + TDefaultGlslIoResolver(const TIntermediate& intermediate); + bool validateBinding(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; } + TResourceType getResourceType(const glslang::TType& type) override; + int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override; + int resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + int resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + void beginResolve(EShLanguage /*stage*/) override; + void endResolve(EShLanguage stage) override; + void beginCollect(EShLanguage) override; + void endCollect(EShLanguage) override; + void reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override; + void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override; + // in/out symbol and uniform symbol are stored in the same resourceSlotMap, the storage key is used to identify each type of symbol. + // We use stage and storage qualifier to construct a storage key. it can help us identify the same storage resource used in different stage. + // if a resource is a program resource and we don't need know it usage stage, we can use same stage to build storage key. + // Note: both stage and type must less then 0xffff. + int buildStorageKey(EShLanguage stage, TStorageQualifier type) { + assert(static_cast(stage) <= 0x0000ffff && static_cast(type) <= 0x0000ffff); + return (stage << 16) | type; + } + +protected: + // Use for mark pre stage, to get more interface symbol information. + EShLanguage preStage; + // Use for mark current shader stage for resolver + EShLanguage currentStage; + // Slot map for storage resource(location of uniform and interface symbol) It's a program share slot + TSlotMap resourceSlotMap; + // Slot map for other resource(image, ubo, ssbo), It's a program share slot. + TSlotMap storageSlotMap; +}; + +typedef std::map TVarLiveMap; + +// override function "operator=", if a vector being sort, +// when use vc++, the sort function will call : +// pair& operator=(const pair<_Other1, _Other2>& _Right) +// { +// first = _Right.first; +// second = _Right.second; +// return (*this); +// } +// that will make a const type handing on left. +// override this function can avoid a compiler error. +// In the future, if the vc++ compiler can handle such a situation, +// this part of the code will be removed. +struct TVarLivePair : std::pair { + TVarLivePair(std::pair& _Right) : pair(_Right.first, _Right.second) {} + TVarLivePair& operator=(const TVarLivePair& _Right) { + const_cast(first) = _Right.first; + second = _Right.second; + return (*this); + } +}; +typedef std::vector TVarLiveVector; + +// I/O mapper +class TIoMapper { +public: + TIoMapper() {} + virtual ~TIoMapper() {} + // grow the reflection stage by stage + bool virtual addStage(EShLanguage, TIntermediate&, TInfoSink&, TIoMapResolver*); + bool virtual doMap(TIoMapResolver*, TInfoSink&) { return true; } +}; + +// I/O mapper for OpenGL +class TGlslIoMapper : public TIoMapper { +public: + TGlslIoMapper() { + memset(inVarMaps, 0, sizeof(TVarLiveMap*) * EShLangCount); + memset(outVarMaps, 0, sizeof(TVarLiveMap*) * EShLangCount); + memset(uniformVarMap, 0, sizeof(TVarLiveMap*) * EShLangCount); + memset(intermediates, 0, sizeof(TIntermediate*) * EShLangCount); + } + virtual ~TGlslIoMapper() { + for (size_t stage = 0; stage < EShLangCount; stage++) { + if (inVarMaps[stage] != nullptr) { + delete inVarMaps[stage]; + inVarMaps[stage] = nullptr; + } + if (outVarMaps[stage] != nullptr) { + delete outVarMaps[stage]; + outVarMaps[stage] = nullptr; + } + if (uniformVarMap[stage] != nullptr) { + delete uniformVarMap[stage]; + uniformVarMap[stage] = nullptr; + } + if (intermediates[stage] != nullptr) + intermediates[stage] = nullptr; + } + } + // grow the reflection stage by stage + bool addStage(EShLanguage, TIntermediate&, TInfoSink&, TIoMapResolver*) override; + bool doMap(TIoMapResolver*, TInfoSink&) override; + TVarLiveMap *inVarMaps[EShLangCount], *outVarMaps[EShLangCount], + *uniformVarMap[EShLangCount]; + TIntermediate* intermediates[EShLangCount]; + bool hadError = false; +}; + +} // end namespace glslang + +#endif // _IOMAPPER_INCLUDED + +#endif // GLSLANG_WEB diff --git a/android/armeabi-v7a/include/glslang/MachineIndependent/localintermediate.h b/android/armeabi-v7a/include/glslang/MachineIndependent/localintermediate.h new file mode 100644 index 00000000..66f5a88a --- /dev/null +++ b/android/armeabi-v7a/include/glslang/MachineIndependent/localintermediate.h @@ -0,0 +1,1013 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2016 LunarG, Inc. +// Copyright (C) 2017 ARM Limited. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _LOCAL_INTERMEDIATE_INCLUDED_ +#define _LOCAL_INTERMEDIATE_INCLUDED_ + +#include "../Include/intermediate.h" +#include "../Public/ShaderLang.h" +#include "Versions.h" + +#include +#include +#include +#include +#include + +class TInfoSink; + +namespace glslang { + +struct TMatrixSelector { + int coord1; // stay agnostic about column/row; this is parse order + int coord2; +}; + +typedef int TVectorSelector; + +const int MaxSwizzleSelectors = 4; + +template +class TSwizzleSelectors { +public: + TSwizzleSelectors() : size_(0) { } + + void push_back(selectorType comp) + { + if (size_ < MaxSwizzleSelectors) + components[size_++] = comp; + } + void resize(int s) + { + assert(s <= size_); + size_ = s; + } + int size() const { return size_; } + selectorType operator[](int i) const + { + assert(i < MaxSwizzleSelectors); + return components[i]; + } + +private: + int size_; + selectorType components[MaxSwizzleSelectors]; +}; + +// +// Some helper structures for TIntermediate. Their contents are encapsulated +// by TIntermediate. +// + +// Used for call-graph algorithms for detecting recursion, missing bodies, and dead bodies. +// A "call" is a pair: . +// There can be duplicates. General assumption is the list is small. +struct TCall { + TCall(const TString& pCaller, const TString& pCallee) : caller(pCaller), callee(pCallee) { } + TString caller; + TString callee; + bool visited; + bool currentPath; + bool errorGiven; + int calleeBodyPosition; +}; + +// A generic 1-D range. +struct TRange { + TRange(int start, int last) : start(start), last(last) { } + bool overlap(const TRange& rhs) const + { + return last >= rhs.start && start <= rhs.last; + } + int start; + int last; +}; + +// An IO range is a 3-D rectangle; the set of (location, component, index) triples all lying +// within the same location range, component range, and index value. Locations don't alias unless +// all other dimensions of their range overlap. +struct TIoRange { + TIoRange(TRange location, TRange component, TBasicType basicType, int index) + : location(location), component(component), basicType(basicType), index(index) { } + bool overlap(const TIoRange& rhs) const + { + return location.overlap(rhs.location) && component.overlap(rhs.component) && index == rhs.index; + } + TRange location; + TRange component; + TBasicType basicType; + int index; +}; + +// An offset range is a 2-D rectangle; the set of (binding, offset) pairs all lying +// within the same binding and offset range. +struct TOffsetRange { + TOffsetRange(TRange binding, TRange offset) + : binding(binding), offset(offset) { } + bool overlap(const TOffsetRange& rhs) const + { + return binding.overlap(rhs.binding) && offset.overlap(rhs.offset); + } + TRange binding; + TRange offset; +}; + +#ifndef GLSLANG_WEB +// Things that need to be tracked per xfb buffer. +struct TXfbBuffer { + TXfbBuffer() : stride(TQualifier::layoutXfbStrideEnd), implicitStride(0), contains64BitType(false), + contains32BitType(false), contains16BitType(false) { } + std::vector ranges; // byte offsets that have already been assigned + unsigned int stride; + unsigned int implicitStride; + bool contains64BitType; + bool contains32BitType; + bool contains16BitType; +}; +#endif + +// Track a set of strings describing how the module was processed. +// This includes command line options, transforms, etc., ideally inclusive enough +// to reproduce the steps used to transform the input source to the output. +// E.g., see SPIR-V OpModuleProcessed. +// Each "process" or "transform" uses is expressed in the form: +// process arg0 arg1 arg2 ... +// process arg0 arg1 arg2 ... +// where everything is textual, and there can be zero or more arguments +class TProcesses { +public: + TProcesses() {} + ~TProcesses() {} + + void addProcess(const char* process) + { + processes.push_back(process); + } + void addProcess(const std::string& process) + { + processes.push_back(process); + } + void addArgument(int arg) + { + processes.back().append(" "); + std::string argString = std::to_string(arg); + processes.back().append(argString); + } + void addArgument(const char* arg) + { + processes.back().append(" "); + processes.back().append(arg); + } + void addArgument(const std::string& arg) + { + processes.back().append(" "); + processes.back().append(arg); + } + void addIfNonZero(const char* process, int value) + { + if (value != 0) { + addProcess(process); + addArgument(value); + } + } + + const std::vector& getProcesses() const { return processes; } + +private: + std::vector processes; +}; + +class TSymbolTable; +class TSymbol; +class TVariable; + +// +// Texture and Sampler transformation mode. +// +enum ComputeDerivativeMode { + LayoutDerivativeNone, // default layout as SPV_NV_compute_shader_derivatives not enabled + LayoutDerivativeGroupQuads, // derivative_group_quadsNV + LayoutDerivativeGroupLinear, // derivative_group_linearNV +}; + +class TIdMaps { +public: + TMap& operator[](int i) { return maps[i]; } + const TMap& operator[](int i) const { return maps[i]; } +private: + TMap maps[EsiCount]; +}; + + +// +// Set of helper functions to help parse and build the tree. +// +class TIntermediate { +public: + explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) : + language(l), + profile(p), version(v), treeRoot(0), + numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false), + invertY(false), + useStorageBuffer(false), + nanMinMaxClamp(false), + depthReplacing(false) +#ifndef GLSLANG_WEB + , + implicitThisName("@this"), implicitCounterName("@count"), + source(EShSourceNone), + useVulkanMemoryModel(false), + invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet), + inputPrimitive(ElgNone), outputPrimitive(ElgNone), + pixelCenterInteger(false), originUpperLeft(false), + vertexSpacing(EvsNone), vertexOrder(EvoNone), interlockOrdering(EioNone), pointMode(false), earlyFragmentTests(false), + postDepthCoverage(false), depthLayout(EldNone), + hlslFunctionality1(false), + blendEquations(0), xfbMode(false), multiStream(false), + layoutOverrideCoverage(false), + geoPassthroughEXT(false), + numShaderRecordBlocks(0), + computeDerivativeMode(LayoutDerivativeNone), + primitives(TQualifier::layoutNotSet), + numTaskNVBlocks(0), + autoMapBindings(false), + autoMapLocations(false), + flattenUniformArrays(false), + useUnknownFormat(false), + hlslOffsets(false), + hlslIoMapping(false), + useVariablePointers(false), + textureSamplerTransformMode(EShTexSampTransKeep), + needToLegalize(false), + binaryDoubleOutput(false), + usePhysicalStorageBuffer(false), + uniformLocationBase(0) +#endif + { + localSize[0] = 1; + localSize[1] = 1; + localSize[2] = 1; + localSizeNotDefault[0] = false; + localSizeNotDefault[1] = false; + localSizeNotDefault[2] = false; + localSizeSpecId[0] = TQualifier::layoutNotSet; + localSizeSpecId[1] = TQualifier::layoutNotSet; + localSizeSpecId[2] = TQualifier::layoutNotSet; +#ifndef GLSLANG_WEB + xfbBuffers.resize(TQualifier::layoutXfbBufferEnd); + shiftBinding.fill(0); +#endif + } + + void setVersion(int v) { version = v; } + int getVersion() const { return version; } + void setProfile(EProfile p) { profile = p; } + EProfile getProfile() const { return profile; } + void setSpv(const SpvVersion& s) + { + spvVersion = s; + + // client processes + if (spvVersion.vulkan > 0) + processes.addProcess("client vulkan100"); + if (spvVersion.openGl > 0) + processes.addProcess("client opengl100"); + + // target SPV + switch (spvVersion.spv) { + case 0: + break; + case EShTargetSpv_1_0: + break; + case EShTargetSpv_1_1: + processes.addProcess("target-env spirv1.1"); + break; + case EShTargetSpv_1_2: + processes.addProcess("target-env spirv1.2"); + break; + case EShTargetSpv_1_3: + processes.addProcess("target-env spirv1.3"); + break; + case EShTargetSpv_1_4: + processes.addProcess("target-env spirv1.4"); + break; + case EShTargetSpv_1_5: + processes.addProcess("target-env spirv1.5"); + break; + default: + processes.addProcess("target-env spirvUnknown"); + break; + } + + // target-environment processes + switch (spvVersion.vulkan) { + case 0: + break; + case EShTargetVulkan_1_0: + processes.addProcess("target-env vulkan1.0"); + break; + case EShTargetVulkan_1_1: + processes.addProcess("target-env vulkan1.1"); + break; + case EShTargetVulkan_1_2: + processes.addProcess("target-env vulkan1.2"); + break; + default: + processes.addProcess("target-env vulkanUnknown"); + break; + } + if (spvVersion.openGl > 0) + processes.addProcess("target-env opengl"); + } + const SpvVersion& getSpv() const { return spvVersion; } + EShLanguage getStage() const { return language; } + void addRequestedExtension(const char* extension) { requestedExtensions.insert(extension); } + const std::set& getRequestedExtensions() const { return requestedExtensions; } + + void setTreeRoot(TIntermNode* r) { treeRoot = r; } + TIntermNode* getTreeRoot() const { return treeRoot; } + void incrementEntryPointCount() { ++numEntryPoints; } + int getNumEntryPoints() const { return numEntryPoints; } + int getNumErrors() const { return numErrors; } + void addPushConstantCount() { ++numPushConstants; } + void setLimits(const TBuiltInResource& r) { resources = r; } + + bool postProcess(TIntermNode*, EShLanguage); + void removeTree(); + + void setEntryPointName(const char* ep) + { + entryPointName = ep; + processes.addProcess("entry-point"); + processes.addArgument(entryPointName); + } + void setEntryPointMangledName(const char* ep) { entryPointMangledName = ep; } + const std::string& getEntryPointName() const { return entryPointName; } + const std::string& getEntryPointMangledName() const { return entryPointMangledName; } + + void setInvertY(bool invert) + { + invertY = invert; + if (invertY) + processes.addProcess("invert-y"); + } + bool getInvertY() const { return invertY; } + +#ifdef ENABLE_HLSL + void setSource(EShSource s) { source = s; } + EShSource getSource() const { return source; } +#else + void setSource(EShSource s) { assert(s == EShSourceGlsl); } + EShSource getSource() const { return EShSourceGlsl; } +#endif + + bool isRecursive() const { return recursive; } + + TIntermSymbol* addSymbol(const TVariable&); + TIntermSymbol* addSymbol(const TVariable&, const TSourceLoc&); + TIntermSymbol* addSymbol(const TType&, const TSourceLoc&); + TIntermSymbol* addSymbol(const TIntermSymbol&); + TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*); + std::tuple addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1); + TIntermTyped* addUniShapeConversion(TOperator, const TType&, TIntermTyped*); + TIntermTyped* addConversion(TBasicType convertTo, TIntermTyped* node) const; + void addBiShapeConversion(TOperator, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode); + TIntermTyped* addShapeConversion(const TType&, TIntermTyped*); + TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc); + TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc); + TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc); + TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, TSourceLoc); + TIntermTyped* addBuiltInFunctionCall(const TSourceLoc& line, TOperator, bool unary, TIntermNode*, const TType& returnType); + bool canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op = EOpNull) const; + bool isIntegralPromotion(TBasicType from, TBasicType to) const; + bool isFPPromotion(TBasicType from, TBasicType to) const; + bool isIntegralConversion(TBasicType from, TBasicType to) const; + bool isFPConversion(TBasicType from, TBasicType to) const; + bool isFPIntegralConversion(TBasicType from, TBasicType to) const; + TOperator mapTypeToConstructorOp(const TType&) const; + TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right); + TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&); + TIntermAggregate* makeAggregate(TIntermNode* node); + TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&); + TIntermAggregate* makeAggregate(const TSourceLoc&); + TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, TSourceLoc); + bool areAllChildConst(TIntermAggregate* aggrNode); + TIntermSelection* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&); + TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&); + TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); + TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, const TSourceLoc&); + TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(signed char, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(unsigned char, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(signed short, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(unsigned short, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(int, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(unsigned int, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(long long, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(unsigned long long, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(bool, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(double, TBasicType, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(const TString*, const TSourceLoc&, bool literal = false) const; + TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const; + bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false); + TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&); + TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, + const TSourceLoc&, TIntermLoop*&); + TIntermBranch* addBranch(TOperator, const TSourceLoc&); + TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&); + template TIntermTyped* addSwizzle(TSwizzleSelectors&, const TSourceLoc&); + + // Low level functions to add nodes (no conversions or other higher level transformations) + // If a type is provided, the node's type will be set to it. + TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc) const; + TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, const TType&) const; + TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc) const; + TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc, const TType&) const; + + // Constant folding (in Constant.cpp) + TIntermTyped* fold(TIntermAggregate* aggrNode); + TIntermTyped* foldConstructor(TIntermAggregate* aggrNode); + TIntermTyped* foldDereference(TIntermTyped* node, int index, const TSourceLoc&); + TIntermTyped* foldSwizzle(TIntermTyped* node, TSwizzleSelectors& fields, const TSourceLoc&); + + // Tree ops + static const TIntermTyped* findLValueBase(const TIntermTyped*, bool swizzleOkay); + + // Linkage related + void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&); + void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&); + + void setUseStorageBuffer() + { + useStorageBuffer = true; + processes.addProcess("use-storage-buffer"); + } + bool usingStorageBuffer() const { return useStorageBuffer; } + void setDepthReplacing() { depthReplacing = true; } + bool isDepthReplacing() const { return depthReplacing; } + bool setLocalSize(int dim, int size) + { + if (localSizeNotDefault[dim]) + return size == localSize[dim]; + localSizeNotDefault[dim] = true; + localSize[dim] = size; + return true; + } + unsigned int getLocalSize(int dim) const { return localSize[dim]; } + bool setLocalSizeSpecId(int dim, int id) + { + if (localSizeSpecId[dim] != TQualifier::layoutNotSet) + return id == localSizeSpecId[dim]; + localSizeSpecId[dim] = id; + return true; + } + int getLocalSizeSpecId(int dim) const { return localSizeSpecId[dim]; } +#ifdef GLSLANG_WEB + void output(TInfoSink&, bool tree) { } + + bool isEsProfile() const { return false; } + bool getXfbMode() const { return false; } + bool isMultiStream() const { return false; } + TLayoutGeometry getOutputPrimitive() const { return ElgNone; } + bool getPostDepthCoverage() const { return false; } + bool getEarlyFragmentTests() const { return false; } + TLayoutDepth getDepth() const { return EldNone; } + bool getPixelCenterInteger() const { return false; } + void setOriginUpperLeft() { } + bool getOriginUpperLeft() const { return true; } + TInterlockOrdering getInterlockOrdering() const { return EioNone; } + + bool getAutoMapBindings() const { return false; } + bool getAutoMapLocations() const { return false; } + int getNumPushConstants() const { return 0; } + void addShaderRecordCount() { } + void addTaskNVCount() { } + void setUseVulkanMemoryModel() { } + bool usingVulkanMemoryModel() const { return false; } + bool usingPhysicalStorageBuffer() const { return false; } + bool usingVariablePointers() const { return false; } + unsigned getXfbStride(int buffer) const { return 0; } + bool hasLayoutDerivativeModeNone() const { return false; } + ComputeDerivativeMode getLayoutDerivativeModeNone() const { return LayoutDerivativeNone; } +#else + void output(TInfoSink&, bool tree); + + bool isEsProfile() const { return profile == EEsProfile; } + + void setShiftBinding(TResourceType res, unsigned int shift) + { + shiftBinding[res] = shift; + + const char* name = getResourceName(res); + if (name != nullptr) + processes.addIfNonZero(name, shift); + } + + unsigned int getShiftBinding(TResourceType res) const { return shiftBinding[res]; } + + void setShiftBindingForSet(TResourceType res, unsigned int shift, unsigned int set) + { + if (shift == 0) // ignore if there's no shift: it's a no-op. + return; + + shiftBindingForSet[res][set] = shift; + + const char* name = getResourceName(res); + if (name != nullptr) { + processes.addProcess(name); + processes.addArgument(shift); + processes.addArgument(set); + } + } + + int getShiftBindingForSet(TResourceType res, unsigned int set) const + { + const auto shift = shiftBindingForSet[res].find(set); + return shift == shiftBindingForSet[res].end() ? -1 : shift->second; + } + bool hasShiftBindingForSet(TResourceType res) const { return !shiftBindingForSet[res].empty(); } + + void setResourceSetBinding(const std::vector& shift) + { + resourceSetBinding = shift; + if (shift.size() > 0) { + processes.addProcess("resource-set-binding"); + for (int s = 0; s < (int)shift.size(); ++s) + processes.addArgument(shift[s]); + } + } + const std::vector& getResourceSetBinding() const { return resourceSetBinding; } + void setAutoMapBindings(bool map) + { + autoMapBindings = map; + if (autoMapBindings) + processes.addProcess("auto-map-bindings"); + } + bool getAutoMapBindings() const { return autoMapBindings; } + void setAutoMapLocations(bool map) + { + autoMapLocations = map; + if (autoMapLocations) + processes.addProcess("auto-map-locations"); + } + bool getAutoMapLocations() const { return autoMapLocations; } + +#ifdef ENABLE_HLSL + void setFlattenUniformArrays(bool flatten) + { + flattenUniformArrays = flatten; + if (flattenUniformArrays) + processes.addProcess("flatten-uniform-arrays"); + } + bool getFlattenUniformArrays() const { return flattenUniformArrays; } +#endif + void setNoStorageFormat(bool b) + { + useUnknownFormat = b; + if (useUnknownFormat) + processes.addProcess("no-storage-format"); + } + bool getNoStorageFormat() const { return useUnknownFormat; } + void setUseVulkanMemoryModel() + { + useVulkanMemoryModel = true; + processes.addProcess("use-vulkan-memory-model"); + } + bool usingVulkanMemoryModel() const { return useVulkanMemoryModel; } + void setUsePhysicalStorageBuffer() + { + usePhysicalStorageBuffer = true; + } + bool usingPhysicalStorageBuffer() const { return usePhysicalStorageBuffer; } + void setUseVariablePointers() + { + useVariablePointers = true; + processes.addProcess("use-variable-pointers"); + } + bool usingVariablePointers() const { return useVariablePointers; } + +#ifdef ENABLE_HLSL + template T addCounterBufferName(const T& name) const { return name + implicitCounterName; } + bool hasCounterBufferName(const TString& name) const { + size_t len = strlen(implicitCounterName); + return name.size() > len && + name.compare(name.size() - len, len, implicitCounterName) == 0; + } +#endif + + void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; } + int getNumPushConstants() const { return numPushConstants; } + void addShaderRecordCount() { ++numShaderRecordBlocks; } + void addTaskNVCount() { ++numTaskNVBlocks; } + + bool setInvocations(int i) + { + if (invocations != TQualifier::layoutNotSet) + return invocations == i; + invocations = i; + return true; + } + int getInvocations() const { return invocations; } + bool setVertices(int m) + { + if (vertices != TQualifier::layoutNotSet) + return vertices == m; + vertices = m; + return true; + } + int getVertices() const { return vertices; } + bool setInputPrimitive(TLayoutGeometry p) + { + if (inputPrimitive != ElgNone) + return inputPrimitive == p; + inputPrimitive = p; + return true; + } + TLayoutGeometry getInputPrimitive() const { return inputPrimitive; } + bool setVertexSpacing(TVertexSpacing s) + { + if (vertexSpacing != EvsNone) + return vertexSpacing == s; + vertexSpacing = s; + return true; + } + TVertexSpacing getVertexSpacing() const { return vertexSpacing; } + bool setVertexOrder(TVertexOrder o) + { + if (vertexOrder != EvoNone) + return vertexOrder == o; + vertexOrder = o; + return true; + } + TVertexOrder getVertexOrder() const { return vertexOrder; } + void setPointMode() { pointMode = true; } + bool getPointMode() const { return pointMode; } + + bool setInterlockOrdering(TInterlockOrdering o) + { + if (interlockOrdering != EioNone) + return interlockOrdering == o; + interlockOrdering = o; + return true; + } + TInterlockOrdering getInterlockOrdering() const { return interlockOrdering; } + + void setXfbMode() { xfbMode = true; } + bool getXfbMode() const { return xfbMode; } + void setMultiStream() { multiStream = true; } + bool isMultiStream() const { return multiStream; } + bool setOutputPrimitive(TLayoutGeometry p) + { + if (outputPrimitive != ElgNone) + return outputPrimitive == p; + outputPrimitive = p; + return true; + } + TLayoutGeometry getOutputPrimitive() const { return outputPrimitive; } + void setPostDepthCoverage() { postDepthCoverage = true; } + bool getPostDepthCoverage() const { return postDepthCoverage; } + void setEarlyFragmentTests() { earlyFragmentTests = true; } + bool getEarlyFragmentTests() const { return earlyFragmentTests; } + bool setDepth(TLayoutDepth d) + { + if (depthLayout != EldNone) + return depthLayout == d; + depthLayout = d; + return true; + } + TLayoutDepth getDepth() const { return depthLayout; } + void setOriginUpperLeft() { originUpperLeft = true; } + bool getOriginUpperLeft() const { return originUpperLeft; } + void setPixelCenterInteger() { pixelCenterInteger = true; } + bool getPixelCenterInteger() const { return pixelCenterInteger; } + void addBlendEquation(TBlendEquationShift b) { blendEquations |= (1 << b); } + unsigned int getBlendEquations() const { return blendEquations; } + bool setXfbBufferStride(int buffer, unsigned stride) + { + if (xfbBuffers[buffer].stride != TQualifier::layoutXfbStrideEnd) + return xfbBuffers[buffer].stride == stride; + xfbBuffers[buffer].stride = stride; + return true; + } + unsigned getXfbStride(int buffer) const { return xfbBuffers[buffer].stride; } + int addXfbBufferOffset(const TType&); + unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType, bool& contains32BitType, bool& contains16BitType) const; + unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType) const; + void setLayoutOverrideCoverage() { layoutOverrideCoverage = true; } + bool getLayoutOverrideCoverage() const { return layoutOverrideCoverage; } + void setGeoPassthroughEXT() { geoPassthroughEXT = true; } + bool getGeoPassthroughEXT() const { return geoPassthroughEXT; } + void setLayoutDerivativeMode(ComputeDerivativeMode mode) { computeDerivativeMode = mode; } + bool hasLayoutDerivativeModeNone() const { return computeDerivativeMode != LayoutDerivativeNone; } + ComputeDerivativeMode getLayoutDerivativeModeNone() const { return computeDerivativeMode; } + bool setPrimitives(int m) + { + if (primitives != TQualifier::layoutNotSet) + return primitives == m; + primitives = m; + return true; + } + int getPrimitives() const { return primitives; } + const char* addSemanticName(const TString& name) + { + return semanticNameSet.insert(name).first->c_str(); + } + void addUniformLocationOverride(const char* nameStr, int location) + { + std::string name = nameStr; + uniformLocationOverrides[name] = location; + } + + int getUniformLocationOverride(const char* nameStr) const + { + std::string name = nameStr; + auto pos = uniformLocationOverrides.find(name); + if (pos == uniformLocationOverrides.end()) + return -1; + else + return pos->second; + } + + void setUniformLocationBase(int base) { uniformLocationBase = base; } + int getUniformLocationBase() const { return uniformLocationBase; } + + void setNeedsLegalization() { needToLegalize = true; } + bool needsLegalization() const { return needToLegalize; } + + void setBinaryDoubleOutput() { binaryDoubleOutput = true; } + bool getBinaryDoubleOutput() { return binaryDoubleOutput; } +#endif // GLSLANG_WEB + +#ifdef ENABLE_HLSL + void setHlslFunctionality1() { hlslFunctionality1 = true; } + bool getHlslFunctionality1() const { return hlslFunctionality1; } + void setHlslOffsets() + { + hlslOffsets = true; + if (hlslOffsets) + processes.addProcess("hlsl-offsets"); + } + bool usingHlslOffsets() const { return hlslOffsets; } + void setHlslIoMapping(bool b) + { + hlslIoMapping = b; + if (hlslIoMapping) + processes.addProcess("hlsl-iomap"); + } + bool usingHlslIoMapping() { return hlslIoMapping; } +#else + bool getHlslFunctionality1() const { return false; } + bool usingHlslOffsets() const { return false; } + bool usingHlslIoMapping() { return false; } +#endif + + void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee); + void merge(TInfoSink&, TIntermediate&); + void finalCheck(TInfoSink&, bool keepUncalled); + + bool buildConvertOp(TBasicType dst, TBasicType src, TOperator& convertOp) const; + TIntermTyped* createConversion(TBasicType convertTo, TIntermTyped* node) const; + + void addIoAccessed(const TString& name) { ioAccessed.insert(name); } + bool inIoAccessed(const TString& name) const { return ioAccessed.find(name) != ioAccessed.end(); } + + int addUsedLocation(const TQualifier&, const TType&, bool& typeCollision); + int checkLocationRange(int set, const TIoRange& range, const TType&, bool& typeCollision); + int addUsedOffsets(int binding, int offset, int numOffsets); + bool addUsedConstantId(int id); + static int computeTypeLocationSize(const TType&, EShLanguage); + static int computeTypeUniformLocationSize(const TType&); + + static int getBaseAlignmentScalar(const TType&, int& size); + static int getBaseAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor); + static int getScalarAlignment(const TType&, int& size, int& stride, bool rowMajor); + static int getMemberAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor); + static bool improperStraddle(const TType& type, int size, int offset); + static void updateOffset(const TType& parentType, const TType& memberType, int& offset, int& memberSize); + static int getOffset(const TType& type, int index); + static int getBlockSize(const TType& blockType); + static int computeBufferReferenceTypeSize(const TType&); + bool promote(TIntermOperator*); + void setNanMinMaxClamp(bool setting) { nanMinMaxClamp = setting; } + bool getNanMinMaxClamp() const { return nanMinMaxClamp; } + + void setSourceFile(const char* file) { if (file != nullptr) sourceFile = file; } + const std::string& getSourceFile() const { return sourceFile; } + void addSourceText(const char* text, size_t len) { sourceText.append(text, len); } + const std::string& getSourceText() const { return sourceText; } + const std::map& getIncludeText() const { return includeText; } + void addIncludeText(const char* name, const char* text, size_t len) { includeText[name].assign(text,len); } + void addProcesses(const std::vector& p) + { + for (int i = 0; i < (int)p.size(); ++i) + processes.addProcess(p[i]); + } + void addProcess(const std::string& process) { processes.addProcess(process); } + void addProcessArgument(const std::string& arg) { processes.addArgument(arg); } + const std::vector& getProcesses() const { return processes.getProcesses(); } + + // Certain explicit conversions are allowed conditionally +#ifdef GLSLANG_WEB + bool getArithemeticInt8Enabled() const { return false; } + bool getArithemeticInt16Enabled() const { return false; } + bool getArithemeticFloat16Enabled() const { return false; } +#else + bool getArithemeticInt8Enabled() const { + return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || + extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8); + } + bool getArithemeticInt16Enabled() const { + return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || + extensionRequested(E_GL_AMD_gpu_shader_int16) || + extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16); + } + + bool getArithemeticFloat16Enabled() const { + return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || + extensionRequested(E_GL_AMD_gpu_shader_half_float) || + extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16); + } +#endif + +protected: + TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&); + void error(TInfoSink& infoSink, const char*); + void warn(TInfoSink& infoSink, const char*); + void mergeCallGraphs(TInfoSink&, TIntermediate&); + void mergeModes(TInfoSink&, TIntermediate&); + void mergeTrees(TInfoSink&, TIntermediate&); + void seedIdMap(TIdMaps& idMaps, int& maxId); + void remapIds(const TIdMaps& idMaps, int idShift, TIntermediate&); + void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals); + void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects); + void mergeImplicitArraySizes(TType&, const TType&); + void mergeErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, bool crossStage); + void checkCallGraphCycles(TInfoSink&); + void checkCallGraphBodies(TInfoSink&, bool keepUncalled); + void inOutLocationCheck(TInfoSink&); + TIntermAggregate* findLinkerObjects() const; + bool userOutputUsed() const; + bool isSpecializationOperation(const TIntermOperator&) const; + bool isNonuniformPropagating(TOperator) const; + bool promoteUnary(TIntermUnary&); + bool promoteBinary(TIntermBinary&); + void addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable&, const TString&); + bool promoteAggregate(TIntermAggregate&); + void pushSelector(TIntermSequence&, const TVectorSelector&, const TSourceLoc&); + void pushSelector(TIntermSequence&, const TMatrixSelector&, const TSourceLoc&); + bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&); + void performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root); + bool isConversionAllowed(TOperator op, TIntermTyped* node) const; + std::tuple getConversionDestinatonType(TBasicType type0, TBasicType type1, TOperator op) const; + + // JohnK: I think this function should go away. + // This data structure is just a log to pass on to back ends. + // Versioning and extensions are handled in Version.cpp, with a rich + // set of functions for querying stages, versions, extension enable/disabled, etc. +#ifdef GLSLANG_WEB + bool extensionRequested(const char *extension) const { return false; } +#else + bool extensionRequested(const char *extension) const {return requestedExtensions.find(extension) != requestedExtensions.end();} +#endif + + static const char* getResourceName(TResourceType); + + const EShLanguage language; // stage, known at construction time + std::string entryPointName; + std::string entryPointMangledName; + typedef std::list TGraph; + TGraph callGraph; + + EProfile profile; // source profile + int version; // source version + SpvVersion spvVersion; + TIntermNode* treeRoot; + std::set requestedExtensions; // cumulation of all enabled or required extensions; not connected to what subset of the shader used them + TBuiltInResource resources; + int numEntryPoints; + int numErrors; + int numPushConstants; + bool recursive; + bool invertY; + bool useStorageBuffer; + bool nanMinMaxClamp; // true if desiring min/max/clamp to favor non-NaN over NaN + bool depthReplacing; + int localSize[3]; + bool localSizeNotDefault[3]; + int localSizeSpecId[3]; +#ifndef GLSLANG_WEB +public: + const char* const implicitThisName; + const char* const implicitCounterName; +protected: + EShSource source; // source language, known a bit later + bool useVulkanMemoryModel; + int invocations; + int vertices; + TLayoutGeometry inputPrimitive; + TLayoutGeometry outputPrimitive; + bool pixelCenterInteger; + bool originUpperLeft; + TVertexSpacing vertexSpacing; + TVertexOrder vertexOrder; + TInterlockOrdering interlockOrdering; + bool pointMode; + bool earlyFragmentTests; + bool postDepthCoverage; + TLayoutDepth depthLayout; + bool hlslFunctionality1; + int blendEquations; // an 'or'ing of masks of shifts of TBlendEquationShift + bool xfbMode; + std::vector xfbBuffers; // all the data we need to track per xfb buffer + bool multiStream; + bool layoutOverrideCoverage; + bool geoPassthroughEXT; + int numShaderRecordBlocks; + ComputeDerivativeMode computeDerivativeMode; + int primitives; + int numTaskNVBlocks; + + // Base shift values + std::array shiftBinding; + + // Per-descriptor-set shift values + std::array, EResCount> shiftBindingForSet; + + std::vector resourceSetBinding; + bool autoMapBindings; + bool autoMapLocations; + bool flattenUniformArrays; + bool useUnknownFormat; + bool hlslOffsets; + bool hlslIoMapping; + bool useVariablePointers; + + std::set semanticNameSet; + + EShTextureSamplerTransformMode textureSamplerTransformMode; + + bool needToLegalize; + bool binaryDoubleOutput; + bool usePhysicalStorageBuffer; + + std::unordered_map uniformLocationOverrides; + int uniformLocationBase; +#endif + + std::unordered_set usedConstantId; // specialization constant ids used + std::vector usedAtomics; // sets of bindings used by atomic counters + std::vector usedIo[4]; // sets of used locations, one for each of in, out, uniform, and buffers + // set of names of statically read/written I/O that might need extra checking + std::set ioAccessed; + // source code of shader, useful as part of debug information + std::string sourceFile; + std::string sourceText; + + // Included text. First string is a name, second is the included text + std::map includeText; + + // for OpModuleProcessed, or equivalent + TProcesses processes; + +private: + void operator=(TIntermediate&); // prevent assignments +}; + +} // end namespace glslang + +#endif // _LOCAL_INTERMEDIATE_INCLUDED_ diff --git a/android/armeabi-v7a/include/glslang/MachineIndependent/parseVersions.h b/android/armeabi-v7a/include/glslang/MachineIndependent/parseVersions.h new file mode 100644 index 00000000..aa1964fc --- /dev/null +++ b/android/armeabi-v7a/include/glslang/MachineIndependent/parseVersions.h @@ -0,0 +1,236 @@ +// +// Copyright (C) 2015-2018 Google, Inc. +// Copyright (C) 2017 ARM Limited. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +// This is implemented in Versions.cpp + +#ifndef _PARSE_VERSIONS_INCLUDED_ +#define _PARSE_VERSIONS_INCLUDED_ + +#include "../Public/ShaderLang.h" +#include "../Include/InfoSink.h" +#include "Scan.h" + +#include + +namespace glslang { + +// +// Base class for parse helpers. +// This just has version-related information and checking. +// This class should be sufficient for preprocessing. +// +class TParseVersions { +public: + TParseVersions(TIntermediate& interm, int version, EProfile profile, + const SpvVersion& spvVersion, EShLanguage language, TInfoSink& infoSink, + bool forwardCompatible, EShMessages messages) + : +#ifndef GLSLANG_WEB + forwardCompatible(forwardCompatible), + profile(profile), +#endif + infoSink(infoSink), version(version), + language(language), + spvVersion(spvVersion), + intermediate(interm), messages(messages), numErrors(0), currentScanner(0) { } + virtual ~TParseVersions() { } + void requireStage(const TSourceLoc&, EShLanguageMask, const char* featureDesc); + void requireStage(const TSourceLoc&, EShLanguage, const char* featureDesc); +#ifdef GLSLANG_WEB + const EProfile profile = EEsProfile; + bool isEsProfile() const { return true; } + void requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc) + { + if (! (EEsProfile & profileMask)) + error(loc, "not supported with this profile:", featureDesc, ProfileName(profile)); + } + void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions, + const char* const extensions[], const char* featureDesc) + { + if ((EEsProfile & profileMask) && (minVersion == 0 || version < minVersion)) + error(loc, "not supported for this version or the enabled extensions", featureDesc, ""); + } + void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, const char* extension, + const char* featureDesc) + { + profileRequires(loc, profileMask, minVersion, extension ? 1 : 0, &extension, featureDesc); + } + void initializeExtensionBehavior() { } + void checkDeprecated(const TSourceLoc&, int queryProfiles, int depVersion, const char* featureDesc) { } + void requireNotRemoved(const TSourceLoc&, int queryProfiles, int removedVersion, const char* featureDesc) { } + void requireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], + const char* featureDesc) { } + void ppRequireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], + const char* featureDesc) { } + TExtensionBehavior getExtensionBehavior(const char*) { return EBhMissing; } + bool extensionTurnedOn(const char* const extension) { return false; } + bool extensionsTurnedOn(int numExtensions, const char* const extensions[]) { return false; } + void updateExtensionBehavior(int line, const char* const extension, const char* behavior) { } + void updateExtensionBehavior(const char* const extension, TExtensionBehavior) { } + void checkExtensionStage(const TSourceLoc&, const char* const extension) { } + void fullIntegerCheck(const TSourceLoc&, const char* op) { } + void doubleCheck(const TSourceLoc&, const char* op) { } + bool float16Arithmetic() { return false; } + void requireFloat16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc) { } + bool int16Arithmetic() { return false; } + void requireInt16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc) { } + bool int8Arithmetic() { return false; } + void requireInt8Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc) { } + void int64Check(const TSourceLoc&, const char* op, bool builtIn = false) { } + void explicitFloat32Check(const TSourceLoc&, const char* op, bool builtIn = false) { } + void explicitFloat64Check(const TSourceLoc&, const char* op, bool builtIn = false) { } + bool relaxedErrors() const { return false; } + bool suppressWarnings() const { return true; } + bool isForwardCompatible() const { return false; } +#else + bool forwardCompatible; // true if errors are to be given for use of deprecated features + EProfile profile; // the declared profile in the shader (core by default) + bool isEsProfile() const { return profile == EEsProfile; } + void requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc); + void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions, + const char* const extensions[], const char* featureDesc); + void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, const char* extension, + const char* featureDesc); + virtual void initializeExtensionBehavior(); + virtual void checkDeprecated(const TSourceLoc&, int queryProfiles, int depVersion, const char* featureDesc); + virtual void requireNotRemoved(const TSourceLoc&, int queryProfiles, int removedVersion, const char* featureDesc); + virtual void requireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], + const char* featureDesc); + virtual void ppRequireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], + const char* featureDesc); + virtual TExtensionBehavior getExtensionBehavior(const char*); + virtual bool extensionTurnedOn(const char* const extension); + virtual bool extensionsTurnedOn(int numExtensions, const char* const extensions[]); + virtual void updateExtensionBehavior(int line, const char* const extension, const char* behavior); + virtual void updateExtensionBehavior(const char* const extension, TExtensionBehavior); + virtual bool checkExtensionsRequested(const TSourceLoc&, int numExtensions, const char* const extensions[], + const char* featureDesc); + virtual void checkExtensionStage(const TSourceLoc&, const char* const extension); + virtual void fullIntegerCheck(const TSourceLoc&, const char* op); + + virtual void unimplemented(const TSourceLoc&, const char* featureDesc); + virtual void doubleCheck(const TSourceLoc&, const char* op); + virtual void float16Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void float16ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false); + virtual bool float16Arithmetic(); + virtual void requireFloat16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc); + virtual void int16ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false); + virtual bool int16Arithmetic(); + virtual void requireInt16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc); + virtual void int8ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false); + virtual bool int8Arithmetic(); + virtual void requireInt8Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc); + virtual void float16OpaqueCheck(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void int64Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void explicitInt8Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void explicitInt16Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void explicitInt32Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void explicitFloat32Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void explicitFloat64Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void fcoopmatCheck(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void intcoopmatCheck(const TSourceLoc&, const char *op, bool builtIn = false); + bool relaxedErrors() const { return (messages & EShMsgRelaxedErrors) != 0; } + bool suppressWarnings() const { return (messages & EShMsgSuppressWarnings) != 0; } + bool isForwardCompatible() const { return forwardCompatible; } +#endif // GLSLANG_WEB + virtual void spvRemoved(const TSourceLoc&, const char* op); + virtual void vulkanRemoved(const TSourceLoc&, const char* op); + virtual void requireVulkan(const TSourceLoc&, const char* op); + virtual void requireSpv(const TSourceLoc&, const char* op); + + +#if defined(GLSLANG_WEB) && !defined(GLSLANG_WEB_DEVEL) + void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) { addError(); } + void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) { } + void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) { addError(); } + void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) { } +#else + virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) = 0; + virtual void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) = 0; + virtual void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) = 0; + virtual void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) = 0; +#endif + + void addError() { ++numErrors; } + int getNumErrors() const { return numErrors; } + + void setScanner(TInputScanner* scanner) { currentScanner = scanner; } + TInputScanner* getScanner() const { return currentScanner; } + const TSourceLoc& getCurrentLoc() const { return currentScanner->getSourceLoc(); } + void setCurrentLine(int line) { currentScanner->setLine(line); } + void setCurrentColumn(int col) { currentScanner->setColumn(col); } + void setCurrentSourceName(const char* name) { currentScanner->setFile(name); } + void setCurrentString(int string) { currentScanner->setString(string); } + + void getPreamble(std::string&); +#ifdef ENABLE_HLSL + bool isReadingHLSL() const { return (messages & EShMsgReadHlsl) == EShMsgReadHlsl; } + bool hlslEnable16BitTypes() const { return (messages & EShMsgHlslEnable16BitTypes) != 0; } + bool hlslDX9Compatible() const { return (messages & EShMsgHlslDX9Compatible) != 0; } +#else + bool isReadingHLSL() const { return false; } +#endif + + TInfoSink& infoSink; + + // compilation mode + int version; // version, updated by #version in the shader + EShLanguage language; // really the stage + SpvVersion spvVersion; + TIntermediate& intermediate; // helper for making and hooking up pieces of the parse tree + +protected: + TMap extensionBehavior; // for each extension string, what its current behavior is set to + EShMessages messages; // errors/warnings/rule-sets + int numErrors; // number of compile-time errors encountered + TInputScanner* currentScanner; + +private: + explicit TParseVersions(const TParseVersions&); + TParseVersions& operator=(const TParseVersions&); +}; + +} // end namespace glslang + +#endif // _PARSE_VERSIONS_INCLUDED_ diff --git a/android/armeabi-v7a/include/glslang/MachineIndependent/preprocessor/PpContext.h b/android/armeabi-v7a/include/glslang/MachineIndependent/preprocessor/PpContext.h new file mode 100644 index 00000000..714b5ead --- /dev/null +++ b/android/armeabi-v7a/include/glslang/MachineIndependent/preprocessor/PpContext.h @@ -0,0 +1,703 @@ +// +// Copyright (C) 2013 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ + +#ifndef PPCONTEXT_H +#define PPCONTEXT_H + +#include +#include +#include + +#include "../ParseHelper.h" +#include "PpTokens.h" + +/* windows only pragma */ +#ifdef _MSC_VER + #pragma warning(disable : 4127) +#endif + +namespace glslang { + +class TPpToken { +public: + TPpToken() { clear(); } + void clear() + { + space = false; + i64val = 0; + loc.init(); + name[0] = 0; + } + + // Used for comparing macro definitions, so checks what is relevant for that. + bool operator==(const TPpToken& right) const + { + return space == right.space && + ival == right.ival && dval == right.dval && i64val == right.i64val && + strncmp(name, right.name, MaxTokenLength) == 0; + } + bool operator!=(const TPpToken& right) const { return ! operator==(right); } + + TSourceLoc loc; + // True if a space (for white space or a removed comment) should also be + // recognized, in front of the token returned: + bool space; + // Numeric value of the token: + union { + int ival; + double dval; + long long i64val; + }; + // Text string of the token: + char name[MaxTokenLength + 1]; +}; + +class TStringAtomMap { +// +// Implementation is in PpAtom.cpp +// +// Maintain a bi-directional mapping between relevant preprocessor strings and +// "atoms" which a unique integers (small, contiguous, not hash-like) per string. +// +public: + TStringAtomMap(); + + // Map string -> atom. + // Return 0 if no existing string. + int getAtom(const char* s) const + { + auto it = atomMap.find(s); + return it == atomMap.end() ? 0 : it->second; + } + + // Map a new or existing string -> atom, inventing a new atom if necessary. + int getAddAtom(const char* s) + { + int atom = getAtom(s); + if (atom == 0) { + atom = nextAtom++; + addAtomFixed(s, atom); + } + return atom; + } + + // Map atom -> string. + const char* getString(int atom) const { return stringMap[atom]->c_str(); } + +protected: + TStringAtomMap(TStringAtomMap&); + TStringAtomMap& operator=(TStringAtomMap&); + + TUnorderedMap atomMap; + TVector stringMap; // these point into the TString in atomMap + int nextAtom; + + // Bad source characters can lead to bad atoms, so gracefully handle those by + // pre-filling the table with them (to avoid if tests later). + TString badToken; + + // Add bi-directional mappings: + // - string -> atom + // - atom -> string + void addAtomFixed(const char* s, int atom) + { + auto it = atomMap.insert(std::pair(s, atom)).first; + if (stringMap.size() < (size_t)atom + 1) + stringMap.resize(atom + 100, &badToken); + stringMap[atom] = &it->first; + } +}; + +class TInputScanner; + +enum MacroExpandResult { + MacroExpandNotStarted, // macro not expanded, which might not be an error + MacroExpandError, // a clear error occurred while expanding, no expansion + MacroExpandStarted, // macro expansion process has started + MacroExpandUndef // macro is undefined and will be expanded +}; + +// This class is the result of turning a huge pile of C code communicating through globals +// into a class. This was done to allowing instancing to attain thread safety. +// Don't expect too much in terms of OO design. +class TPpContext { +public: + TPpContext(TParseContextBase&, const std::string& rootFileName, TShader::Includer&); + virtual ~TPpContext(); + + void setPreamble(const char* preamble, size_t length); + + int tokenize(TPpToken& ppToken); + int tokenPaste(int token, TPpToken&); + + class tInput { + public: + tInput(TPpContext* p) : done(false), pp(p) { } + virtual ~tInput() { } + + virtual int scan(TPpToken*) = 0; + virtual int getch() = 0; + virtual void ungetch() = 0; + virtual bool peekPasting() { return false; } // true when about to see ## + virtual bool peekContinuedPasting(int) { return false; } // true when non-spaced tokens can paste + virtual bool endOfReplacementList() { return false; } // true when at the end of a macro replacement list (RHS of #define) + virtual bool isMacroInput() { return false; } + + // Will be called when we start reading tokens from this instance + virtual void notifyActivated() {} + // Will be called when we do not read tokens from this instance anymore + virtual void notifyDeleted() {} + protected: + bool done; + TPpContext* pp; + }; + + void setInput(TInputScanner& input, bool versionWillBeError); + + void pushInput(tInput* in) + { + inputStack.push_back(in); + in->notifyActivated(); + } + void popInput() + { + inputStack.back()->notifyDeleted(); + delete inputStack.back(); + inputStack.pop_back(); + } + + // + // From PpTokens.cpp + // + + // Capture the needed parts of a token stream for macro recording/playback. + class TokenStream { + public: + // Manage a stream of these 'Token', which capture the relevant parts + // of a TPpToken, plus its atom. + class Token { + public: + Token(int atom, const TPpToken& ppToken) : + atom(atom), + space(ppToken.space), + i64val(ppToken.i64val), + name(ppToken.name) { } + int get(TPpToken& ppToken) + { + ppToken.clear(); + ppToken.space = space; + ppToken.i64val = i64val; + snprintf(ppToken.name, sizeof(ppToken.name), "%s", name.c_str()); + return atom; + } + bool isAtom(int a) const { return atom == a; } + int getAtom() const { return atom; } + bool nonSpaced() const { return !space; } + protected: + Token() {} + int atom; + bool space; // did a space precede the token? + long long i64val; + TString name; + }; + + TokenStream() : currentPos(0) { } + + void putToken(int token, TPpToken* ppToken); + bool peekToken(int atom) { return !atEnd() && stream[currentPos].isAtom(atom); } + bool peekContinuedPasting(int atom) + { + // This is basically necessary because, for example, the PP + // tokenizer only accepts valid numeric-literals plus suffixes, so + // separates numeric-literals plus bad suffix into two tokens, which + // should get both pasted together as one token when token pasting. + // + // The following code is a bit more generalized than the above example. + if (!atEnd() && atom == PpAtomIdentifier && stream[currentPos].nonSpaced()) { + switch(stream[currentPos].getAtom()) { + case PpAtomConstInt: + case PpAtomConstUint: + case PpAtomConstInt64: + case PpAtomConstUint64: + case PpAtomConstInt16: + case PpAtomConstUint16: + case PpAtomConstFloat: + case PpAtomConstDouble: + case PpAtomConstFloat16: + case PpAtomConstString: + case PpAtomIdentifier: + return true; + default: + break; + } + } + + return false; + } + int getToken(TParseContextBase&, TPpToken*); + bool atEnd() { return currentPos >= stream.size(); } + bool peekTokenizedPasting(bool lastTokenPastes); + bool peekUntokenizedPasting(); + void reset() { currentPos = 0; } + + protected: + TVector stream; + size_t currentPos; + }; + + // + // From Pp.cpp + // + + struct MacroSymbol { + MacroSymbol() : functionLike(0), busy(0), undef(0) { } + TVector args; + TokenStream body; + unsigned functionLike : 1; // 0 means object-like, 1 means function-like + unsigned busy : 1; + unsigned undef : 1; + }; + + typedef TMap TSymbolMap; + TSymbolMap macroDefs; // map atoms to macro definitions + MacroSymbol* lookupMacroDef(int atom) + { + auto existingMacroIt = macroDefs.find(atom); + return (existingMacroIt == macroDefs.end()) ? nullptr : &(existingMacroIt->second); + } + void addMacroDef(int atom, MacroSymbol& macroDef) { macroDefs[atom] = macroDef; } + +protected: + TPpContext(TPpContext&); + TPpContext& operator=(TPpContext&); + + TStringAtomMap atomStrings; + char* preamble; // string to parse, all before line 1 of string 0, it is 0 if no preamble + int preambleLength; + char** strings; // official strings of shader, starting a string 0 line 1 + size_t* lengths; + int numStrings; // how many official strings there are + int currentString; // which string we're currently parsing (-1 for preamble) + + // Scanner data: + int previous_token; + TParseContextBase& parseContext; + + // Get the next token from *stack* of input sources, popping input sources + // that are out of tokens, down until an input source is found that has a token. + // Return EndOfInput when there are no more tokens to be found by doing this. + int scanToken(TPpToken* ppToken) + { + int token = EndOfInput; + + while (! inputStack.empty()) { + token = inputStack.back()->scan(ppToken); + if (token != EndOfInput || inputStack.empty()) + break; + popInput(); + } + + return token; + } + int getChar() { return inputStack.back()->getch(); } + void ungetChar() { inputStack.back()->ungetch(); } + bool peekPasting() { return !inputStack.empty() && inputStack.back()->peekPasting(); } + bool peekContinuedPasting(int a) + { + return !inputStack.empty() && inputStack.back()->peekContinuedPasting(a); + } + bool endOfReplacementList() { return inputStack.empty() || inputStack.back()->endOfReplacementList(); } + bool isMacroInput() { return inputStack.size() > 0 && inputStack.back()->isMacroInput(); } + + static const int maxIfNesting = 65; + + int ifdepth; // current #if-#else-#endif nesting in the cpp.c file (pre-processor) + bool elseSeen[maxIfNesting]; // Keep a track of whether an else has been seen at a particular depth + int elsetracker; // #if-#else and #endif constructs...Counter. + + class tMacroInput : public tInput { + public: + tMacroInput(TPpContext* pp) : tInput(pp), prepaste(false), postpaste(false) { } + virtual ~tMacroInput() + { + for (size_t i = 0; i < args.size(); ++i) + delete args[i]; + for (size_t i = 0; i < expandedArgs.size(); ++i) + delete expandedArgs[i]; + } + + virtual int scan(TPpToken*) override; + virtual int getch() override { assert(0); return EndOfInput; } + virtual void ungetch() override { assert(0); } + bool peekPasting() override { return prepaste; } + bool peekContinuedPasting(int a) override { return mac->body.peekContinuedPasting(a); } + bool endOfReplacementList() override { return mac->body.atEnd(); } + bool isMacroInput() override { return true; } + + MacroSymbol *mac; + TVector args; + TVector expandedArgs; + + protected: + bool prepaste; // true if we are just before ## + bool postpaste; // true if we are right after ## + }; + + class tMarkerInput : public tInput { + public: + tMarkerInput(TPpContext* pp) : tInput(pp) { } + virtual int scan(TPpToken*) override + { + if (done) + return EndOfInput; + done = true; + + return marker; + } + virtual int getch() override { assert(0); return EndOfInput; } + virtual void ungetch() override { assert(0); } + static const int marker = -3; + }; + + class tZeroInput : public tInput { + public: + tZeroInput(TPpContext* pp) : tInput(pp) { } + virtual int scan(TPpToken*) override; + virtual int getch() override { assert(0); return EndOfInput; } + virtual void ungetch() override { assert(0); } + }; + + std::vector inputStack; + bool errorOnVersion; + bool versionSeen; + + // + // from Pp.cpp + // + + // Used to obtain #include content. + TShader::Includer& includer; + + int CPPdefine(TPpToken * ppToken); + int CPPundef(TPpToken * ppToken); + int CPPelse(int matchelse, TPpToken * ppToken); + int extraTokenCheck(int atom, TPpToken* ppToken, int token); + int eval(int token, int precedence, bool shortCircuit, int& res, bool& err, TPpToken * ppToken); + int evalToToken(int token, bool shortCircuit, int& res, bool& err, TPpToken * ppToken); + int CPPif (TPpToken * ppToken); + int CPPifdef(int defined, TPpToken * ppToken); + int CPPinclude(TPpToken * ppToken); + int CPPline(TPpToken * ppToken); + int CPPerror(TPpToken * ppToken); + int CPPpragma(TPpToken * ppToken); + int CPPversion(TPpToken * ppToken); + int CPPextension(TPpToken * ppToken); + int readCPPline(TPpToken * ppToken); + int scanHeaderName(TPpToken* ppToken, char delimit); + TokenStream* PrescanMacroArg(TokenStream&, TPpToken*, bool newLineOkay); + MacroExpandResult MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay); + + // + // From PpTokens.cpp + // + void pushTokenStreamInput(TokenStream&, bool pasting = false); + void UngetToken(int token, TPpToken*); + + class tTokenInput : public tInput { + public: + tTokenInput(TPpContext* pp, TokenStream* t, bool prepasting) : + tInput(pp), + tokens(t), + lastTokenPastes(prepasting) { } + virtual int scan(TPpToken *ppToken) override { return tokens->getToken(pp->parseContext, ppToken); } + virtual int getch() override { assert(0); return EndOfInput; } + virtual void ungetch() override { assert(0); } + virtual bool peekPasting() override { return tokens->peekTokenizedPasting(lastTokenPastes); } + bool peekContinuedPasting(int a) override { return tokens->peekContinuedPasting(a); } + protected: + TokenStream* tokens; + bool lastTokenPastes; // true if the last token in the input is to be pasted, rather than consumed as a token + }; + + class tUngotTokenInput : public tInput { + public: + tUngotTokenInput(TPpContext* pp, int t, TPpToken* p) : tInput(pp), token(t), lval(*p) { } + virtual int scan(TPpToken *) override; + virtual int getch() override { assert(0); return EndOfInput; } + virtual void ungetch() override { assert(0); } + protected: + int token; + TPpToken lval; + }; + + // + // From PpScanner.cpp + // + class tStringInput : public tInput { + public: + tStringInput(TPpContext* pp, TInputScanner& i) : tInput(pp), input(&i) { } + virtual int scan(TPpToken*) override; + + // Scanner used to get source stream characters. + // - Escaped newlines are handled here, invisibly to the caller. + // - All forms of newline are handled, and turned into just a '\n'. + int getch() override + { + int ch = input->get(); + + if (ch == '\\') { + // Move past escaped newlines, as many as sequentially exist + do { + if (input->peek() == '\r' || input->peek() == '\n') { + bool allowed = pp->parseContext.lineContinuationCheck(input->getSourceLoc(), pp->inComment); + if (! allowed && pp->inComment) + return '\\'; + + // escape one newline now + ch = input->get(); + int nextch = input->get(); + if (ch == '\r' && nextch == '\n') + ch = input->get(); + else + ch = nextch; + } else + return '\\'; + } while (ch == '\\'); + } + + // handle any non-escaped newline + if (ch == '\r' || ch == '\n') { + if (ch == '\r' && input->peek() == '\n') + input->get(); + return '\n'; + } + + return ch; + } + + // Scanner used to backup the source stream characters. Newlines are + // handled here, invisibly to the caller, meaning have to undo exactly + // what getch() above does (e.g., don't leave things in the middle of a + // sequence of escaped newlines). + void ungetch() override + { + input->unget(); + + do { + int ch = input->peek(); + if (ch == '\r' || ch == '\n') { + if (ch == '\n') { + // correct for two-character newline + input->unget(); + if (input->peek() != '\r') + input->get(); + } + // now in front of a complete newline, move past an escape character + input->unget(); + if (input->peek() == '\\') + input->unget(); + else { + input->get(); + break; + } + } else + break; + } while (true); + } + + protected: + TInputScanner* input; + }; + + // Holds a reference to included file data, as well as a + // prologue and an epilogue string. This can be scanned using the tInput + // interface and acts as a single source string. + class TokenizableIncludeFile : public tInput { + public: + // Copies prologue and epilogue. The includedFile must remain valid + // until this TokenizableIncludeFile is no longer used. + TokenizableIncludeFile(const TSourceLoc& startLoc, + const std::string& prologue, + TShader::Includer::IncludeResult* includedFile, + const std::string& epilogue, + TPpContext* pp) + : tInput(pp), + prologue_(prologue), + epilogue_(epilogue), + includedFile_(includedFile), + scanner(3, strings, lengths, nullptr, 0, 0, true), + prevScanner(nullptr), + stringInput(pp, scanner) + { + strings[0] = prologue_.data(); + strings[1] = includedFile_->headerData; + strings[2] = epilogue_.data(); + + lengths[0] = prologue_.size(); + lengths[1] = includedFile_->headerLength; + lengths[2] = epilogue_.size(); + + scanner.setLine(startLoc.line); + scanner.setString(startLoc.string); + + scanner.setFile(startLoc.getFilenameStr(), 0); + scanner.setFile(startLoc.getFilenameStr(), 1); + scanner.setFile(startLoc.getFilenameStr(), 2); + } + + // tInput methods: + int scan(TPpToken* t) override { return stringInput.scan(t); } + int getch() override { return stringInput.getch(); } + void ungetch() override { stringInput.ungetch(); } + + void notifyActivated() override + { + prevScanner = pp->parseContext.getScanner(); + pp->parseContext.setScanner(&scanner); + pp->push_include(includedFile_); + } + + void notifyDeleted() override + { + pp->parseContext.setScanner(prevScanner); + pp->pop_include(); + } + + private: + TokenizableIncludeFile& operator=(const TokenizableIncludeFile&); + + // Stores the prologue for this string. + const std::string prologue_; + + // Stores the epilogue for this string. + const std::string epilogue_; + + // Points to the IncludeResult that this TokenizableIncludeFile represents. + TShader::Includer::IncludeResult* includedFile_; + + // Will point to prologue_, includedFile_->headerData and epilogue_ + // This is passed to scanner constructor. + // These do not own the storage and it must remain valid until this + // object has been destroyed. + const char* strings[3]; + // Length of str_, passed to scanner constructor. + size_t lengths[3]; + // Scans over str_. + TInputScanner scanner; + // The previous effective scanner before the scanner in this instance + // has been activated. + TInputScanner* prevScanner; + // Delegate object implementing the tInput interface. + tStringInput stringInput; + }; + + int ScanFromString(char* s); + void missingEndifCheck(); + int lFloatConst(int len, int ch, TPpToken* ppToken); + int characterLiteral(TPpToken* ppToken); + + void push_include(TShader::Includer::IncludeResult* result) + { + currentSourceFile = result->headerName; + includeStack.push(result); + } + + void pop_include() + { + TShader::Includer::IncludeResult* include = includeStack.top(); + includeStack.pop(); + includer.releaseInclude(include); + if (includeStack.empty()) { + currentSourceFile = rootFileName; + } else { + currentSourceFile = includeStack.top()->headerName; + } + } + + bool inComment; + std::string rootFileName; + std::stack includeStack; + std::string currentSourceFile; + + std::istringstream strtodStream; + bool disableEscapeSequences; +}; + +} // end namespace glslang + +#endif // PPCONTEXT_H diff --git a/android/armeabi-v7a/include/glslang/MachineIndependent/preprocessor/PpTokens.h b/android/armeabi-v7a/include/glslang/MachineIndependent/preprocessor/PpTokens.h new file mode 100644 index 00000000..7b0f8155 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/MachineIndependent/preprocessor/PpTokens.h @@ -0,0 +1,179 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ + +#ifndef PARSER_H +#define PARSER_H + +namespace glslang { + +// Multi-character tokens +enum EFixedAtoms { + // single character tokens get their own char value as their token; start here for multi-character tokens + PpAtomMaxSingle = 127, + + // replace bad character tokens with this, to avoid accidental aliasing with the below + PpAtomBadToken, + + // Operators + + PPAtomAddAssign, + PPAtomSubAssign, + PPAtomMulAssign, + PPAtomDivAssign, + PPAtomModAssign, + + PpAtomRight, + PpAtomLeft, + + PpAtomRightAssign, + PpAtomLeftAssign, + PpAtomAndAssign, + PpAtomOrAssign, + PpAtomXorAssign, + + PpAtomAnd, + PpAtomOr, + PpAtomXor, + + PpAtomEQ, + PpAtomNE, + PpAtomGE, + PpAtomLE, + + PpAtomDecrement, + PpAtomIncrement, + + PpAtomColonColon, + + PpAtomPaste, + + // Constants + + PpAtomConstInt, + PpAtomConstUint, + PpAtomConstInt64, + PpAtomConstUint64, + PpAtomConstInt16, + PpAtomConstUint16, + PpAtomConstFloat, + PpAtomConstDouble, + PpAtomConstFloat16, + PpAtomConstString, + + // Identifiers + PpAtomIdentifier, + + // preprocessor "keywords" + + PpAtomDefine, + PpAtomUndef, + + PpAtomIf, + PpAtomIfdef, + PpAtomIfndef, + PpAtomElse, + PpAtomElif, + PpAtomEndif, + + PpAtomLine, + PpAtomPragma, + PpAtomError, + + // #version ... + PpAtomVersion, + PpAtomCore, + PpAtomCompatibility, + PpAtomEs, + + // #extension + PpAtomExtension, + + // __LINE__, __FILE__, __VERSION__ + + PpAtomLineMacro, + PpAtomFileMacro, + PpAtomVersionMacro, + + // #include + PpAtomInclude, + + PpAtomLast, +}; + +} // end namespace glslang + +#endif /* not PARSER_H */ diff --git a/android/armeabi-v7a/include/glslang/MachineIndependent/propagateNoContraction.h b/android/armeabi-v7a/include/glslang/MachineIndependent/propagateNoContraction.h new file mode 100644 index 00000000..8521ad7d --- /dev/null +++ b/android/armeabi-v7a/include/glslang/MachineIndependent/propagateNoContraction.h @@ -0,0 +1,55 @@ +// +// Copyright (C) 2015-2016 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Visit the nodes in the glslang intermediate tree representation to +// propagate 'noContraction' qualifier. +// + +#pragma once + +#include "../Include/intermediate.h" + +namespace glslang { + +// Propagates the 'precise' qualifier for objects (objects marked with +// 'noContraction' qualifier) from the shader source specified 'precise' +// variables to all the involved objects, and add 'noContraction' qualifier for +// the involved arithmetic operations. +// Note that the same qualifier: 'noContraction' is used in both object nodes +// and arithmetic operation nodes, but has different meaning. For object nodes, +// 'noContraction' means the object is 'precise'; and for arithmetic operation +// nodes, it means the operation should not be contracted. +void PropagateNoContraction(const glslang::TIntermediate& intermediate); +}; diff --git a/android/armeabi-v7a/include/glslang/MachineIndependent/reflection.h b/android/armeabi-v7a/include/glslang/MachineIndependent/reflection.h new file mode 100644 index 00000000..0c33de45 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/MachineIndependent/reflection.h @@ -0,0 +1,223 @@ +// +// Copyright (C) 2013-2016 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef GLSLANG_WEB + +#ifndef _REFLECTION_INCLUDED +#define _REFLECTION_INCLUDED + +#include "../Public/ShaderLang.h" +#include "../Include/Types.h" + +#include +#include + +// +// A reflection database and its interface, consistent with the OpenGL API reflection queries. +// + +namespace glslang { + +class TIntermediate; +class TIntermAggregate; +class TReflectionTraverser; + +// The full reflection database +class TReflection { +public: + TReflection(EShReflectionOptions opts, EShLanguage first, EShLanguage last) + : options(opts), firstStage(first), lastStage(last), badReflection(TObjectReflection::badReflection()) + { + for (int dim=0; dim<3; ++dim) + localSize[dim] = 0; + } + + virtual ~TReflection() {} + + // grow the reflection stage by stage + bool addStage(EShLanguage, const TIntermediate&); + + // for mapping a uniform index to a uniform object's description + int getNumUniforms() { return (int)indexToUniform.size(); } + const TObjectReflection& getUniform(int i) const + { + if (i >= 0 && i < (int)indexToUniform.size()) + return indexToUniform[i]; + else + return badReflection; + } + + // for mapping a block index to the block's description + int getNumUniformBlocks() const { return (int)indexToUniformBlock.size(); } + const TObjectReflection& getUniformBlock(int i) const + { + if (i >= 0 && i < (int)indexToUniformBlock.size()) + return indexToUniformBlock[i]; + else + return badReflection; + } + + // for mapping an pipeline input index to the input's description + int getNumPipeInputs() { return (int)indexToPipeInput.size(); } + const TObjectReflection& getPipeInput(int i) const + { + if (i >= 0 && i < (int)indexToPipeInput.size()) + return indexToPipeInput[i]; + else + return badReflection; + } + + // for mapping an pipeline output index to the output's description + int getNumPipeOutputs() { return (int)indexToPipeOutput.size(); } + const TObjectReflection& getPipeOutput(int i) const + { + if (i >= 0 && i < (int)indexToPipeOutput.size()) + return indexToPipeOutput[i]; + else + return badReflection; + } + + // for mapping from an atomic counter to the uniform index + int getNumAtomicCounters() const { return (int)atomicCounterUniformIndices.size(); } + const TObjectReflection& getAtomicCounter(int i) const + { + if (i >= 0 && i < (int)atomicCounterUniformIndices.size()) + return getUniform(atomicCounterUniformIndices[i]); + else + return badReflection; + } + + // for mapping a buffer variable index to a buffer variable object's description + int getNumBufferVariables() { return (int)indexToBufferVariable.size(); } + const TObjectReflection& getBufferVariable(int i) const + { + if (i >= 0 && i < (int)indexToBufferVariable.size()) + return indexToBufferVariable[i]; + else + return badReflection; + } + + // for mapping a storage block index to the storage block's description + int getNumStorageBuffers() const { return (int)indexToBufferBlock.size(); } + const TObjectReflection& getStorageBufferBlock(int i) const + { + if (i >= 0 && i < (int)indexToBufferBlock.size()) + return indexToBufferBlock[i]; + else + return badReflection; + } + + // for mapping any name to its index (block names, uniform names and input/output names) + int getIndex(const char* name) const + { + TNameToIndex::const_iterator it = nameToIndex.find(name); + if (it == nameToIndex.end()) + return -1; + else + return it->second; + } + + // see getIndex(const char*) + int getIndex(const TString& name) const { return getIndex(name.c_str()); } + + + // for mapping any name to its index (only pipe input/output names) + int getPipeIOIndex(const char* name, const bool inOrOut) const + { + TNameToIndex::const_iterator it = inOrOut ? pipeInNameToIndex.find(name) : pipeOutNameToIndex.find(name); + if (it == (inOrOut ? pipeInNameToIndex.end() : pipeOutNameToIndex.end())) + return -1; + else + return it->second; + } + + // see gePipeIOIndex(const char*, const bool) + int getPipeIOIndex(const TString& name, const bool inOrOut) const { return getPipeIOIndex(name.c_str(), inOrOut); } + + // Thread local size + unsigned getLocalSize(int dim) const { return dim <= 2 ? localSize[dim] : 0; } + + void dump(); + +protected: + friend class glslang::TReflectionTraverser; + + void buildCounterIndices(const TIntermediate&); + void buildUniformStageMask(const TIntermediate& intermediate); + void buildAttributeReflection(EShLanguage, const TIntermediate&); + + // Need a TString hash: typedef std::unordered_map TNameToIndex; + typedef std::map TNameToIndex; + typedef std::vector TMapIndexToReflection; + typedef std::vector TIndices; + + TMapIndexToReflection& GetBlockMapForStorage(TStorageQualifier storage) + { + if ((options & EShReflectionSeparateBuffers) && storage == EvqBuffer) + return indexToBufferBlock; + return indexToUniformBlock; + } + TMapIndexToReflection& GetVariableMapForStorage(TStorageQualifier storage) + { + if ((options & EShReflectionSeparateBuffers) && storage == EvqBuffer) + return indexToBufferVariable; + return indexToUniform; + } + + EShReflectionOptions options; + + EShLanguage firstStage; + EShLanguage lastStage; + + TObjectReflection badReflection; // return for queries of -1 or generally out of range; has expected descriptions with in it for this + TNameToIndex nameToIndex; // maps names to indexes; can hold all types of data: uniform/buffer and which function names have been processed + TNameToIndex pipeInNameToIndex; // maps pipe in names to indexes, this is a fix to seperate pipe I/O from uniforms and buffers. + TNameToIndex pipeOutNameToIndex; // maps pipe out names to indexes, this is a fix to seperate pipe I/O from uniforms and buffers. + TMapIndexToReflection indexToUniform; + TMapIndexToReflection indexToUniformBlock; + TMapIndexToReflection indexToBufferVariable; + TMapIndexToReflection indexToBufferBlock; + TMapIndexToReflection indexToPipeInput; + TMapIndexToReflection indexToPipeOutput; + TIndices atomicCounterUniformIndices; + + unsigned int localSize[3]; +}; + +} // end namespace glslang + +#endif // _REFLECTION_INCLUDED + +#endif // GLSLANG_WEB diff --git a/android/armeabi-v7a/include/glslang/Public/ShaderLang.h b/android/armeabi-v7a/include/glslang/Public/ShaderLang.h new file mode 100644 index 00000000..acb2a078 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/Public/ShaderLang.h @@ -0,0 +1,927 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013-2016 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +#ifndef _COMPILER_INTERFACE_INCLUDED_ +#define _COMPILER_INTERFACE_INCLUDED_ + +#include "../Include/ResourceLimits.h" +#include "../MachineIndependent/Versions.h" + +#include +#include + +#ifdef _WIN32 +#define C_DECL __cdecl +//#ifdef SH_EXPORTING +// #define SH_IMPORT_EXPORT __declspec(dllexport) +//#else +// #define SH_IMPORT_EXPORT __declspec(dllimport) +//#endif +#define SH_IMPORT_EXPORT +#else +#define SH_IMPORT_EXPORT +#define C_DECL +#endif + +// +// This is the platform independent interface between an OGL driver +// and the shading language compiler/linker. +// + +#ifdef __cplusplus + extern "C" { +#endif + +// This should always increase, as some paths to do not consume +// a more major number. +// It should increment by one when new functionality is added. +#define GLSLANG_MINOR_VERSION 13 + +// +// Call before doing any other compiler/linker operations. +// +// (Call once per process, not once per thread.) +// +SH_IMPORT_EXPORT int ShInitialize(); + +// +// Call this at process shutdown to clean up memory. +// +SH_IMPORT_EXPORT int ShFinalize(); + +// +// Types of languages the compiler can consume. +// +typedef enum { + EShLangVertex, + EShLangTessControl, + EShLangTessEvaluation, + EShLangGeometry, + EShLangFragment, + EShLangCompute, + EShLangRayGen, + EShLangRayGenNV = EShLangRayGen, + EShLangIntersect, + EShLangIntersectNV = EShLangIntersect, + EShLangAnyHit, + EShLangAnyHitNV = EShLangAnyHit, + EShLangClosestHit, + EShLangClosestHitNV = EShLangClosestHit, + EShLangMiss, + EShLangMissNV = EShLangMiss, + EShLangCallable, + EShLangCallableNV = EShLangCallable, + EShLangTaskNV, + EShLangMeshNV, + LAST_ELEMENT_MARKER(EShLangCount), +} EShLanguage; // would be better as stage, but this is ancient now + +typedef enum { + EShLangVertexMask = (1 << EShLangVertex), + EShLangTessControlMask = (1 << EShLangTessControl), + EShLangTessEvaluationMask = (1 << EShLangTessEvaluation), + EShLangGeometryMask = (1 << EShLangGeometry), + EShLangFragmentMask = (1 << EShLangFragment), + EShLangComputeMask = (1 << EShLangCompute), + EShLangRayGenMask = (1 << EShLangRayGen), + EShLangRayGenNVMask = EShLangRayGenMask, + EShLangIntersectMask = (1 << EShLangIntersect), + EShLangIntersectNVMask = EShLangIntersectMask, + EShLangAnyHitMask = (1 << EShLangAnyHit), + EShLangAnyHitNVMask = EShLangAnyHitMask, + EShLangClosestHitMask = (1 << EShLangClosestHit), + EShLangClosestHitNVMask = EShLangClosestHitMask, + EShLangMissMask = (1 << EShLangMiss), + EShLangMissNVMask = EShLangMissMask, + EShLangCallableMask = (1 << EShLangCallable), + EShLangCallableNVMask = EShLangCallableMask, + EShLangTaskNVMask = (1 << EShLangTaskNV), + EShLangMeshNVMask = (1 << EShLangMeshNV), + LAST_ELEMENT_MARKER(EShLanguageMaskCount), +} EShLanguageMask; + +namespace glslang { + +class TType; + +typedef enum { + EShSourceNone, + EShSourceGlsl, // GLSL, includes ESSL (OpenGL ES GLSL) + EShSourceHlsl, // HLSL + LAST_ELEMENT_MARKER(EShSourceCount), +} EShSource; // if EShLanguage were EShStage, this could be EShLanguage instead + +typedef enum { + EShClientNone, // use when there is no client, e.g. for validation + EShClientVulkan, + EShClientOpenGL, + LAST_ELEMENT_MARKER(EShClientCount), +} EShClient; + +typedef enum { + EShTargetNone, + EShTargetSpv, // SPIR-V (preferred spelling) + EshTargetSpv = EShTargetSpv, // legacy spelling + LAST_ELEMENT_MARKER(EShTargetCount), +} EShTargetLanguage; + +typedef enum { + EShTargetVulkan_1_0 = (1 << 22), // Vulkan 1.0 + EShTargetVulkan_1_1 = (1 << 22) | (1 << 12), // Vulkan 1.1 + EShTargetVulkan_1_2 = (1 << 22) | (2 << 12), // Vulkan 1.2 + EShTargetOpenGL_450 = 450, // OpenGL + LAST_ELEMENT_MARKER(EShTargetClientVersionCount), +} EShTargetClientVersion; + +typedef EShTargetClientVersion EshTargetClientVersion; + +typedef enum { + EShTargetSpv_1_0 = (1 << 16), // SPIR-V 1.0 + EShTargetSpv_1_1 = (1 << 16) | (1 << 8), // SPIR-V 1.1 + EShTargetSpv_1_2 = (1 << 16) | (2 << 8), // SPIR-V 1.2 + EShTargetSpv_1_3 = (1 << 16) | (3 << 8), // SPIR-V 1.3 + EShTargetSpv_1_4 = (1 << 16) | (4 << 8), // SPIR-V 1.4 + EShTargetSpv_1_5 = (1 << 16) | (5 << 8), // SPIR-V 1.5 + LAST_ELEMENT_MARKER(EShTargetLanguageVersionCount), +} EShTargetLanguageVersion; + +struct TInputLanguage { + EShSource languageFamily; // redundant information with other input, this one overrides when not EShSourceNone + EShLanguage stage; // redundant information with other input, this one overrides when not EShSourceNone + EShClient dialect; + int dialectVersion; // version of client's language definition, not the client (when not EShClientNone) +}; + +struct TClient { + EShClient client; + EShTargetClientVersion version; // version of client itself (not the client's input dialect) +}; + +struct TTarget { + EShTargetLanguage language; + EShTargetLanguageVersion version; // version to target, if SPIR-V, defined by "word 1" of the SPIR-V header + bool hlslFunctionality1; // can target hlsl_functionality1 extension(s) +}; + +// All source/client/target versions and settings. +// Can override previous methods of setting, when items are set here. +// Expected to grow, as more are added, rather than growing parameter lists. +struct TEnvironment { + TInputLanguage input; // definition of the input language + TClient client; // what client is the overall compilation being done for? + TTarget target; // what to generate +}; + +const char* StageName(EShLanguage); + +} // end namespace glslang + +// +// Types of output the linker will create. +// +typedef enum { + EShExVertexFragment, + EShExFragment +} EShExecutable; + +// +// Optimization level for the compiler. +// +typedef enum { + EShOptNoGeneration, + EShOptNone, + EShOptSimple, // Optimizations that can be done quickly + EShOptFull, // Optimizations that will take more time + LAST_ELEMENT_MARKER(EshOptLevelCount), +} EShOptimizationLevel; + +// +// Texture and Sampler transformation mode. +// +typedef enum { + EShTexSampTransKeep, // keep textures and samplers as is (default) + EShTexSampTransUpgradeTextureRemoveSampler, // change texture w/o embeded sampler into sampled texture and throw away all samplers + LAST_ELEMENT_MARKER(EShTexSampTransCount), +} EShTextureSamplerTransformMode; + +// +// Message choices for what errors and warnings are given. +// +enum EShMessages { + EShMsgDefault = 0, // default is to give all required errors and extra warnings + EShMsgRelaxedErrors = (1 << 0), // be liberal in accepting input + EShMsgSuppressWarnings = (1 << 1), // suppress all warnings, except those required by the specification + EShMsgAST = (1 << 2), // print the AST intermediate representation + EShMsgSpvRules = (1 << 3), // issue messages for SPIR-V generation + EShMsgVulkanRules = (1 << 4), // issue messages for Vulkan-requirements of GLSL for SPIR-V + EShMsgOnlyPreprocessor = (1 << 5), // only print out errors produced by the preprocessor + EShMsgReadHlsl = (1 << 6), // use HLSL parsing rules and semantics + EShMsgCascadingErrors = (1 << 7), // get cascading errors; risks error-recovery issues, instead of an early exit + EShMsgKeepUncalled = (1 << 8), // for testing, don't eliminate uncalled functions + EShMsgHlslOffsets = (1 << 9), // allow block offsets to follow HLSL rules instead of GLSL rules + EShMsgDebugInfo = (1 << 10), // save debug information + EShMsgHlslEnable16BitTypes = (1 << 11), // enable use of 16-bit types in SPIR-V for HLSL + EShMsgHlslLegalization = (1 << 12), // enable HLSL Legalization messages + EShMsgHlslDX9Compatible = (1 << 13), // enable HLSL DX9 compatible mode (right now only for samplers) + EShMsgBuiltinSymbolTable = (1 << 14), // print the builtin symbol table + LAST_ELEMENT_MARKER(EShMsgCount), +}; + +// +// Options for building reflection +// +typedef enum { + EShReflectionDefault = 0, // default is original behaviour before options were added + EShReflectionStrictArraySuffix = (1 << 0), // reflection will follow stricter rules for array-of-structs suffixes + EShReflectionBasicArraySuffix = (1 << 1), // arrays of basic types will be appended with [0] as in GL reflection + EShReflectionIntermediateIO = (1 << 2), // reflect inputs and outputs to program, even with no vertex shader + EShReflectionSeparateBuffers = (1 << 3), // buffer variables and buffer blocks are reflected separately + EShReflectionAllBlockVariables = (1 << 4), // reflect all variables in blocks, even if they are inactive + EShReflectionUnwrapIOBlocks = (1 << 5), // unwrap input/output blocks the same as with uniform blocks + LAST_ELEMENT_MARKER(EShReflectionCount), +} EShReflectionOptions; + +// +// Build a table for bindings. This can be used for locating +// attributes, uniforms, globals, etc., as needed. +// +typedef struct { + const char* name; + int binding; +} ShBinding; + +typedef struct { + int numBindings; + ShBinding* bindings; // array of bindings +} ShBindingTable; + +// +// ShHandle held by but opaque to the driver. It is allocated, +// managed, and de-allocated by the compiler/linker. It's contents +// are defined by and used by the compiler and linker. For example, +// symbol table information and object code passed from the compiler +// to the linker can be stored where ShHandle points. +// +// If handle creation fails, 0 will be returned. +// +typedef void* ShHandle; + +// +// Driver calls these to create and destroy compiler/linker +// objects. +// +SH_IMPORT_EXPORT ShHandle ShConstructCompiler(const EShLanguage, int debugOptions); // one per shader +SH_IMPORT_EXPORT ShHandle ShConstructLinker(const EShExecutable, int debugOptions); // one per shader pair +SH_IMPORT_EXPORT ShHandle ShConstructUniformMap(); // one per uniform namespace (currently entire program object) +SH_IMPORT_EXPORT void ShDestruct(ShHandle); + +// +// The return value of ShCompile is boolean, non-zero indicating +// success. +// +// The info-log should be written by ShCompile into +// ShHandle, so it can answer future queries. +// +SH_IMPORT_EXPORT int ShCompile( + const ShHandle, + const char* const shaderStrings[], + const int numStrings, + const int* lengths, + const EShOptimizationLevel, + const TBuiltInResource *resources, + int debugOptions, + int defaultVersion = 110, // use 100 for ES environment, overridden by #version in shader + bool forwardCompatible = false, // give errors for use of deprecated features + EShMessages messages = EShMsgDefault // warnings and errors + ); + +SH_IMPORT_EXPORT int ShLinkExt( + const ShHandle, // linker object + const ShHandle h[], // compiler objects to link together + const int numHandles); + +// +// ShSetEncrpytionMethod is a place-holder for specifying +// how source code is encrypted. +// +SH_IMPORT_EXPORT void ShSetEncryptionMethod(ShHandle); + +// +// All the following return 0 if the information is not +// available in the object passed down, or the object is bad. +// +SH_IMPORT_EXPORT const char* ShGetInfoLog(const ShHandle); +SH_IMPORT_EXPORT const void* ShGetExecutable(const ShHandle); +SH_IMPORT_EXPORT int ShSetVirtualAttributeBindings(const ShHandle, const ShBindingTable*); // to detect user aliasing +SH_IMPORT_EXPORT int ShSetFixedAttributeBindings(const ShHandle, const ShBindingTable*); // to force any physical mappings +// +// Tell the linker to never assign a vertex attribute to this list of physical attributes +// +SH_IMPORT_EXPORT int ShExcludeAttributes(const ShHandle, int *attributes, int count); + +// +// Returns the location ID of the named uniform. +// Returns -1 if error. +// +SH_IMPORT_EXPORT int ShGetUniformLocation(const ShHandle uniformMap, const char* name); + +#ifdef __cplusplus + } // end extern "C" +#endif + +//////////////////////////////////////////////////////////////////////////////////////////// +// +// Deferred-Lowering C++ Interface +// ----------------------------------- +// +// Below is a new alternate C++ interface, which deprecates the above +// opaque handle-based interface. +// +// The below is further designed to handle multiple compilation units per stage, where +// the intermediate results, including the parse tree, are preserved until link time, +// rather than the above interface which is designed to have each compilation unit +// lowered at compile time. In the above model, linking occurs on the lowered results, +// whereas in this model intra-stage linking can occur at the parse tree +// (treeRoot in TIntermediate) level, and then a full stage can be lowered. +// + +#include +#include +#include + +class TCompiler; +class TInfoSink; + +namespace glslang { + +const char* GetEsslVersionString(); +const char* GetGlslVersionString(); +int GetKhronosToolId(); + +class TIntermediate; +class TProgram; +class TPoolAllocator; + +// Call this exactly once per process before using anything else +bool InitializeProcess(); + +// Call once per process to tear down everything +void FinalizeProcess(); + +// Resource type for IO resolver +enum TResourceType { + EResSampler, + EResTexture, + EResImage, + EResUbo, + EResSsbo, + EResUav, + EResCount +}; + +// Make one TShader per shader that you will link into a program. Then +// - provide the shader through setStrings() or setStringsWithLengths() +// - optionally call setEnv*(), see below for more detail +// - optionally use setPreamble() to set a special shader string that will be +// processed before all others but won't affect the validity of #version +// - optionally call addProcesses() for each setting/transform, +// see comment for class TProcesses +// - call parse(): source language and target environment must be selected +// either by correct setting of EShMessages sent to parse(), or by +// explicitly calling setEnv*() +// - query the info logs +// +// N.B.: Does not yet support having the same TShader instance being linked into +// multiple programs. +// +// N.B.: Destruct a linked program *before* destructing the shaders linked into it. +// +class TShader { +public: + explicit TShader(EShLanguage); + virtual ~TShader(); + void setStrings(const char* const* s, int n); + void setStringsWithLengths(const char* const* s, const int* l, int n); + void setStringsWithLengthsAndNames( + const char* const* s, const int* l, const char* const* names, int n); + void setPreamble(const char* s) { preamble = s; } + void setEntryPoint(const char* entryPoint); + void setSourceEntryPoint(const char* sourceEntryPointName); + void addProcesses(const std::vector&); + + // IO resolver binding data: see comments in ShaderLang.cpp + void setShiftBinding(TResourceType res, unsigned int base); + void setShiftSamplerBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftTextureBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftImageBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftUboBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftUavBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftCbufferBinding(unsigned int base); // synonym for setShiftUboBinding + void setShiftSsboBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftBindingForSet(TResourceType res, unsigned int base, unsigned int set); + void setResourceSetBinding(const std::vector& base); + void setAutoMapBindings(bool map); + void setAutoMapLocations(bool map); + void addUniformLocationOverride(const char* name, int loc); + void setUniformLocationBase(int base); + void setInvertY(bool invert); +#ifdef ENABLE_HLSL + void setHlslIoMapping(bool hlslIoMap); + void setFlattenUniformArrays(bool flatten); +#endif + void setNoStorageFormat(bool useUnknownFormat); + void setNanMinMaxClamp(bool nanMinMaxClamp); + void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode); + + // For setting up the environment (cleared to nothingness in the constructor). + // These must be called so that parsing is done for the right source language and + // target environment, either indirectly through TranslateEnvironment() based on + // EShMessages et. al., or directly by the user. + // + // setEnvInput: The input source language and stage. If generating code for a + // specific client, the input client semantics to use and the + // version of the that client's input semantics to use, otherwise + // use EShClientNone and version of 0, e.g. for validation mode. + // Note 'version' does not describe the target environment, + // just the version of the source dialect to compile under. + // + // See the definitions of TEnvironment, EShSource, EShLanguage, + // and EShClient for choices and more detail. + // + // setEnvClient: The client that will be hosting the execution, and it's version. + // Note 'version' is not the version of the languages involved, but + // the version of the client environment. + // Use EShClientNone and version of 0 if there is no client, e.g. + // for validation mode. + // + // See EShTargetClientVersion for choices. + // + // setEnvTarget: The language to translate to when generating code, and that + // language's version. + // Use EShTargetNone and version of 0 if there is no client, e.g. + // for validation mode. + // + void setEnvInput(EShSource lang, EShLanguage envStage, EShClient client, int version) + { + environment.input.languageFamily = lang; + environment.input.stage = envStage; + environment.input.dialect = client; + environment.input.dialectVersion = version; + } + void setEnvClient(EShClient client, EShTargetClientVersion version) + { + environment.client.client = client; + environment.client.version = version; + } + void setEnvTarget(EShTargetLanguage lang, EShTargetLanguageVersion version) + { + environment.target.language = lang; + environment.target.version = version; + } + + void getStrings(const char* const* &s, int& n) { s = strings; n = numStrings; } + +#ifdef ENABLE_HLSL + void setEnvTargetHlslFunctionality1() { environment.target.hlslFunctionality1 = true; } + bool getEnvTargetHlslFunctionality1() const { return environment.target.hlslFunctionality1; } +#else + bool getEnvTargetHlslFunctionality1() const { return false; } +#endif + + // Interface to #include handlers. + // + // To support #include, a client of Glslang does the following: + // 1. Call setStringsWithNames to set the source strings and associated + // names. For example, the names could be the names of the files + // containing the shader sources. + // 2. Call parse with an Includer. + // + // When the Glslang parser encounters an #include directive, it calls + // the Includer's include method with the requested include name + // together with the current string name. The returned IncludeResult + // contains the fully resolved name of the included source, together + // with the source text that should replace the #include directive + // in the source stream. After parsing that source, Glslang will + // release the IncludeResult object. + class Includer { + public: + // An IncludeResult contains the resolved name and content of a source + // inclusion. + struct IncludeResult { + IncludeResult(const std::string& headerName, const char* const headerData, const size_t headerLength, void* userData) : + headerName(headerName), headerData(headerData), headerLength(headerLength), userData(userData) { } + // For a successful inclusion, the fully resolved name of the requested + // include. For example, in a file system-based includer, full resolution + // should convert a relative path name into an absolute path name. + // For a failed inclusion, this is an empty string. + const std::string headerName; + // The content and byte length of the requested inclusion. The + // Includer producing this IncludeResult retains ownership of the + // storage. + // For a failed inclusion, the header + // field points to a string containing error details. + const char* const headerData; + const size_t headerLength; + // Include resolver's context. + void* userData; + protected: + IncludeResult& operator=(const IncludeResult&); + IncludeResult(); + }; + + // For both include methods below: + // + // Resolves an inclusion request by name, current source name, + // and include depth. + // On success, returns an IncludeResult containing the resolved name + // and content of the include. + // On failure, returns a nullptr, or an IncludeResult + // with an empty string for the headerName and error details in the + // header field. + // The Includer retains ownership of the contents + // of the returned IncludeResult value, and those contents must + // remain valid until the releaseInclude method is called on that + // IncludeResult object. + // + // Note "local" vs. "system" is not an "either/or": "local" is an + // extra thing to do over "system". Both might get called, as per + // the C++ specification. + + // For the "system" or <>-style includes; search the "system" paths. + virtual IncludeResult* includeSystem(const char* /*headerName*/, + const char* /*includerName*/, + size_t /*inclusionDepth*/) { return nullptr; } + + // For the "local"-only aspect of a "" include. Should not search in the + // "system" paths, because on returning a failure, the parser will + // call includeSystem() to look in the "system" locations. + virtual IncludeResult* includeLocal(const char* /*headerName*/, + const char* /*includerName*/, + size_t /*inclusionDepth*/) { return nullptr; } + + // Signals that the parser will no longer use the contents of the + // specified IncludeResult. + virtual void releaseInclude(IncludeResult*) = 0; + virtual ~Includer() {} + }; + + // Fail all Includer searches + class ForbidIncluder : public Includer { + public: + virtual void releaseInclude(IncludeResult*) override { } + }; + + bool parse(const TBuiltInResource*, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, + bool forwardCompatible, EShMessages, Includer&); + + bool parse(const TBuiltInResource* res, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, + bool forwardCompatible, EShMessages messages) + { + TShader::ForbidIncluder includer; + return parse(res, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, messages, includer); + } + + // Equivalent to parse() without a default profile and without forcing defaults. + bool parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages) + { + return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages); + } + + bool parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages, + Includer& includer) + { + return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages, includer); + } + + // NOTE: Doing just preprocessing to obtain a correct preprocessed shader string + // is not an officially supported or fully working path. + bool preprocess(const TBuiltInResource* builtInResources, + int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, + bool forwardCompatible, EShMessages message, std::string* outputString, + Includer& includer); + + const char* getInfoLog(); + const char* getInfoDebugLog(); + EShLanguage getStage() const { return stage; } + TIntermediate* getIntermediate() const { return intermediate; } + +protected: + TPoolAllocator* pool; + EShLanguage stage; + TCompiler* compiler; + TIntermediate* intermediate; + TInfoSink* infoSink; + // strings and lengths follow the standard for glShaderSource: + // strings is an array of numStrings pointers to string data. + // lengths can be null, but if not it is an array of numStrings + // integers containing the length of the associated strings. + // if lengths is null or lengths[n] < 0 the associated strings[n] is + // assumed to be null-terminated. + // stringNames is the optional names for all the strings. If stringNames + // is null, then none of the strings has name. If a certain element in + // stringNames is null, then the corresponding string does not have name. + const char* const* strings; // explicit code to compile, see previous comment + const int* lengths; + const char* const* stringNames; + int numStrings; // size of the above arrays + const char* preamble; // string of implicit code to compile before the explicitly provided code + + // a function in the source string can be renamed FROM this TO the name given in setEntryPoint. + std::string sourceEntryPointName; + + TEnvironment environment; + + friend class TProgram; + +private: + TShader& operator=(TShader&); +}; + +#ifndef GLSLANG_WEB + +// +// A reflection database and its interface, consistent with the OpenGL API reflection queries. +// + +// Data needed for just a single object at the granularity exchanged by the reflection API +class TObjectReflection { +public: + TObjectReflection(const std::string& pName, const TType& pType, int pOffset, int pGLDefineType, int pSize, int pIndex); + + const TType* getType() const { return type; } + int getBinding() const; + void dump() const; + static TObjectReflection badReflection() { return TObjectReflection(); } + + std::string name; + int offset; + int glDefineType; + int size; // data size in bytes for a block, array size for a (non-block) object that's an array + int index; + int counterIndex; + int numMembers; + int arrayStride; // stride of an array variable + int topLevelArrayStride; // stride of the top-level variable in a storage buffer member + EShLanguageMask stages; + +protected: + TObjectReflection() + : offset(-1), glDefineType(-1), size(-1), index(-1), counterIndex(-1), numMembers(-1), arrayStride(0), + topLevelArrayStride(0), stages(EShLanguageMask(0)), type(nullptr) + { + } + + const TType* type; +}; + +class TReflection; +class TIoMapper; +struct TVarEntryInfo; + +// Allows to customize the binding layout after linking. +// All used uniform variables will invoke at least validateBinding. +// If validateBinding returned true then the other resolveBinding, +// resolveSet, and resolveLocation are invoked to resolve the binding +// and descriptor set index respectively. +// +// Invocations happen in a particular order: +// 1) all shader inputs +// 2) all shader outputs +// 3) all uniforms with binding and set already defined +// 4) all uniforms with binding but no set defined +// 5) all uniforms with set but no binding defined +// 6) all uniforms with no binding and no set defined +// +// mapIO will use this resolver in two phases. The first +// phase is a notification phase, calling the corresponging +// notifiy callbacks, this phase ends with a call to endNotifications. +// Phase two starts directly after the call to endNotifications +// and calls all other callbacks to validate and to get the +// bindings, sets, locations, component and color indices. +// +// NOTE: that still limit checks are applied to bindings and sets +// and may result in an error. +class TIoMapResolver +{ +public: + virtual ~TIoMapResolver() {} + + // Should return true if the resulting/current binding would be okay. + // Basic idea is to do aliasing binding checks with this. + virtual bool validateBinding(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current binding should be overridden. + // Return -1 if the current binding (including no binding) should be kept. + virtual int resolveBinding(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current set should be overridden. + // Return -1 if the current set (including no set) should be kept. + virtual int resolveSet(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current location should be overridden. + // Return -1 if the current location (including no location) should be kept. + virtual int resolveUniformLocation(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return true if the resulting/current setup would be okay. + // Basic idea is to do aliasing checks and reject invalid semantic names. + virtual bool validateInOut(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current location should be overridden. + // Return -1 if the current location (including no location) should be kept. + virtual int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current component index should be overridden. + // Return -1 if the current component index (including no index) should be kept. + virtual int resolveInOutComponent(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current color index should be overridden. + // Return -1 if the current color index (including no index) should be kept. + virtual int resolveInOutIndex(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Notification of a uniform variable + virtual void notifyBinding(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Notification of a in or out variable + virtual void notifyInOut(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Called by mapIO when it starts its notify pass for the given stage + virtual void beginNotifications(EShLanguage stage) = 0; + // Called by mapIO when it has finished the notify pass + virtual void endNotifications(EShLanguage stage) = 0; + // Called by mipIO when it starts its resolve pass for the given stage + virtual void beginResolve(EShLanguage stage) = 0; + // Called by mapIO when it has finished the resolve pass + virtual void endResolve(EShLanguage stage) = 0; + // Called by mapIO when it starts its symbol collect for teh given stage + virtual void beginCollect(EShLanguage stage) = 0; + // Called by mapIO when it has finished the symbol collect + virtual void endCollect(EShLanguage stage) = 0; + // Called by TSlotCollector to resolve storage locations or bindings + virtual void reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) = 0; + // Called by TSlotCollector to resolve resource locations or bindings + virtual void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) = 0; + // Called by mapIO.addStage to set shader stage mask to mark a stage be added to this pipeline + virtual void addStage(EShLanguage stage) = 0; +}; + +#endif // GLSLANG_WEB + +// Make one TProgram per set of shaders that will get linked together. Add all +// the shaders that are to be linked together. After calling shader.parse() +// for all shaders, call link(). +// +// N.B.: Destruct a linked program *before* destructing the shaders linked into it. +// +class TProgram { +public: + TProgram(); + virtual ~TProgram(); + void addShader(TShader* shader) { stages[shader->stage].push_back(shader); } + std::list& getShaders(EShLanguage stage) { return stages[stage]; } + // Link Validation interface + bool link(EShMessages); + const char* getInfoLog(); + const char* getInfoDebugLog(); + + TIntermediate* getIntermediate(EShLanguage stage) const { return intermediate[stage]; } + +#ifndef GLSLANG_WEB + + // Reflection Interface + + // call first, to do liveness analysis, index mapping, etc.; returns false on failure + bool buildReflection(int opts = EShReflectionDefault); + unsigned getLocalSize(int dim) const; // return dim'th local size + int getReflectionIndex(const char *name) const; + int getReflectionPipeIOIndex(const char* name, const bool inOrOut) const; + int getNumUniformVariables() const; + const TObjectReflection& getUniform(int index) const; + int getNumUniformBlocks() const; + const TObjectReflection& getUniformBlock(int index) const; + int getNumPipeInputs() const; + const TObjectReflection& getPipeInput(int index) const; + int getNumPipeOutputs() const; + const TObjectReflection& getPipeOutput(int index) const; + int getNumBufferVariables() const; + const TObjectReflection& getBufferVariable(int index) const; + int getNumBufferBlocks() const; + const TObjectReflection& getBufferBlock(int index) const; + int getNumAtomicCounters() const; + const TObjectReflection& getAtomicCounter(int index) const; + + // Legacy Reflection Interface - expressed in terms of above interface + + // can be used for glGetProgramiv(GL_ACTIVE_UNIFORMS) + int getNumLiveUniformVariables() const { return getNumUniformVariables(); } + + // can be used for glGetProgramiv(GL_ACTIVE_UNIFORM_BLOCKS) + int getNumLiveUniformBlocks() const { return getNumUniformBlocks(); } + + // can be used for glGetProgramiv(GL_ACTIVE_ATTRIBUTES) + int getNumLiveAttributes() const { return getNumPipeInputs(); } + + // can be used for glGetUniformIndices() + int getUniformIndex(const char *name) const { return getReflectionIndex(name); } + + int getPipeIOIndex(const char *name, const bool inOrOut) const + { return getReflectionPipeIOIndex(name, inOrOut); } + + // can be used for "name" part of glGetActiveUniform() + const char *getUniformName(int index) const { return getUniform(index).name.c_str(); } + + // returns the binding number + int getUniformBinding(int index) const { return getUniform(index).getBinding(); } + + // returns Shaders Stages where a Uniform is present + EShLanguageMask getUniformStages(int index) const { return getUniform(index).stages; } + + // can be used for glGetActiveUniformsiv(GL_UNIFORM_BLOCK_INDEX) + int getUniformBlockIndex(int index) const { return getUniform(index).index; } + + // can be used for glGetActiveUniformsiv(GL_UNIFORM_TYPE) + int getUniformType(int index) const { return getUniform(index).glDefineType; } + + // can be used for glGetActiveUniformsiv(GL_UNIFORM_OFFSET) + int getUniformBufferOffset(int index) const { return getUniform(index).offset; } + + // can be used for glGetActiveUniformsiv(GL_UNIFORM_SIZE) + int getUniformArraySize(int index) const { return getUniform(index).size; } + + // returns a TType* + const TType *getUniformTType(int index) const { return getUniform(index).getType(); } + + // can be used for glGetActiveUniformBlockName() + const char *getUniformBlockName(int index) const { return getUniformBlock(index).name.c_str(); } + + // can be used for glGetActiveUniformBlockiv(UNIFORM_BLOCK_DATA_SIZE) + int getUniformBlockSize(int index) const { return getUniformBlock(index).size; } + + // returns the block binding number + int getUniformBlockBinding(int index) const { return getUniformBlock(index).getBinding(); } + + // returns block index of associated counter. + int getUniformBlockCounterIndex(int index) const { return getUniformBlock(index).counterIndex; } + + // returns a TType* + const TType *getUniformBlockTType(int index) const { return getUniformBlock(index).getType(); } + + // can be used for glGetActiveAttrib() + const char *getAttributeName(int index) const { return getPipeInput(index).name.c_str(); } + + // can be used for glGetActiveAttrib() + int getAttributeType(int index) const { return getPipeInput(index).glDefineType; } + + // returns a TType* + const TType *getAttributeTType(int index) const { return getPipeInput(index).getType(); } + + void dumpReflection(); + // I/O mapping: apply base offsets and map live unbound variables + // If resolver is not provided it uses the previous approach + // and respects auto assignment and offsets. + bool mapIO(TIoMapResolver* pResolver = nullptr, TIoMapper* pIoMapper = nullptr); +#endif + +protected: + bool linkStage(EShLanguage, EShMessages); + + TPoolAllocator* pool; + std::list stages[EShLangCount]; + TIntermediate* intermediate[EShLangCount]; + bool newedIntermediate[EShLangCount]; // track which intermediate were "new" versus reusing a singleton unit in a stage + TInfoSink* infoSink; +#ifndef GLSLANG_WEB + TReflection* reflection; +#endif + bool linked; + +private: + TProgram(TProgram&); + TProgram& operator=(TProgram&); +}; + +} // end namespace glslang + +#endif // _COMPILER_INTERFACE_INCLUDED_ diff --git a/android/armeabi-v7a/include/glslang/SPIRV/GLSL.ext.AMD.h b/android/armeabi-v7a/include/glslang/SPIRV/GLSL.ext.AMD.h new file mode 100644 index 00000000..009d2f1c --- /dev/null +++ b/android/armeabi-v7a/include/glslang/SPIRV/GLSL.ext.AMD.h @@ -0,0 +1,108 @@ +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextAMD_H +#define GLSLextAMD_H + +static const int GLSLextAMDVersion = 100; +static const int GLSLextAMDRevision = 7; + +// SPV_AMD_shader_ballot +static const char* const E_SPV_AMD_shader_ballot = "SPV_AMD_shader_ballot"; + +enum ShaderBallotAMD { + ShaderBallotBadAMD = 0, // Don't use + + SwizzleInvocationsAMD = 1, + SwizzleInvocationsMaskedAMD = 2, + WriteInvocationAMD = 3, + MbcntAMD = 4, + + ShaderBallotCountAMD +}; + +// SPV_AMD_shader_trinary_minmax +static const char* const E_SPV_AMD_shader_trinary_minmax = "SPV_AMD_shader_trinary_minmax"; + +enum ShaderTrinaryMinMaxAMD { + ShaderTrinaryMinMaxBadAMD = 0, // Don't use + + FMin3AMD = 1, + UMin3AMD = 2, + SMin3AMD = 3, + FMax3AMD = 4, + UMax3AMD = 5, + SMax3AMD = 6, + FMid3AMD = 7, + UMid3AMD = 8, + SMid3AMD = 9, + + ShaderTrinaryMinMaxCountAMD +}; + +// SPV_AMD_shader_explicit_vertex_parameter +static const char* const E_SPV_AMD_shader_explicit_vertex_parameter = "SPV_AMD_shader_explicit_vertex_parameter"; + +enum ShaderExplicitVertexParameterAMD { + ShaderExplicitVertexParameterBadAMD = 0, // Don't use + + InterpolateAtVertexAMD = 1, + + ShaderExplicitVertexParameterCountAMD +}; + +// SPV_AMD_gcn_shader +static const char* const E_SPV_AMD_gcn_shader = "SPV_AMD_gcn_shader"; + +enum GcnShaderAMD { + GcnShaderBadAMD = 0, // Don't use + + CubeFaceIndexAMD = 1, + CubeFaceCoordAMD = 2, + TimeAMD = 3, + + GcnShaderCountAMD +}; + +// SPV_AMD_gpu_shader_half_float +static const char* const E_SPV_AMD_gpu_shader_half_float = "SPV_AMD_gpu_shader_half_float"; + +// SPV_AMD_texture_gather_bias_lod +static const char* const E_SPV_AMD_texture_gather_bias_lod = "SPV_AMD_texture_gather_bias_lod"; + +// SPV_AMD_gpu_shader_int16 +static const char* const E_SPV_AMD_gpu_shader_int16 = "SPV_AMD_gpu_shader_int16"; + +// SPV_AMD_shader_image_load_store_lod +static const char* const E_SPV_AMD_shader_image_load_store_lod = "SPV_AMD_shader_image_load_store_lod"; + +// SPV_AMD_shader_fragment_mask +static const char* const E_SPV_AMD_shader_fragment_mask = "SPV_AMD_shader_fragment_mask"; + +// SPV_AMD_gpu_shader_half_float_fetch +static const char* const E_SPV_AMD_gpu_shader_half_float_fetch = "SPV_AMD_gpu_shader_half_float_fetch"; + +#endif // #ifndef GLSLextAMD_H diff --git a/android/armeabi-v7a/include/glslang/SPIRV/GLSL.ext.EXT.h b/android/armeabi-v7a/include/glslang/SPIRV/GLSL.ext.EXT.h new file mode 100644 index 00000000..40164b61 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/SPIRV/GLSL.ext.EXT.h @@ -0,0 +1,39 @@ +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextEXT_H +#define GLSLextEXT_H + +static const int GLSLextEXTVersion = 100; +static const int GLSLextEXTRevision = 2; + +static const char* const E_SPV_EXT_shader_stencil_export = "SPV_EXT_shader_stencil_export"; +static const char* const E_SPV_EXT_shader_viewport_index_layer = "SPV_EXT_shader_viewport_index_layer"; +static const char* const E_SPV_EXT_fragment_fully_covered = "SPV_EXT_fragment_fully_covered"; +static const char* const E_SPV_EXT_fragment_invocation_density = "SPV_EXT_fragment_invocation_density"; +static const char* const E_SPV_EXT_demote_to_helper_invocation = "SPV_EXT_demote_to_helper_invocation"; + +#endif // #ifndef GLSLextEXT_H diff --git a/android/armeabi-v7a/include/glslang/SPIRV/GLSL.ext.KHR.h b/android/armeabi-v7a/include/glslang/SPIRV/GLSL.ext.KHR.h new file mode 100644 index 00000000..d783a8f2 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/SPIRV/GLSL.ext.KHR.h @@ -0,0 +1,51 @@ +/* +** Copyright (c) 2014-2020 The Khronos Group Inc. +** Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextKHR_H +#define GLSLextKHR_H + +static const int GLSLextKHRVersion = 100; +static const int GLSLextKHRRevision = 2; + +static const char* const E_SPV_KHR_shader_ballot = "SPV_KHR_shader_ballot"; +static const char* const E_SPV_KHR_subgroup_vote = "SPV_KHR_subgroup_vote"; +static const char* const E_SPV_KHR_device_group = "SPV_KHR_device_group"; +static const char* const E_SPV_KHR_multiview = "SPV_KHR_multiview"; +static const char* const E_SPV_KHR_shader_draw_parameters = "SPV_KHR_shader_draw_parameters"; +static const char* const E_SPV_KHR_16bit_storage = "SPV_KHR_16bit_storage"; +static const char* const E_SPV_KHR_8bit_storage = "SPV_KHR_8bit_storage"; +static const char* const E_SPV_KHR_storage_buffer_storage_class = "SPV_KHR_storage_buffer_storage_class"; +static const char* const E_SPV_KHR_post_depth_coverage = "SPV_KHR_post_depth_coverage"; +static const char* const E_SPV_KHR_vulkan_memory_model = "SPV_KHR_vulkan_memory_model"; +static const char* const E_SPV_EXT_physical_storage_buffer = "SPV_EXT_physical_storage_buffer"; +static const char* const E_SPV_KHR_physical_storage_buffer = "SPV_KHR_physical_storage_buffer"; +static const char* const E_SPV_EXT_fragment_shader_interlock = "SPV_EXT_fragment_shader_interlock"; +static const char* const E_SPV_KHR_shader_clock = "SPV_KHR_shader_clock"; +static const char* const E_SPV_KHR_non_semantic_info = "SPV_KHR_non_semantic_info"; +static const char* const E_SPV_KHR_ray_tracing = "SPV_KHR_ray_tracing"; +static const char* const E_SPV_KHR_ray_query = "SPV_KHR_ray_query"; +#endif // #ifndef GLSLextKHR_H diff --git a/android/armeabi-v7a/include/glslang/SPIRV/GLSL.ext.NV.h b/android/armeabi-v7a/include/glslang/SPIRV/GLSL.ext.NV.h new file mode 100644 index 00000000..50146da1 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/SPIRV/GLSL.ext.NV.h @@ -0,0 +1,81 @@ +/* +** Copyright (c) 2014-2017 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextNV_H +#define GLSLextNV_H + +enum BuiltIn; +enum Decoration; +enum Op; +enum Capability; + +static const int GLSLextNVVersion = 100; +static const int GLSLextNVRevision = 11; + +//SPV_NV_sample_mask_override_coverage +const char* const E_SPV_NV_sample_mask_override_coverage = "SPV_NV_sample_mask_override_coverage"; + +//SPV_NV_geometry_shader_passthrough +const char* const E_SPV_NV_geometry_shader_passthrough = "SPV_NV_geometry_shader_passthrough"; + +//SPV_NV_viewport_array2 +const char* const E_SPV_NV_viewport_array2 = "SPV_NV_viewport_array2"; +const char* const E_ARB_shader_viewport_layer_array = "SPV_ARB_shader_viewport_layer_array"; + +//SPV_NV_stereo_view_rendering +const char* const E_SPV_NV_stereo_view_rendering = "SPV_NV_stereo_view_rendering"; + +//SPV_NVX_multiview_per_view_attributes +const char* const E_SPV_NVX_multiview_per_view_attributes = "SPV_NVX_multiview_per_view_attributes"; + +//SPV_NV_shader_subgroup_partitioned +const char* const E_SPV_NV_shader_subgroup_partitioned = "SPV_NV_shader_subgroup_partitioned"; + +//SPV_NV_fragment_shader_barycentric +const char* const E_SPV_NV_fragment_shader_barycentric = "SPV_NV_fragment_shader_barycentric"; + +//SPV_NV_compute_shader_derivatives +const char* const E_SPV_NV_compute_shader_derivatives = "SPV_NV_compute_shader_derivatives"; + +//SPV_NV_shader_image_footprint +const char* const E_SPV_NV_shader_image_footprint = "SPV_NV_shader_image_footprint"; + +//SPV_NV_mesh_shader +const char* const E_SPV_NV_mesh_shader = "SPV_NV_mesh_shader"; + +//SPV_NV_raytracing +const char* const E_SPV_NV_ray_tracing = "SPV_NV_ray_tracing"; + +//SPV_NV_shading_rate +const char* const E_SPV_NV_shading_rate = "SPV_NV_shading_rate"; + +//SPV_NV_cooperative_matrix +const char* const E_SPV_NV_cooperative_matrix = "SPV_NV_cooperative_matrix"; + +//SPV_NV_shader_sm_builtins +const char* const E_SPV_NV_shader_sm_builtins = "SPV_NV_shader_sm_builtins"; + +#endif // #ifndef GLSLextNV_H diff --git a/android/armeabi-v7a/include/glslang/SPIRV/GLSL.std.450.h b/android/armeabi-v7a/include/glslang/SPIRV/GLSL.std.450.h new file mode 100644 index 00000000..df31092b --- /dev/null +++ b/android/armeabi-v7a/include/glslang/SPIRV/GLSL.std.450.h @@ -0,0 +1,131 @@ +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLstd450_H +#define GLSLstd450_H + +static const int GLSLstd450Version = 100; +static const int GLSLstd450Revision = 1; + +enum GLSLstd450 { + GLSLstd450Bad = 0, // Don't use + + GLSLstd450Round = 1, + GLSLstd450RoundEven = 2, + GLSLstd450Trunc = 3, + GLSLstd450FAbs = 4, + GLSLstd450SAbs = 5, + GLSLstd450FSign = 6, + GLSLstd450SSign = 7, + GLSLstd450Floor = 8, + GLSLstd450Ceil = 9, + GLSLstd450Fract = 10, + + GLSLstd450Radians = 11, + GLSLstd450Degrees = 12, + GLSLstd450Sin = 13, + GLSLstd450Cos = 14, + GLSLstd450Tan = 15, + GLSLstd450Asin = 16, + GLSLstd450Acos = 17, + GLSLstd450Atan = 18, + GLSLstd450Sinh = 19, + GLSLstd450Cosh = 20, + GLSLstd450Tanh = 21, + GLSLstd450Asinh = 22, + GLSLstd450Acosh = 23, + GLSLstd450Atanh = 24, + GLSLstd450Atan2 = 25, + + GLSLstd450Pow = 26, + GLSLstd450Exp = 27, + GLSLstd450Log = 28, + GLSLstd450Exp2 = 29, + GLSLstd450Log2 = 30, + GLSLstd450Sqrt = 31, + GLSLstd450InverseSqrt = 32, + + GLSLstd450Determinant = 33, + GLSLstd450MatrixInverse = 34, + + GLSLstd450Modf = 35, // second operand needs an OpVariable to write to + GLSLstd450ModfStruct = 36, // no OpVariable operand + GLSLstd450FMin = 37, + GLSLstd450UMin = 38, + GLSLstd450SMin = 39, + GLSLstd450FMax = 40, + GLSLstd450UMax = 41, + GLSLstd450SMax = 42, + GLSLstd450FClamp = 43, + GLSLstd450UClamp = 44, + GLSLstd450SClamp = 45, + GLSLstd450FMix = 46, + GLSLstd450IMix = 47, // Reserved + GLSLstd450Step = 48, + GLSLstd450SmoothStep = 49, + + GLSLstd450Fma = 50, + GLSLstd450Frexp = 51, // second operand needs an OpVariable to write to + GLSLstd450FrexpStruct = 52, // no OpVariable operand + GLSLstd450Ldexp = 53, + + GLSLstd450PackSnorm4x8 = 54, + GLSLstd450PackUnorm4x8 = 55, + GLSLstd450PackSnorm2x16 = 56, + GLSLstd450PackUnorm2x16 = 57, + GLSLstd450PackHalf2x16 = 58, + GLSLstd450PackDouble2x32 = 59, + GLSLstd450UnpackSnorm2x16 = 60, + GLSLstd450UnpackUnorm2x16 = 61, + GLSLstd450UnpackHalf2x16 = 62, + GLSLstd450UnpackSnorm4x8 = 63, + GLSLstd450UnpackUnorm4x8 = 64, + GLSLstd450UnpackDouble2x32 = 65, + + GLSLstd450Length = 66, + GLSLstd450Distance = 67, + GLSLstd450Cross = 68, + GLSLstd450Normalize = 69, + GLSLstd450FaceForward = 70, + GLSLstd450Reflect = 71, + GLSLstd450Refract = 72, + + GLSLstd450FindILsb = 73, + GLSLstd450FindSMsb = 74, + GLSLstd450FindUMsb = 75, + + GLSLstd450InterpolateAtCentroid = 76, + GLSLstd450InterpolateAtSample = 77, + GLSLstd450InterpolateAtOffset = 78, + + GLSLstd450NMin = 79, + GLSLstd450NMax = 80, + GLSLstd450NClamp = 81, + + GLSLstd450Count +}; + +#endif // #ifndef GLSLstd450_H diff --git a/android/armeabi-v7a/include/glslang/SPIRV/GlslangToSpv.h b/android/armeabi-v7a/include/glslang/SPIRV/GlslangToSpv.h new file mode 100644 index 00000000..3907be43 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/SPIRV/GlslangToSpv.h @@ -0,0 +1,61 @@ +// +// Copyright (C) 2014 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#pragma once + +#if defined(_MSC_VER) && _MSC_VER >= 1900 + #pragma warning(disable : 4464) // relative include path contains '..' +#endif + +#include "SpvTools.h" +#include "glslang/Include/intermediate.h" + +#include +#include + +#include "Logger.h" + +namespace glslang { + +void GetSpirvVersion(std::string&); +int GetSpirvGeneratorVersion(); +void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, + SpvOptions* options = nullptr); +void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger* logger, SpvOptions* options = nullptr); +void OutputSpvBin(const std::vector& spirv, const char* baseName); +void OutputSpvHex(const std::vector& spirv, const char* baseName, const char* varName); + +} diff --git a/android/armeabi-v7a/include/glslang/SPIRV/Logger.h b/android/armeabi-v7a/include/glslang/SPIRV/Logger.h new file mode 100644 index 00000000..411367c0 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/SPIRV/Logger.h @@ -0,0 +1,83 @@ +// +// Copyright (C) 2016 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef GLSLANG_SPIRV_LOGGER_H +#define GLSLANG_SPIRV_LOGGER_H + +#include +#include + +namespace spv { + +// A class for holding all SPIR-V build status messages, including +// missing/TBD functionalities, warnings, and errors. +class SpvBuildLogger { +public: + SpvBuildLogger() {} + +#ifdef GLSLANG_WEB + void tbdFunctionality(const std::string& f) { } + void missingFunctionality(const std::string& f) { } + void warning(const std::string& w) { } + void error(const std::string& e) { errors.push_back(e); } + std::string getAllMessages() { return ""; } +#else + + // Registers a TBD functionality. + void tbdFunctionality(const std::string& f); + // Registers a missing functionality. + void missingFunctionality(const std::string& f); + + // Logs a warning. + void warning(const std::string& w) { warnings.push_back(w); } + // Logs an error. + void error(const std::string& e) { errors.push_back(e); } + + // Returns all messages accumulated in the order of: + // TBD functionalities, missing functionalities, warnings, errors. + std::string getAllMessages() const; +#endif + +private: + SpvBuildLogger(const SpvBuildLogger&); + + std::vector tbdFeatures; + std::vector missingFeatures; + std::vector warnings; + std::vector errors; +}; + +} // end spv namespace + +#endif // GLSLANG_SPIRV_LOGGER_H diff --git a/android/armeabi-v7a/include/glslang/SPIRV/NonSemanticDebugPrintf.h b/android/armeabi-v7a/include/glslang/SPIRV/NonSemanticDebugPrintf.h new file mode 100644 index 00000000..83796d75 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/SPIRV/NonSemanticDebugPrintf.h @@ -0,0 +1,50 @@ +// Copyright (c) 2020 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and/or associated documentation files (the +// "Materials"), to deal in the Materials without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Materials, and to +// permit persons to whom the Materials are furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS +// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS +// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT +// https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +// + +#ifndef SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ +#define SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + NonSemanticDebugPrintfRevision = 1, + NonSemanticDebugPrintfRevision_BitWidthPadding = 0x7fffffff +}; + +enum NonSemanticDebugPrintfInstructions { + NonSemanticDebugPrintfDebugPrintf = 1, + NonSemanticDebugPrintfInstructionsMax = 0x7fffffff +}; + + +#ifdef __cplusplus +} +#endif + +#endif // SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ diff --git a/android/armeabi-v7a/include/glslang/SPIRV/SPVRemapper.h b/android/armeabi-v7a/include/glslang/SPIRV/SPVRemapper.h new file mode 100644 index 00000000..d6b9c346 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/SPIRV/SPVRemapper.h @@ -0,0 +1,304 @@ +// +// Copyright (C) 2015 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef SPIRVREMAPPER_H +#define SPIRVREMAPPER_H + +#include +#include +#include +#include + +namespace spv { + +// MSVC defines __cplusplus as an older value, even when it supports almost all of 11. +// We handle that here by making our own symbol. +#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1700) +# define use_cpp11 1 +#endif + +class spirvbin_base_t +{ +public: + enum Options { + NONE = 0, + STRIP = (1<<0), + MAP_TYPES = (1<<1), + MAP_NAMES = (1<<2), + MAP_FUNCS = (1<<3), + DCE_FUNCS = (1<<4), + DCE_VARS = (1<<5), + DCE_TYPES = (1<<6), + OPT_LOADSTORE = (1<<7), + OPT_FWD_LS = (1<<8), // EXPERIMENTAL: PRODUCES INVALID SCHEMA-0 SPIRV + MAP_ALL = (MAP_TYPES | MAP_NAMES | MAP_FUNCS), + DCE_ALL = (DCE_FUNCS | DCE_VARS | DCE_TYPES), + OPT_ALL = (OPT_LOADSTORE), + + ALL_BUT_STRIP = (MAP_ALL | DCE_ALL | OPT_ALL), + DO_EVERYTHING = (STRIP | ALL_BUT_STRIP) + }; +}; + +} // namespace SPV + +#if !defined (use_cpp11) +#include +#include + +namespace spv { +class spirvbin_t : public spirvbin_base_t +{ +public: + spirvbin_t(int /*verbose = 0*/) { } + + void remap(std::vector& /*spv*/, unsigned int /*opts = 0*/) + { + printf("Tool not compiled for C++11, which is required for SPIR-V remapping.\n"); + exit(5); + } +}; + +} // namespace SPV + +#else // defined (use_cpp11) + +#include +#include +#include +#include +#include +#include +#include + +#include "spirv.hpp" +#include "spvIR.h" + +namespace spv { + +// class to hold SPIR-V binary data for remapping, DCE, and debug stripping +class spirvbin_t : public spirvbin_base_t +{ +public: + spirvbin_t(int verbose = 0) : entryPoint(spv::NoResult), largestNewId(0), verbose(verbose), errorLatch(false) + { } + + virtual ~spirvbin_t() { } + + // remap on an existing binary in memory + void remap(std::vector& spv, std::uint32_t opts = DO_EVERYTHING); + + // Type for error/log handler functions + typedef std::function errorfn_t; + typedef std::function logfn_t; + + // Register error/log handling functions (can be lambda fn / functor / etc) + static void registerErrorHandler(errorfn_t handler) { errorHandler = handler; } + static void registerLogHandler(logfn_t handler) { logHandler = handler; } + +protected: + // This can be overridden to provide other message behavior if needed + virtual void msg(int minVerbosity, int indent, const std::string& txt) const; + +private: + // Local to global, or global to local ID map + typedef std::unordered_map idmap_t; + typedef std::unordered_set idset_t; + typedef std::unordered_map blockmap_t; + + void remap(std::uint32_t opts = DO_EVERYTHING); + + // Map of names to IDs + typedef std::unordered_map namemap_t; + + typedef std::uint32_t spirword_t; + + typedef std::pair range_t; + typedef std::function idfn_t; + typedef std::function instfn_t; + + // Special Values for ID map: + static const spv::Id unmapped; // unchanged from default value + static const spv::Id unused; // unused ID + static const int header_size; // SPIR header = 5 words + + class id_iterator_t; + + // For mapping type entries between different shaders + typedef std::vector typeentry_t; + typedef std::map globaltypes_t; + + // A set that preserves position order, and a reverse map + typedef std::set posmap_t; + typedef std::unordered_map posmap_rev_t; + + // Maps and ID to the size of its base type, if known. + typedef std::unordered_map typesize_map_t; + + // handle error + void error(const std::string& txt) const { errorLatch = true; errorHandler(txt); } + + bool isConstOp(spv::Op opCode) const; + bool isTypeOp(spv::Op opCode) const; + bool isStripOp(spv::Op opCode) const; + bool isFlowCtrl(spv::Op opCode) const; + range_t literalRange(spv::Op opCode) const; + range_t typeRange(spv::Op opCode) const; + range_t constRange(spv::Op opCode) const; + unsigned typeSizeInWords(spv::Id id) const; + unsigned idTypeSizeInWords(spv::Id id) const; + + spv::Id& asId(unsigned word) { return spv[word]; } + const spv::Id& asId(unsigned word) const { return spv[word]; } + spv::Op asOpCode(unsigned word) const { return opOpCode(spv[word]); } + std::uint32_t asOpCodeHash(unsigned word); + spv::Decoration asDecoration(unsigned word) const { return spv::Decoration(spv[word]); } + unsigned asWordCount(unsigned word) const { return opWordCount(spv[word]); } + spv::Id asTypeConstId(unsigned word) const { return asId(word + (isTypeOp(asOpCode(word)) ? 1 : 2)); } + unsigned idPos(spv::Id id) const; + + static unsigned opWordCount(spirword_t data) { return data >> spv::WordCountShift; } + static spv::Op opOpCode(spirword_t data) { return spv::Op(data & spv::OpCodeMask); } + + // Header access & set methods + spirword_t magic() const { return spv[0]; } // return magic number + spirword_t bound() const { return spv[3]; } // return Id bound from header + spirword_t bound(spirword_t b) { return spv[3] = b; } + spirword_t genmagic() const { return spv[2]; } // generator magic + spirword_t genmagic(spirword_t m) { return spv[2] = m; } + spirword_t schemaNum() const { return spv[4]; } // schema number from header + + // Mapping fns: get + spv::Id localId(spv::Id id) const { return idMapL[id]; } + + // Mapping fns: set + inline spv::Id localId(spv::Id id, spv::Id newId); + void countIds(spv::Id id); + + // Return next unused new local ID. + // NOTE: boost::dynamic_bitset would be more efficient due to find_next(), + // which std::vector doens't have. + inline spv::Id nextUnusedId(spv::Id id); + + void buildLocalMaps(); + std::string literalString(unsigned word) const; // Return literal as a std::string + int literalStringWords(const std::string& str) const { return (int(str.size())+4)/4; } + + bool isNewIdMapped(spv::Id newId) const { return isMapped(newId); } + bool isOldIdUnmapped(spv::Id oldId) const { return localId(oldId) == unmapped; } + bool isOldIdUnused(spv::Id oldId) const { return localId(oldId) == unused; } + bool isOldIdMapped(spv::Id oldId) const { return !isOldIdUnused(oldId) && !isOldIdUnmapped(oldId); } + bool isFunction(spv::Id oldId) const { return fnPos.find(oldId) != fnPos.end(); } + + // bool matchType(const globaltypes_t& globalTypes, spv::Id lt, spv::Id gt) const; + // spv::Id findType(const globaltypes_t& globalTypes, spv::Id lt) const; + std::uint32_t hashType(unsigned typeStart) const; + + spirvbin_t& process(instfn_t, idfn_t, unsigned begin = 0, unsigned end = 0); + int processInstruction(unsigned word, instfn_t, idfn_t); + + void validate() const; + void mapTypeConst(); + void mapFnBodies(); + void optLoadStore(); + void dceFuncs(); + void dceVars(); + void dceTypes(); + void mapNames(); + void foldIds(); // fold IDs to smallest space + void forwardLoadStores(); // load store forwarding (EXPERIMENTAL) + void offsetIds(); // create relative offset IDs + + void applyMap(); // remap per local name map + void mapRemainder(); // map any IDs we haven't touched yet + void stripDebug(); // strip all debug info + void stripDeadRefs(); // strips debug info for now-dead references after DCE + void strip(); // remove debug symbols + + std::vector spv; // SPIR words + + namemap_t nameMap; // ID names from OpName + + // Since we want to also do binary ops, we can't use std::vector. we could use + // boost::dynamic_bitset, but we're trying to avoid a boost dependency. + typedef std::uint64_t bits_t; + std::vector mapped; // which new IDs have been mapped + static const int mBits = sizeof(bits_t) * 4; + + bool isMapped(spv::Id id) const { return id < maxMappedId() && ((mapped[id/mBits] & (1LL<<(id%mBits))) != 0); } + void setMapped(spv::Id id) { resizeMapped(id); mapped[id/mBits] |= (1LL<<(id%mBits)); } + void resizeMapped(spv::Id id) { if (id >= maxMappedId()) mapped.resize(id/mBits+1, 0); } + size_t maxMappedId() const { return mapped.size() * mBits; } + + // Add a strip range for a given instruction starting at 'start' + // Note: avoiding brace initializers to please older versions os MSVC. + void stripInst(unsigned start) { stripRange.push_back(range_t(start, start + asWordCount(start))); } + + // Function start and end. use unordered_map because we'll have + // many fewer functions than IDs. + std::unordered_map fnPos; + + // Which functions are called, anywhere in the module, with a call count + std::unordered_map fnCalls; + + posmap_t typeConstPos; // word positions that define types & consts (ordered) + posmap_rev_t idPosR; // reverse map from IDs to positions + typesize_map_t idTypeSizeMap; // maps each ID to its type size, if known. + + std::vector idMapL; // ID {M}ap from {L}ocal to {G}lobal IDs + + spv::Id entryPoint; // module entry point + spv::Id largestNewId; // biggest new ID we have mapped anything to + + // Sections of the binary to strip, given as [begin,end) + std::vector stripRange; + + // processing options: + std::uint32_t options; + int verbose; // verbosity level + + // Error latch: this is set if the error handler is ever executed. It would be better to + // use a try/catch block and throw, but that's not desired for certain environments, so + // this is the alternative. + mutable bool errorLatch; + + static errorfn_t errorHandler; + static logfn_t logHandler; +}; + +} // namespace SPV + +#endif // defined (use_cpp11) +#endif // SPIRVREMAPPER_H diff --git a/android/armeabi-v7a/include/glslang/SPIRV/SpvBuilder.h b/android/armeabi-v7a/include/glslang/SPIRV/SpvBuilder.h new file mode 100644 index 00000000..71b90d60 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/SPIRV/SpvBuilder.h @@ -0,0 +1,838 @@ +// +// Copyright (C) 2014-2015 LunarG, Inc. +// Copyright (C) 2015-2020 Google, Inc. +// Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// "Builder" is an interface to fully build SPIR-V IR. Allocate one of +// these to build (a thread safe) internal SPIR-V representation (IR), +// and then dump it as a binary stream according to the SPIR-V specification. +// +// A Builder has a 1:1 relationship with a SPIR-V module. +// + +#pragma once +#ifndef SpvBuilder_H +#define SpvBuilder_H + +#include "Logger.h" +#include "spirv.hpp" +#include "spvIR.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace spv { + +typedef enum { + Spv_1_0 = (1 << 16), + Spv_1_1 = (1 << 16) | (1 << 8), + Spv_1_2 = (1 << 16) | (2 << 8), + Spv_1_3 = (1 << 16) | (3 << 8), + Spv_1_4 = (1 << 16) | (4 << 8), + Spv_1_5 = (1 << 16) | (5 << 8), +} SpvVersion; + +class Builder { +public: + Builder(unsigned int spvVersion, unsigned int userNumber, SpvBuildLogger* logger); + virtual ~Builder(); + + static const int maxMatrixSize = 4; + + unsigned int getSpvVersion() const { return spvVersion; } + + void setSource(spv::SourceLanguage lang, int version) + { + source = lang; + sourceVersion = version; + } + spv::Id getStringId(const std::string& str) + { + auto sItr = stringIds.find(str); + if (sItr != stringIds.end()) + return sItr->second; + spv::Id strId = getUniqueId(); + Instruction* fileString = new Instruction(strId, NoType, OpString); + const char* file_c_str = str.c_str(); + fileString->addStringOperand(file_c_str); + strings.push_back(std::unique_ptr(fileString)); + module.mapInstruction(fileString); + stringIds[file_c_str] = strId; + return strId; + } + void setSourceFile(const std::string& file) + { + sourceFileStringId = getStringId(file); + } + void setSourceText(const std::string& text) { sourceText = text; } + void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); } + void addModuleProcessed(const std::string& p) { moduleProcesses.push_back(p.c_str()); } + void setEmitOpLines() { emitOpLines = true; } + void addExtension(const char* ext) { extensions.insert(ext); } + void removeExtension(const char* ext) + { + extensions.erase(ext); + } + void addIncorporatedExtension(const char* ext, SpvVersion incorporatedVersion) + { + if (getSpvVersion() < static_cast(incorporatedVersion)) + addExtension(ext); + } + void promoteIncorporatedExtension(const char* baseExt, const char* promoExt, SpvVersion incorporatedVersion) + { + removeExtension(baseExt); + addIncorporatedExtension(promoExt, incorporatedVersion); + } + void addInclude(const std::string& name, const std::string& text) + { + spv::Id incId = getStringId(name); + includeFiles[incId] = &text; + } + Id import(const char*); + void setMemoryModel(spv::AddressingModel addr, spv::MemoryModel mem) + { + addressModel = addr; + memoryModel = mem; + } + + void addCapability(spv::Capability cap) { capabilities.insert(cap); } + + // To get a new for anything needing a new one. + Id getUniqueId() { return ++uniqueId; } + + // To get a set of new s, e.g., for a set of function parameters + Id getUniqueIds(int numIds) + { + Id id = uniqueId + 1; + uniqueId += numIds; + return id; + } + + // Generate OpLine for non-filename-based #line directives (ie no filename + // seen yet): Log the current line, and if different than the last one, + // issue a new OpLine using the new line and current source file name. + void setLine(int line); + + // If filename null, generate OpLine for non-filename-based line directives, + // else do filename-based: Log the current line and file, and if different + // than the last one, issue a new OpLine using the new line and file + // name. + void setLine(int line, const char* filename); + // Low-level OpLine. See setLine() for a layered helper. + void addLine(Id fileName, int line, int column); + + // For creating new types (will return old type if the requested one was already made). + Id makeVoidType(); + Id makeBoolType(); + Id makePointer(StorageClass, Id pointee); + Id makeForwardPointer(StorageClass); + Id makePointerFromForwardPointer(StorageClass, Id forwardPointerType, Id pointee); + Id makeIntegerType(int width, bool hasSign); // generic + Id makeIntType(int width) { return makeIntegerType(width, true); } + Id makeUintType(int width) { return makeIntegerType(width, false); } + Id makeFloatType(int width); + Id makeStructType(const std::vector& members, const char*); + Id makeStructResultType(Id type0, Id type1); + Id makeVectorType(Id component, int size); + Id makeMatrixType(Id component, int cols, int rows); + Id makeArrayType(Id element, Id sizeId, int stride); // 0 stride means no stride decoration + Id makeRuntimeArray(Id element); + Id makeFunctionType(Id returnType, const std::vector& paramTypes); + Id makeImageType(Id sampledType, Dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format); + Id makeSamplerType(); + Id makeSampledImageType(Id imageType); + Id makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols); + + // accelerationStructureNV type + Id makeAccelerationStructureType(); + // rayQueryEXT type + Id makeRayQueryType(); + + // For querying about types. + Id getTypeId(Id resultId) const { return module.getTypeId(resultId); } + Id getDerefTypeId(Id resultId) const; + Op getOpCode(Id id) const { return module.getInstruction(id)->getOpCode(); } + Op getTypeClass(Id typeId) const { return getOpCode(typeId); } + Op getMostBasicTypeClass(Id typeId) const; + int getNumComponents(Id resultId) const { return getNumTypeComponents(getTypeId(resultId)); } + int getNumTypeConstituents(Id typeId) const; + int getNumTypeComponents(Id typeId) const { return getNumTypeConstituents(typeId); } + Id getScalarTypeId(Id typeId) const; + Id getContainedTypeId(Id typeId) const; + Id getContainedTypeId(Id typeId, int) const; + StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); } + ImageFormat getImageTypeFormat(Id typeId) const + { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); } + + bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); } + bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); } + bool isVector(Id resultId) const { return isVectorType(getTypeId(resultId)); } + bool isMatrix(Id resultId) const { return isMatrixType(getTypeId(resultId)); } + bool isCooperativeMatrix(Id resultId)const { return isCooperativeMatrixType(getTypeId(resultId)); } + bool isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); } + bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); } + + bool isBoolType(Id typeId) + { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); } + bool isIntType(Id typeId) const + { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; } + bool isUintType(Id typeId) const + { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; } + bool isFloatType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat; } + bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; } + bool isScalarType(Id typeId) const + { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt || + getTypeClass(typeId) == OpTypeBool; } + bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; } + bool isMatrixType(Id typeId) const { return getTypeClass(typeId) == OpTypeMatrix; } + bool isStructType(Id typeId) const { return getTypeClass(typeId) == OpTypeStruct; } + bool isArrayType(Id typeId) const { return getTypeClass(typeId) == OpTypeArray; } +#ifdef GLSLANG_WEB + bool isCooperativeMatrixType(Id typeId)const { return false; } +#else + bool isCooperativeMatrixType(Id typeId)const { return getTypeClass(typeId) == OpTypeCooperativeMatrixNV; } +#endif + bool isAggregateType(Id typeId) const + { return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); } + bool isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; } + bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; } + bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; } + bool containsType(Id typeId, Op typeOp, unsigned int width) const; + bool containsPhysicalStorageBufferOrArray(Id typeId) const; + + bool isConstantOpCode(Op opcode) const; + bool isSpecConstantOpCode(Op opcode) const; + bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); } + bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; } + bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); } + unsigned int getConstantScalar(Id resultId) const + { return module.getInstruction(resultId)->getImmediateOperand(0); } + StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); } + + int getScalarTypeWidth(Id typeId) const + { + Id scalarTypeId = getScalarTypeId(typeId); + assert(getTypeClass(scalarTypeId) == OpTypeInt || getTypeClass(scalarTypeId) == OpTypeFloat); + return module.getInstruction(scalarTypeId)->getImmediateOperand(0); + } + + int getTypeNumColumns(Id typeId) const + { + assert(isMatrixType(typeId)); + return getNumTypeConstituents(typeId); + } + int getNumColumns(Id resultId) const { return getTypeNumColumns(getTypeId(resultId)); } + int getTypeNumRows(Id typeId) const + { + assert(isMatrixType(typeId)); + return getNumTypeComponents(getContainedTypeId(typeId)); + } + int getNumRows(Id resultId) const { return getTypeNumRows(getTypeId(resultId)); } + + Dim getTypeDimensionality(Id typeId) const + { + assert(isImageType(typeId)); + return (Dim)module.getInstruction(typeId)->getImmediateOperand(1); + } + Id getImageType(Id resultId) const + { + Id typeId = getTypeId(resultId); + assert(isImageType(typeId) || isSampledImageType(typeId)); + return isSampledImageType(typeId) ? module.getInstruction(typeId)->getIdOperand(0) : typeId; + } + bool isArrayedImageType(Id typeId) const + { + assert(isImageType(typeId)); + return module.getInstruction(typeId)->getImmediateOperand(3) != 0; + } + + // For making new constants (will return old constant if the requested one was already made). + Id makeBoolConstant(bool b, bool specConstant = false); + Id makeInt8Constant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); } + Id makeUint8Constant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(8), u, specConstant); } + Id makeInt16Constant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(16), (unsigned)i, specConstant); } + Id makeUint16Constant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(16), u, specConstant); } + Id makeIntConstant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); } + Id makeUintConstant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(32), u, specConstant); } + Id makeInt64Constant(long long i, bool specConstant = false) + { return makeInt64Constant(makeIntType(64), (unsigned long long)i, specConstant); } + Id makeUint64Constant(unsigned long long u, bool specConstant = false) + { return makeInt64Constant(makeUintType(64), u, specConstant); } + Id makeFloatConstant(float f, bool specConstant = false); + Id makeDoubleConstant(double d, bool specConstant = false); + Id makeFloat16Constant(float f16, bool specConstant = false); + Id makeFpConstant(Id type, double d, bool specConstant = false); + + // Turn the array of constants into a proper spv constant of the requested type. + Id makeCompositeConstant(Id type, const std::vector& comps, bool specConst = false); + + // Methods for adding information outside the CFG. + Instruction* addEntryPoint(ExecutionModel, Function*, const char* name); + void addExecutionMode(Function*, ExecutionMode mode, int value1 = -1, int value2 = -1, int value3 = -1); + void addName(Id, const char* name); + void addMemberName(Id, int member, const char* name); + void addDecoration(Id, Decoration, int num = -1); + void addDecoration(Id, Decoration, const char*); + void addDecorationId(Id id, Decoration, Id idDecoration); + void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1); + void addMemberDecoration(Id, unsigned int member, Decoration, const char*); + + // At the end of what block do the next create*() instructions go? + void setBuildPoint(Block* bp) { buildPoint = bp; } + Block* getBuildPoint() const { return buildPoint; } + + // Make the entry-point function. The returned pointer is only valid + // for the lifetime of this builder. + Function* makeEntryPoint(const char*); + + // Make a shader-style function, and create its entry block if entry is non-zero. + // Return the function, pass back the entry. + // The returned pointer is only valid for the lifetime of this builder. + Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, + const std::vector& paramTypes, const std::vector>& precisions, Block **entry = 0); + + // Create a return. An 'implicit' return is one not appearing in the source + // code. In the case of an implicit return, no post-return block is inserted. + void makeReturn(bool implicit, Id retVal = 0); + + // Generate all the code needed to finish up a function. + void leaveFunction(); + + // Create a discard. + void makeDiscard(); + + // Create a global or function local or IO variable. + Id createVariable(StorageClass, Id type, const char* name = 0, Id initializer = NoResult); + + // Create an intermediate with an undefined value. + Id createUndefined(Id type); + + // Store into an Id and return the l-value + void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + + // Load from an Id and return it + Id createLoad(Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + + // Create an OpAccessChain instruction + Id createAccessChain(StorageClass, Id base, const std::vector& offsets); + + // Create an OpArrayLength instruction + Id createArrayLength(Id base, unsigned int member); + + // Create an OpCooperativeMatrixLengthNV instruction + Id createCooperativeMatrixLength(Id type); + + // Create an OpCompositeExtract instruction + Id createCompositeExtract(Id composite, Id typeId, unsigned index); + Id createCompositeExtract(Id composite, Id typeId, const std::vector& indexes); + Id createCompositeInsert(Id object, Id composite, Id typeId, unsigned index); + Id createCompositeInsert(Id object, Id composite, Id typeId, const std::vector& indexes); + + Id createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex); + Id createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex); + + void createNoResultOp(Op); + void createNoResultOp(Op, Id operand); + void createNoResultOp(Op, const std::vector& operands); + void createNoResultOp(Op, const std::vector& operands); + void createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask); + void createMemoryBarrier(unsigned executionScope, unsigned memorySemantics); + Id createUnaryOp(Op, Id typeId, Id operand); + Id createBinOp(Op, Id typeId, Id operand1, Id operand2); + Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3); + Id createOp(Op, Id typeId, const std::vector& operands); + Id createOp(Op, Id typeId, const std::vector& operands); + Id createFunctionCall(spv::Function*, const std::vector&); + Id createSpecConstantOp(Op, Id typeId, const std::vector& operands, const std::vector& literals); + + // Take an rvalue (source) and a set of channels to extract from it to + // make a new rvalue, which is returned. + Id createRvalueSwizzle(Decoration precision, Id typeId, Id source, const std::vector& channels); + + // Take a copy of an lvalue (target) and a source of components, and set the + // source components into the lvalue where the 'channels' say to put them. + // An updated version of the target is returned. + // (No true lvalue or stores are used.) + Id createLvalueSwizzle(Id typeId, Id target, Id source, const std::vector& channels); + + // If both the id and precision are valid, the id + // gets tagged with the requested precision. + // The passed in id is always the returned id, to simplify use patterns. + Id setPrecision(Id id, Decoration precision) + { + if (precision != NoPrecision && id != NoResult) + addDecoration(id, precision); + + return id; + } + + // Can smear a scalar to a vector for the following forms: + // - promoteScalar(scalar, vector) // smear scalar to width of vector + // - promoteScalar(vector, scalar) // smear scalar to width of vector + // - promoteScalar(pointer, scalar) // smear scalar to width of what pointer points to + // - promoteScalar(scalar, scalar) // do nothing + // Other forms are not allowed. + // + // Generally, the type of 'scalar' does not need to be the same type as the components in 'vector'. + // The type of the created vector is a vector of components of the same type as the scalar. + // + // Note: One of the arguments will change, with the result coming back that way rather than + // through the return value. + void promoteScalar(Decoration precision, Id& left, Id& right); + + // Make a value by smearing the scalar to fill the type. + // vectorType should be the correct type for making a vector of scalarVal. + // (No conversions are done.) + Id smearScalar(Decoration precision, Id scalarVal, Id vectorType); + + // Create a call to a built-in function. + Id createBuiltinCall(Id resultType, Id builtins, int entryPoint, const std::vector& args); + + // List of parameters used to create a texture operation + struct TextureParameters { + Id sampler; + Id coords; + Id bias; + Id lod; + Id Dref; + Id offset; + Id offsets; + Id gradX; + Id gradY; + Id sample; + Id component; + Id texelOut; + Id lodClamp; + Id granularity; + Id coarse; + bool nonprivate; + bool volatil; + }; + + // Select the correct texture operation based on all inputs, and emit the correct instruction + Id createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, + bool noImplicit, const TextureParameters&, ImageOperandsMask); + + // Emit the OpTextureQuery* instruction that was passed in. + // Figure out the right return value and type, and return it. + Id createTextureQueryCall(Op, const TextureParameters&, bool isUnsignedResult); + + Id createSamplePositionCall(Decoration precision, Id, Id); + + Id createBitFieldExtractCall(Decoration precision, Id, Id, Id, bool isSigned); + Id createBitFieldInsertCall(Decoration precision, Id, Id, Id, Id); + + // Reduction comparison for composites: For equal and not-equal resulting in a scalar. + Id createCompositeCompare(Decoration precision, Id, Id, bool /* true if for equal, false if for not-equal */); + + // OpCompositeConstruct + Id createCompositeConstruct(Id typeId, const std::vector& constituents); + + // vector or scalar constructor + Id createConstructor(Decoration precision, const std::vector& sources, Id resultTypeId); + + // matrix constructor + Id createMatrixConstructor(Decoration precision, const std::vector& sources, Id constructee); + + // Helper to use for building nested control flow with if-then-else. + class If { + public: + If(Id condition, unsigned int ctrl, Builder& builder); + ~If() {} + + void makeBeginElse(); + void makeEndIf(); + + private: + If(const If&); + If& operator=(If&); + + Builder& builder; + Id condition; + unsigned int control; + Function* function; + Block* headerBlock; + Block* thenBlock; + Block* elseBlock; + Block* mergeBlock; + }; + + // Make a switch statement. A switch has 'numSegments' of pieces of code, not containing + // any case/default labels, all separated by one or more case/default labels. Each possible + // case value v is a jump to the caseValues[v] segment. The defaultSegment is also in this + // number space. How to compute the value is given by 'condition', as in switch(condition). + // + // The SPIR-V Builder will maintain the stack of post-switch merge blocks for nested switches. + // + // Use a defaultSegment < 0 if there is no default segment (to branch to post switch). + // + // Returns the right set of basic blocks to start each code segment with, so that the caller's + // recursion stack can hold the memory for it. + // + void makeSwitch(Id condition, unsigned int control, int numSegments, const std::vector& caseValues, + const std::vector& valueToSegment, int defaultSegment, std::vector& segmentBB); + + // Add a branch to the innermost switch's merge block. + void addSwitchBreak(); + + // Move to the next code segment, passing in the return argument in makeSwitch() + void nextSwitchSegment(std::vector& segmentBB, int segment); + + // Finish off the innermost switch. + void endSwitch(std::vector& segmentBB); + + struct LoopBlocks { + LoopBlocks(Block& head, Block& body, Block& merge, Block& continue_target) : + head(head), body(body), merge(merge), continue_target(continue_target) { } + Block &head, &body, &merge, &continue_target; + private: + LoopBlocks(); + LoopBlocks& operator=(const LoopBlocks&) = delete; + }; + + // Start a new loop and prepare the builder to generate code for it. Until + // closeLoop() is called for this loop, createLoopContinue() and + // createLoopExit() will target its corresponding blocks. + LoopBlocks& makeNewLoop(); + + // Create a new block in the function containing the build point. Memory is + // owned by the function object. + Block& makeNewBlock(); + + // Add a branch to the continue_target of the current (innermost) loop. + void createLoopContinue(); + + // Add an exit (e.g. "break") from the innermost loop that we're currently + // in. + void createLoopExit(); + + // Close the innermost loop that you're in + void closeLoop(); + + // + // Access chain design for an R-Value vs. L-Value: + // + // There is a single access chain the builder is building at + // any particular time. Such a chain can be used to either to a load or + // a store, when desired. + // + // Expressions can be r-values, l-values, or both, or only r-values: + // a[b.c].d = .... // l-value + // ... = a[b.c].d; // r-value, that also looks like an l-value + // ++a[b.c].d; // r-value and l-value + // (x + y)[2]; // r-value only, can't possibly be l-value + // + // Computing an r-value means generating code. Hence, + // r-values should only be computed when they are needed, not speculatively. + // + // Computing an l-value means saving away information for later use in the compiler, + // no code is generated until the l-value is later dereferenced. It is okay + // to speculatively generate an l-value, just not okay to speculatively dereference it. + // + // The base of the access chain (the left-most variable or expression + // from which everything is based) can be set either as an l-value + // or as an r-value. Most efficient would be to set an l-value if one + // is available. If an expression was evaluated, the resulting r-value + // can be set as the chain base. + // + // The users of this single access chain can save and restore if they + // want to nest or manage multiple chains. + // + + struct AccessChain { + Id base; // for l-values, pointer to the base object, for r-values, the base object + std::vector indexChain; + Id instr; // cache the instruction that generates this access chain + std::vector swizzle; // each std::vector element selects the next GLSL component number + Id component; // a dynamic component index, can coexist with a swizzle, + // done after the swizzle, NoResult if not present + Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied; + // NoType unless a swizzle or component is present + bool isRValue; // true if 'base' is an r-value, otherwise, base is an l-value + unsigned int alignment; // bitwise OR of alignment values passed in. Accumulates worst alignment. + // Only tracks base and (optional) component selection alignment. + + // Accumulate whether anything in the chain of structures has coherent decorations. + struct CoherentFlags { + CoherentFlags() { clear(); } +#ifdef GLSLANG_WEB + void clear() { } + bool isVolatile() const { return false; } + CoherentFlags operator |=(const CoherentFlags &other) { return *this; } +#else + bool isVolatile() const { return volatil; } + bool anyCoherent() const { + return coherent || devicecoherent || queuefamilycoherent || workgroupcoherent || + subgroupcoherent || shadercallcoherent; + } + + unsigned coherent : 1; + unsigned devicecoherent : 1; + unsigned queuefamilycoherent : 1; + unsigned workgroupcoherent : 1; + unsigned subgroupcoherent : 1; + unsigned shadercallcoherent : 1; + unsigned nonprivate : 1; + unsigned volatil : 1; + unsigned isImage : 1; + + void clear() { + coherent = 0; + devicecoherent = 0; + queuefamilycoherent = 0; + workgroupcoherent = 0; + subgroupcoherent = 0; + shadercallcoherent = 0; + nonprivate = 0; + volatil = 0; + isImage = 0; + } + + CoherentFlags operator |=(const CoherentFlags &other) { + coherent |= other.coherent; + devicecoherent |= other.devicecoherent; + queuefamilycoherent |= other.queuefamilycoherent; + workgroupcoherent |= other.workgroupcoherent; + subgroupcoherent |= other.subgroupcoherent; + shadercallcoherent |= other.shadercallcoherent; + nonprivate |= other.nonprivate; + volatil |= other.volatil; + isImage |= other.isImage; + return *this; + } +#endif + }; + CoherentFlags coherentFlags; + }; + + // + // the SPIR-V builder maintains a single active chain that + // the following methods operate on + // + + // for external save and restore + AccessChain getAccessChain() { return accessChain; } + void setAccessChain(AccessChain newChain) { accessChain = newChain; } + + // clear accessChain + void clearAccessChain(); + + // set new base as an l-value base + void setAccessChainLValue(Id lValue) + { + assert(isPointer(lValue)); + accessChain.base = lValue; + } + + // set new base value as an r-value + void setAccessChainRValue(Id rValue) + { + accessChain.isRValue = true; + accessChain.base = rValue; + } + + // push offset onto the end of the chain + void accessChainPush(Id offset, AccessChain::CoherentFlags coherentFlags, unsigned int alignment) + { + accessChain.indexChain.push_back(offset); + accessChain.coherentFlags |= coherentFlags; + accessChain.alignment |= alignment; + } + + // push new swizzle onto the end of any existing swizzle, merging into a single swizzle + void accessChainPushSwizzle(std::vector& swizzle, Id preSwizzleBaseType, + AccessChain::CoherentFlags coherentFlags, unsigned int alignment); + + // push a dynamic component selection onto the access chain, only applicable with a + // non-trivial swizzle or no swizzle + void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, + unsigned int alignment) + { + if (accessChain.swizzle.size() != 1) { + accessChain.component = component; + if (accessChain.preSwizzleBaseType == NoType) + accessChain.preSwizzleBaseType = preSwizzleBaseType; + } + accessChain.coherentFlags |= coherentFlags; + accessChain.alignment |= alignment; + } + + // use accessChain and swizzle to store value + void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + + // use accessChain and swizzle to load an r-value + Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType, + spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, + unsigned int alignment = 0); + + // Return whether or not the access chain can be represented in SPIR-V + // as an l-value. + // E.g., a[3].yx cannot be, while a[3].y and a[3].y[x] can be. + bool isSpvLvalue() const { return accessChain.swizzle.size() <= 1; } + + // get the direct pointer for an l-value + Id accessChainGetLValue(); + + // Get the inferred SPIR-V type of the result of the current access chain, + // based on the type of the base and the chain of dereferences. + Id accessChainGetInferredType(); + + // Add capabilities, extensions, remove unneeded decorations, etc., + // based on the resulting SPIR-V. + void postProcess(); + + // Prune unreachable blocks in the CFG and remove unneeded decorations. + void postProcessCFG(); + +#ifndef GLSLANG_WEB + // Add capabilities, extensions based on instructions in the module. + void postProcessFeatures(); + // Hook to visit each instruction in a block in a function + void postProcess(Instruction&); + // Hook to visit each non-32-bit sized float/int operation in a block. + void postProcessType(const Instruction&, spv::Id typeId); +#endif + + void dump(std::vector&) const; + + void createBranch(Block* block); + void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock); + void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, + const std::vector& operands); + + // Sets to generate opcode for specialization constants. + void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; } + // Sets to generate opcode for non-specialization constants (normal mode). + void setToNormalCodeGenMode() { generatingOpCodeForSpecConst = false; } + // Check if the builder is generating code for spec constants. + bool isInSpecConstCodeGenMode() { return generatingOpCodeForSpecConst; } + + protected: + Id makeIntConstant(Id typeId, unsigned value, bool specConstant); + Id makeInt64Constant(Id typeId, unsigned long long value, bool specConstant); + Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value); + Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2); + Id findCompositeConstant(Op typeClass, Id typeId, const std::vector& comps); + Id findStructConstant(Id typeId, const std::vector& comps); + Id collapseAccessChain(); + void remapDynamicSwizzle(); + void transferAccessChainSwizzle(bool dynamic); + void simplifyAccessChainSwizzle(); + void createAndSetNoPredecessorBlock(const char*); + void createSelectionMerge(Block* mergeBlock, unsigned int control); + void dumpSourceInstructions(std::vector&) const; + void dumpSourceInstructions(const spv::Id fileId, const std::string& text, std::vector&) const; + void dumpInstructions(std::vector&, const std::vector >&) const; + void dumpModuleProcesses(std::vector&) const; + spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) + const; + + unsigned int spvVersion; // the version of SPIR-V to emit in the header + SourceLanguage source; + int sourceVersion; + spv::Id sourceFileStringId; + std::string sourceText; + int currentLine; + const char* currentFile; + bool emitOpLines; + std::set extensions; + std::vector sourceExtensions; + std::vector moduleProcesses; + AddressingModel addressModel; + MemoryModel memoryModel; + std::set capabilities; + int builderNumber; + Module module; + Block* buildPoint; + Id uniqueId; + Function* entryPointFunction; + bool generatingOpCodeForSpecConst; + AccessChain accessChain; + + // special blocks of instructions for output + std::vector > strings; + std::vector > imports; + std::vector > entryPoints; + std::vector > executionModes; + std::vector > names; + std::vector > decorations; + std::vector > constantsTypesGlobals; + std::vector > externals; + std::vector > functions; + + // not output, internally used for quick & dirty canonical (unique) creation + + // map type opcodes to constant inst. + std::unordered_map> groupedConstants; + // map struct-id to constant instructions + std::unordered_map> groupedStructConstants; + // map type opcodes to type instructions + std::unordered_map> groupedTypes; + + // stack of switches + std::stack switchMerges; + + // Our loop stack. + std::stack loops; + + // map from strings to their string ids + std::unordered_map stringIds; + + // map from include file name ids to their contents + std::map includeFiles; + + // The stream for outputting warnings and errors. + SpvBuildLogger* logger; +}; // end Builder class + +}; // end spv namespace + +#endif // SpvBuilder_H diff --git a/android/armeabi-v7a/include/glslang/SPIRV/SpvTools.h b/android/armeabi-v7a/include/glslang/SPIRV/SpvTools.h new file mode 100644 index 00000000..59c914da --- /dev/null +++ b/android/armeabi-v7a/include/glslang/SPIRV/SpvTools.h @@ -0,0 +1,82 @@ +// +// Copyright (C) 2014-2016 LunarG, Inc. +// Copyright (C) 2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Call into SPIRV-Tools to disassemble, validate, and optimize. +// + +#pragma once +#ifndef GLSLANG_SPV_TOOLS_H +#define GLSLANG_SPV_TOOLS_H + +#ifdef ENABLE_OPT +#include +#include +#endif + +#include "glslang/MachineIndependent/localintermediate.h" +#include "Logger.h" + +namespace glslang { + +struct SpvOptions { + SpvOptions() : generateDebugInfo(false), disableOptimizer(true), + optimizeSize(false), disassemble(false), validate(false) { } + bool generateDebugInfo; + bool disableOptimizer; + bool optimizeSize; + bool disassemble; + bool validate; +}; + +#ifdef ENABLE_OPT + +// Use the SPIRV-Tools disassembler to print SPIR-V. +void SpirvToolsDisassemble(std::ostream& out, const std::vector& spirv); + +// Apply the SPIRV-Tools validator to generated SPIR-V. +void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger*, bool prelegalization); + +// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of +// legalizing HLSL SPIR-V. +void SpirvToolsLegalize(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger*, const SpvOptions*); + +#endif + +} // end namespace glslang + +#endif // GLSLANG_SPV_TOOLS_H diff --git a/android/armeabi-v7a/include/glslang/SPIRV/bitutils.h b/android/armeabi-v7a/include/glslang/SPIRV/bitutils.h new file mode 100644 index 00000000..22e44cec --- /dev/null +++ b/android/armeabi-v7a/include/glslang/SPIRV/bitutils.h @@ -0,0 +1,81 @@ +// Copyright (c) 2015-2016 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef LIBSPIRV_UTIL_BITUTILS_H_ +#define LIBSPIRV_UTIL_BITUTILS_H_ + +#include +#include + +namespace spvutils { + +// Performs a bitwise copy of source to the destination type Dest. +template +Dest BitwiseCast(Src source) { + Dest dest; + static_assert(sizeof(source) == sizeof(dest), + "BitwiseCast: Source and destination must have the same size"); + std::memcpy(static_cast(&dest), &source, sizeof(dest)); + return dest; +} + +// SetBits returns an integer of type with bits set +// for position through , counting from the least +// significant bit. In particular when Num == 0, no positions are set to 1. +// A static assert will be triggered if First + Num > sizeof(T) * 8, that is, +// a bit that will not fit in the underlying type is set. +template +struct SetBits { + static_assert(First < sizeof(T) * 8, + "Tried to set a bit that is shifted too far."); + const static T get = (T(1) << First) | SetBits::get; +}; + +template +struct SetBits { + const static T get = T(0); +}; + +// This is all compile-time so we can put our tests right here. +static_assert(SetBits::get == uint32_t(0x00000000), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x00000001), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x80000000), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x00000006), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0xc0000000), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x7FFFFFFF), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0xFFFFFFFF), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0xFFFF0000), + "SetBits failed"); + +static_assert(SetBits::get == uint64_t(0x0000000000000001LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0x8000000000000000LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0xc000000000000000LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0x0000000080000000LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0x00000000FFFF0000LL), + "SetBits failed"); + +} // namespace spvutils + +#endif // LIBSPIRV_UTIL_BITUTILS_H_ diff --git a/android/armeabi-v7a/include/glslang/SPIRV/disassemble.h b/android/armeabi-v7a/include/glslang/SPIRV/disassemble.h new file mode 100644 index 00000000..b6a46357 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/SPIRV/disassemble.h @@ -0,0 +1,53 @@ +// +// Copyright (C) 2014-2015 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Disassembler for SPIR-V. +// + +#pragma once +#ifndef disassembler_H +#define disassembler_H + +#include +#include + +namespace spv { + + // disassemble with glslang custom disassembler + void Disassemble(std::ostream& out, const std::vector&); + +} // end namespace spv + +#endif // disassembler_H diff --git a/android/armeabi-v7a/include/glslang/SPIRV/doc.h b/android/armeabi-v7a/include/glslang/SPIRV/doc.h new file mode 100644 index 00000000..293256a2 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/SPIRV/doc.h @@ -0,0 +1,258 @@ +// +// Copyright (C) 2014-2015 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Parameterize the SPIR-V enumerants. +// + +#pragma once + +#include "spirv.hpp" + +#include + +namespace spv { + +// Fill in all the parameters +void Parameterize(); + +// Return the English names of all the enums. +const char* SourceString(int); +const char* AddressingString(int); +const char* MemoryString(int); +const char* ExecutionModelString(int); +const char* ExecutionModeString(int); +const char* StorageClassString(int); +const char* DecorationString(int); +const char* BuiltInString(int); +const char* DimensionString(int); +const char* SelectControlString(int); +const char* LoopControlString(int); +const char* FunctionControlString(int); +const char* SamplerAddressingModeString(int); +const char* SamplerFilterModeString(int); +const char* ImageFormatString(int); +const char* ImageChannelOrderString(int); +const char* ImageChannelTypeString(int); +const char* ImageChannelDataTypeString(int type); +const char* ImageOperandsString(int format); +const char* ImageOperands(int); +const char* FPFastMathString(int); +const char* FPRoundingModeString(int); +const char* LinkageTypeString(int); +const char* FuncParamAttrString(int); +const char* AccessQualifierString(int); +const char* MemorySemanticsString(int); +const char* MemoryAccessString(int); +const char* ExecutionScopeString(int); +const char* GroupOperationString(int); +const char* KernelEnqueueFlagsString(int); +const char* KernelProfilingInfoString(int); +const char* CapabilityString(int); +const char* OpcodeString(int); +const char* ScopeString(int mem); + +// For grouping opcodes into subsections +enum OpcodeClass { + OpClassMisc, + OpClassDebug, + OpClassAnnotate, + OpClassExtension, + OpClassMode, + OpClassType, + OpClassConstant, + OpClassMemory, + OpClassFunction, + OpClassImage, + OpClassConvert, + OpClassComposite, + OpClassArithmetic, + OpClassBit, + OpClassRelationalLogical, + OpClassDerivative, + OpClassFlowControl, + OpClassAtomic, + OpClassPrimitive, + OpClassBarrier, + OpClassGroup, + OpClassDeviceSideEnqueue, + OpClassPipe, + + OpClassCount, + OpClassMissing // all instructions start out as missing +}; + +// For parameterizing operands. +enum OperandClass { + OperandNone, + OperandId, + OperandVariableIds, + OperandOptionalLiteral, + OperandOptionalLiteralString, + OperandVariableLiterals, + OperandVariableIdLiteral, + OperandVariableLiteralId, + OperandLiteralNumber, + OperandLiteralString, + OperandSource, + OperandExecutionModel, + OperandAddressing, + OperandMemory, + OperandExecutionMode, + OperandStorage, + OperandDimensionality, + OperandSamplerAddressingMode, + OperandSamplerFilterMode, + OperandSamplerImageFormat, + OperandImageChannelOrder, + OperandImageChannelDataType, + OperandImageOperands, + OperandFPFastMath, + OperandFPRoundingMode, + OperandLinkageType, + OperandAccessQualifier, + OperandFuncParamAttr, + OperandDecoration, + OperandBuiltIn, + OperandSelect, + OperandLoop, + OperandFunction, + OperandMemorySemantics, + OperandMemoryAccess, + OperandScope, + OperandGroupOperation, + OperandKernelEnqueueFlags, + OperandKernelProfilingInfo, + OperandCapability, + + OperandOpcode, + + OperandCount +}; + +// Any specific enum can have a set of capabilities that allow it: +typedef std::vector EnumCaps; + +// Parameterize a set of operands with their OperandClass(es) and descriptions. +class OperandParameters { +public: + OperandParameters() { } + void push(OperandClass oc, const char* d, bool opt = false) + { + opClass.push_back(oc); + desc.push_back(d); + optional.push_back(opt); + } + void setOptional(); + OperandClass getClass(int op) const { return opClass[op]; } + const char* getDesc(int op) const { return desc[op]; } + bool isOptional(int op) const { return optional[op]; } + int getNum() const { return (int)opClass.size(); } + +protected: + std::vector opClass; + std::vector desc; + std::vector optional; +}; + +// Parameterize an enumerant +class EnumParameters { +public: + EnumParameters() : desc(0) { } + const char* desc; +}; + +// Parameterize a set of enumerants that form an enum +class EnumDefinition : public EnumParameters { +public: + EnumDefinition() : + ceiling(0), bitmask(false), getName(0), enumParams(0), operandParams(0) { } + void set(int ceil, const char* (*name)(int), EnumParameters* ep, bool mask = false) + { + ceiling = ceil; + getName = name; + bitmask = mask; + enumParams = ep; + } + void setOperands(OperandParameters* op) { operandParams = op; } + int ceiling; // ceiling of enumerants + bool bitmask; // true if these enumerants combine into a bitmask + const char* (*getName)(int); // a function that returns the name for each enumerant value (or shift) + EnumParameters* enumParams; // parameters for each individual enumerant + OperandParameters* operandParams; // sets of operands +}; + +// Parameterize an instruction's logical format, including its known set of operands, +// per OperandParameters above. +class InstructionParameters { +public: + InstructionParameters() : + opDesc("TBD"), + opClass(OpClassMissing), + typePresent(true), // most normal, only exceptions have to be spelled out + resultPresent(true) // most normal, only exceptions have to be spelled out + { } + + void setResultAndType(bool r, bool t) + { + resultPresent = r; + typePresent = t; + } + + bool hasResult() const { return resultPresent != 0; } + bool hasType() const { return typePresent != 0; } + + const char* opDesc; + OpcodeClass opClass; + OperandParameters operands; + +protected: + int typePresent : 1; + int resultPresent : 1; +}; + +// The set of objects that hold all the instruction/operand +// parameterization information. +extern InstructionParameters InstructionDesc[]; + +// These hold definitions of the enumerants used for operands +extern EnumDefinition OperandClassParams[]; + +const char* GetOperandDesc(OperandClass operand); +void PrintImmediateRow(int imm, const char* name, const EnumParameters* enumParams, bool caps, bool hex = false); +const char* AccessQualifierString(int attr); + +void PrintOperands(const OperandParameters& operands, int reservedOperands); + +} // end namespace spv diff --git a/android/armeabi-v7a/include/glslang/SPIRV/hex_float.h b/android/armeabi-v7a/include/glslang/SPIRV/hex_float.h new file mode 100644 index 00000000..8be8e9f7 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/SPIRV/hex_float.h @@ -0,0 +1,1078 @@ +// Copyright (c) 2015-2016 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef LIBSPIRV_UTIL_HEX_FLOAT_H_ +#define LIBSPIRV_UTIL_HEX_FLOAT_H_ + +#include +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) && _MSC_VER < 1800 +namespace std { +bool isnan(double f) +{ + return ::_isnan(f) != 0; +} +bool isinf(double f) +{ + return ::_finite(f) == 0; +} +} +#endif + +#include "bitutils.h" + +namespace spvutils { + +class Float16 { + public: + Float16(uint16_t v) : val(v) {} + Float16() {} + static bool isNan(const Float16& val) { + return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) != 0); + } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(const Float16& val) { + return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) == 0); + } + Float16(const Float16& other) { val = other.val; } + uint16_t get_value() const { return val; } + + // Returns the maximum normal value. + static Float16 max() { return Float16(0x7bff); } + // Returns the lowest normal value. + static Float16 lowest() { return Float16(0xfbff); } + + private: + uint16_t val; +}; + +// To specialize this type, you must override uint_type to define +// an unsigned integer that can fit your floating point type. +// You must also add a isNan function that returns true if +// a value is Nan. +template +struct FloatProxyTraits { + typedef void uint_type; +}; + +template <> +struct FloatProxyTraits { + typedef uint32_t uint_type; + static bool isNan(float f) { return std::isnan(f); } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(float f) { return std::isinf(f); } + // Returns the maximum normal value. + static float max() { return std::numeric_limits::max(); } + // Returns the lowest normal value. + static float lowest() { return std::numeric_limits::lowest(); } +}; + +template <> +struct FloatProxyTraits { + typedef uint64_t uint_type; + static bool isNan(double f) { return std::isnan(f); } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(double f) { return std::isinf(f); } + // Returns the maximum normal value. + static double max() { return std::numeric_limits::max(); } + // Returns the lowest normal value. + static double lowest() { return std::numeric_limits::lowest(); } +}; + +template <> +struct FloatProxyTraits { + typedef uint16_t uint_type; + static bool isNan(Float16 f) { return Float16::isNan(f); } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(Float16 f) { return Float16::isInfinity(f); } + // Returns the maximum normal value. + static Float16 max() { return Float16::max(); } + // Returns the lowest normal value. + static Float16 lowest() { return Float16::lowest(); } +}; + +// Since copying a floating point number (especially if it is NaN) +// does not guarantee that bits are preserved, this class lets us +// store the type and use it as a float when necessary. +template +class FloatProxy { + public: + typedef typename FloatProxyTraits::uint_type uint_type; + + // Since this is to act similar to the normal floats, + // do not initialize the data by default. + FloatProxy() {} + + // Intentionally non-explicit. This is a proxy type so + // implicit conversions allow us to use it more transparently. + FloatProxy(T val) { data_ = BitwiseCast(val); } + + // Intentionally non-explicit. This is a proxy type so + // implicit conversions allow us to use it more transparently. + FloatProxy(uint_type val) { data_ = val; } + + // This is helpful to have and is guaranteed not to stomp bits. + FloatProxy operator-() const { + return static_cast(data_ ^ + (uint_type(0x1) << (sizeof(T) * 8 - 1))); + } + + // Returns the data as a floating point value. + T getAsFloat() const { return BitwiseCast(data_); } + + // Returns the raw data. + uint_type data() const { return data_; } + + // Returns true if the value represents any type of NaN. + bool isNan() { return FloatProxyTraits::isNan(getAsFloat()); } + // Returns true if the value represents any type of infinity. + bool isInfinity() { return FloatProxyTraits::isInfinity(getAsFloat()); } + + // Returns the maximum normal value. + static FloatProxy max() { + return FloatProxy(FloatProxyTraits::max()); + } + // Returns the lowest normal value. + static FloatProxy lowest() { + return FloatProxy(FloatProxyTraits::lowest()); + } + + private: + uint_type data_; +}; + +template +bool operator==(const FloatProxy& first, const FloatProxy& second) { + return first.data() == second.data(); +} + +// Reads a FloatProxy value as a normal float from a stream. +template +std::istream& operator>>(std::istream& is, FloatProxy& value) { + T float_val; + is >> float_val; + value = FloatProxy(float_val); + return is; +} + +// This is an example traits. It is not meant to be used in practice, but will +// be the default for any non-specialized type. +template +struct HexFloatTraits { + // Integer type that can store this hex-float. + typedef void uint_type; + // Signed integer type that can store this hex-float. + typedef void int_type; + // The numerical type that this HexFloat represents. + typedef void underlying_type; + // The type needed to construct the underlying type. + typedef void native_type; + // The number of bits that are actually relevant in the uint_type. + // This allows us to deal with, for example, 24-bit values in a 32-bit + // integer. + static const uint32_t num_used_bits = 0; + // Number of bits that represent the exponent. + static const uint32_t num_exponent_bits = 0; + // Number of bits that represent the fractional part. + static const uint32_t num_fraction_bits = 0; + // The bias of the exponent. (How much we need to subtract from the stored + // value to get the correct value.) + static const uint32_t exponent_bias = 0; +}; + +// Traits for IEEE float. +// 1 sign bit, 8 exponent bits, 23 fractional bits. +template <> +struct HexFloatTraits> { + typedef uint32_t uint_type; + typedef int32_t int_type; + typedef FloatProxy underlying_type; + typedef float native_type; + static const uint_type num_used_bits = 32; + static const uint_type num_exponent_bits = 8; + static const uint_type num_fraction_bits = 23; + static const uint_type exponent_bias = 127; +}; + +// Traits for IEEE double. +// 1 sign bit, 11 exponent bits, 52 fractional bits. +template <> +struct HexFloatTraits> { + typedef uint64_t uint_type; + typedef int64_t int_type; + typedef FloatProxy underlying_type; + typedef double native_type; + static const uint_type num_used_bits = 64; + static const uint_type num_exponent_bits = 11; + static const uint_type num_fraction_bits = 52; + static const uint_type exponent_bias = 1023; +}; + +// Traits for IEEE half. +// 1 sign bit, 5 exponent bits, 10 fractional bits. +template <> +struct HexFloatTraits> { + typedef uint16_t uint_type; + typedef int16_t int_type; + typedef uint16_t underlying_type; + typedef uint16_t native_type; + static const uint_type num_used_bits = 16; + static const uint_type num_exponent_bits = 5; + static const uint_type num_fraction_bits = 10; + static const uint_type exponent_bias = 15; +}; + +enum round_direction { + kRoundToZero, + kRoundToNearestEven, + kRoundToPositiveInfinity, + kRoundToNegativeInfinity +}; + +// Template class that houses a floating pointer number. +// It exposes a number of constants based on the provided traits to +// assist in interpreting the bits of the value. +template > +class HexFloat { + public: + typedef typename Traits::uint_type uint_type; + typedef typename Traits::int_type int_type; + typedef typename Traits::underlying_type underlying_type; + typedef typename Traits::native_type native_type; + + explicit HexFloat(T f) : value_(f) {} + + T value() const { return value_; } + void set_value(T f) { value_ = f; } + + // These are all written like this because it is convenient to have + // compile-time constants for all of these values. + + // Pass-through values to save typing. + static const uint32_t num_used_bits = Traits::num_used_bits; + static const uint32_t exponent_bias = Traits::exponent_bias; + static const uint32_t num_exponent_bits = Traits::num_exponent_bits; + static const uint32_t num_fraction_bits = Traits::num_fraction_bits; + + // Number of bits to shift left to set the highest relevant bit. + static const uint32_t top_bit_left_shift = num_used_bits - 1; + // How many nibbles (hex characters) the fractional part takes up. + static const uint32_t fraction_nibbles = (num_fraction_bits + 3) / 4; + // If the fractional part does not fit evenly into a hex character (4-bits) + // then we have to left-shift to get rid of leading 0s. This is the amount + // we have to shift (might be 0). + static const uint32_t num_overflow_bits = + fraction_nibbles * 4 - num_fraction_bits; + + // The representation of the fraction, not the actual bits. This + // includes the leading bit that is usually implicit. + static const uint_type fraction_represent_mask = + spvutils::SetBits::get; + + // The topmost bit in the nibble-aligned fraction. + static const uint_type fraction_top_bit = + uint_type(1) << (num_fraction_bits + num_overflow_bits - 1); + + // The least significant bit in the exponent, which is also the bit + // immediately to the left of the significand. + static const uint_type first_exponent_bit = uint_type(1) + << (num_fraction_bits); + + // The mask for the encoded fraction. It does not include the + // implicit bit. + static const uint_type fraction_encode_mask = + spvutils::SetBits::get; + + // The bit that is used as a sign. + static const uint_type sign_mask = uint_type(1) << top_bit_left_shift; + + // The bits that represent the exponent. + static const uint_type exponent_mask = + spvutils::SetBits::get; + + // How far left the exponent is shifted. + static const uint32_t exponent_left_shift = num_fraction_bits; + + // How far from the right edge the fraction is shifted. + static const uint32_t fraction_right_shift = + static_cast(sizeof(uint_type) * 8) - num_fraction_bits; + + // The maximum representable unbiased exponent. + static const int_type max_exponent = + (exponent_mask >> num_fraction_bits) - exponent_bias; + // The minimum representable exponent for normalized numbers. + static const int_type min_exponent = -static_cast(exponent_bias); + + // Returns the bits associated with the value. + uint_type getBits() const { return spvutils::BitwiseCast(value_); } + + // Returns the bits associated with the value, without the leading sign bit. + uint_type getUnsignedBits() const { + return static_cast(spvutils::BitwiseCast(value_) & + ~sign_mask); + } + + // Returns the bits associated with the exponent, shifted to start at the + // lsb of the type. + const uint_type getExponentBits() const { + return static_cast((getBits() & exponent_mask) >> + num_fraction_bits); + } + + // Returns the exponent in unbiased form. This is the exponent in the + // human-friendly form. + const int_type getUnbiasedExponent() const { + return static_cast(getExponentBits() - exponent_bias); + } + + // Returns just the significand bits from the value. + const uint_type getSignificandBits() const { + return getBits() & fraction_encode_mask; + } + + // If the number was normalized, returns the unbiased exponent. + // If the number was denormal, normalize the exponent first. + const int_type getUnbiasedNormalizedExponent() const { + if ((getBits() & ~sign_mask) == 0) { // special case if everything is 0 + return 0; + } + int_type exp = getUnbiasedExponent(); + if (exp == min_exponent) { // We are in denorm land. + uint_type significand_bits = getSignificandBits(); + while ((significand_bits & (first_exponent_bit >> 1)) == 0) { + significand_bits = static_cast(significand_bits << 1); + exp = static_cast(exp - 1); + } + significand_bits &= fraction_encode_mask; + } + return exp; + } + + // Returns the signficand after it has been normalized. + const uint_type getNormalizedSignificand() const { + int_type unbiased_exponent = getUnbiasedNormalizedExponent(); + uint_type significand = getSignificandBits(); + for (int_type i = unbiased_exponent; i <= min_exponent; ++i) { + significand = static_cast(significand << 1); + } + significand &= fraction_encode_mask; + return significand; + } + + // Returns true if this number represents a negative value. + bool isNegative() const { return (getBits() & sign_mask) != 0; } + + // Sets this HexFloat from the individual components. + // Note this assumes EVERY significand is normalized, and has an implicit + // leading one. This means that the only way that this method will set 0, + // is if you set a number so denormalized that it underflows. + // Do not use this method with raw bits extracted from a subnormal number, + // since subnormals do not have an implicit leading 1 in the significand. + // The significand is also expected to be in the + // lowest-most num_fraction_bits of the uint_type. + // The exponent is expected to be unbiased, meaning an exponent of + // 0 actually means 0. + // If underflow_round_up is set, then on underflow, if a number is non-0 + // and would underflow, we round up to the smallest denorm. + void setFromSignUnbiasedExponentAndNormalizedSignificand( + bool negative, int_type exponent, uint_type significand, + bool round_denorm_up) { + bool significand_is_zero = significand == 0; + + if (exponent <= min_exponent) { + // If this was denormalized, then we have to shift the bit on, meaning + // the significand is not zero. + significand_is_zero = false; + significand |= first_exponent_bit; + significand = static_cast(significand >> 1); + } + + while (exponent < min_exponent) { + significand = static_cast(significand >> 1); + ++exponent; + } + + if (exponent == min_exponent) { + if (significand == 0 && !significand_is_zero && round_denorm_up) { + significand = static_cast(0x1); + } + } + + uint_type new_value = 0; + if (negative) { + new_value = static_cast(new_value | sign_mask); + } + exponent = static_cast(exponent + exponent_bias); + assert(exponent >= 0); + + // put it all together + exponent = static_cast((exponent << exponent_left_shift) & + exponent_mask); + significand = static_cast(significand & fraction_encode_mask); + new_value = static_cast(new_value | (exponent | significand)); + value_ = BitwiseCast(new_value); + } + + // Increments the significand of this number by the given amount. + // If this would spill the significand into the implicit bit, + // carry is set to true and the significand is shifted to fit into + // the correct location, otherwise carry is set to false. + // All significands and to_increment are assumed to be within the bounds + // for a valid significand. + static uint_type incrementSignificand(uint_type significand, + uint_type to_increment, bool* carry) { + significand = static_cast(significand + to_increment); + *carry = false; + if (significand & first_exponent_bit) { + *carry = true; + // The implicit 1-bit will have carried, so we should zero-out the + // top bit and shift back. + significand = static_cast(significand & ~first_exponent_bit); + significand = static_cast(significand >> 1); + } + return significand; + } + + // These exist because MSVC throws warnings on negative right-shifts + // even if they are not going to be executed. Eg: + // constant_number < 0? 0: constant_number + // These convert the negative left-shifts into right shifts. + + template + uint_type negatable_left_shift(int_type N, uint_type val) + { + if(N >= 0) + return val << N; + + return val >> -N; + } + + template + uint_type negatable_right_shift(int_type N, uint_type val) + { + if(N >= 0) + return val >> N; + + return val << -N; + } + + // Returns the significand, rounded to fit in a significand in + // other_T. This is shifted so that the most significant + // bit of the rounded number lines up with the most significant bit + // of the returned significand. + template + typename other_T::uint_type getRoundedNormalizedSignificand( + round_direction dir, bool* carry_bit) { + typedef typename other_T::uint_type other_uint_type; + static const int_type num_throwaway_bits = + static_cast(num_fraction_bits) - + static_cast(other_T::num_fraction_bits); + + static const uint_type last_significant_bit = + (num_throwaway_bits < 0) + ? 0 + : negatable_left_shift(num_throwaway_bits, 1u); + static const uint_type first_rounded_bit = + (num_throwaway_bits < 1) + ? 0 + : negatable_left_shift(num_throwaway_bits - 1, 1u); + + static const uint_type throwaway_mask_bits = + num_throwaway_bits > 0 ? num_throwaway_bits : 0; + static const uint_type throwaway_mask = + spvutils::SetBits::get; + + *carry_bit = false; + other_uint_type out_val = 0; + uint_type significand = getNormalizedSignificand(); + // If we are up-casting, then we just have to shift to the right location. + if (num_throwaway_bits <= 0) { + out_val = static_cast(significand); + uint_type shift_amount = static_cast(-num_throwaway_bits); + out_val = static_cast(out_val << shift_amount); + return out_val; + } + + // If every non-representable bit is 0, then we don't have any casting to + // do. + if ((significand & throwaway_mask) == 0) { + return static_cast( + negatable_right_shift(num_throwaway_bits, significand)); + } + + bool round_away_from_zero = false; + // We actually have to narrow the significand here, so we have to follow the + // rounding rules. + switch (dir) { + case kRoundToZero: + break; + case kRoundToPositiveInfinity: + round_away_from_zero = !isNegative(); + break; + case kRoundToNegativeInfinity: + round_away_from_zero = isNegative(); + break; + case kRoundToNearestEven: + // Have to round down, round bit is 0 + if ((first_rounded_bit & significand) == 0) { + break; + } + if (((significand & throwaway_mask) & ~first_rounded_bit) != 0) { + // If any subsequent bit of the rounded portion is non-0 then we round + // up. + round_away_from_zero = true; + break; + } + // We are exactly half-way between 2 numbers, pick even. + if ((significand & last_significant_bit) != 0) { + // 1 for our last bit, round up. + round_away_from_zero = true; + break; + } + break; + } + + if (round_away_from_zero) { + return static_cast( + negatable_right_shift(num_throwaway_bits, incrementSignificand( + significand, last_significant_bit, carry_bit))); + } else { + return static_cast( + negatable_right_shift(num_throwaway_bits, significand)); + } + } + + // Casts this value to another HexFloat. If the cast is widening, + // then round_dir is ignored. If the cast is narrowing, then + // the result is rounded in the direction specified. + // This number will retain Nan and Inf values. + // It will also saturate to Inf if the number overflows, and + // underflow to (0 or min depending on rounding) if the number underflows. + template + void castTo(other_T& other, round_direction round_dir) { + other = other_T(static_cast(0)); + bool negate = isNegative(); + if (getUnsignedBits() == 0) { + if (negate) { + other.set_value(-other.value()); + } + return; + } + uint_type significand = getSignificandBits(); + bool carried = false; + typename other_T::uint_type rounded_significand = + getRoundedNormalizedSignificand(round_dir, &carried); + + int_type exponent = getUnbiasedExponent(); + if (exponent == min_exponent) { + // If we are denormal, normalize the exponent, so that we can encode + // easily. + exponent = static_cast(exponent + 1); + for (uint_type check_bit = first_exponent_bit >> 1; check_bit != 0; + check_bit = static_cast(check_bit >> 1)) { + exponent = static_cast(exponent - 1); + if (check_bit & significand) break; + } + } + + bool is_nan = + (getBits() & exponent_mask) == exponent_mask && significand != 0; + bool is_inf = + !is_nan && + ((exponent + carried) > static_cast(other_T::exponent_bias) || + (significand == 0 && (getBits() & exponent_mask) == exponent_mask)); + + // If we are Nan or Inf we should pass that through. + if (is_inf) { + other.set_value(BitwiseCast( + static_cast( + (negate ? other_T::sign_mask : 0) | other_T::exponent_mask))); + return; + } + if (is_nan) { + typename other_T::uint_type shifted_significand; + shifted_significand = static_cast( + negatable_left_shift( + static_cast(other_T::num_fraction_bits) - + static_cast(num_fraction_bits), significand)); + + // We are some sort of Nan. We try to keep the bit-pattern of the Nan + // as close as possible. If we had to shift off bits so we are 0, then we + // just set the last bit. + other.set_value(BitwiseCast( + static_cast( + (negate ? other_T::sign_mask : 0) | other_T::exponent_mask | + (shifted_significand == 0 ? 0x1 : shifted_significand)))); + return; + } + + bool round_underflow_up = + isNegative() ? round_dir == kRoundToNegativeInfinity + : round_dir == kRoundToPositiveInfinity; + typedef typename other_T::int_type other_int_type; + // setFromSignUnbiasedExponentAndNormalizedSignificand will + // zero out any underflowing value (but retain the sign). + other.setFromSignUnbiasedExponentAndNormalizedSignificand( + negate, static_cast(exponent), rounded_significand, + round_underflow_up); + return; + } + + private: + T value_; + + static_assert(num_used_bits == + Traits::num_exponent_bits + Traits::num_fraction_bits + 1, + "The number of bits do not fit"); + static_assert(sizeof(T) == sizeof(uint_type), "The type sizes do not match"); +}; + +// Returns 4 bits represented by the hex character. +inline uint8_t get_nibble_from_character(int character) { + const char* dec = "0123456789"; + const char* lower = "abcdef"; + const char* upper = "ABCDEF"; + const char* p = nullptr; + if ((p = strchr(dec, character))) { + return static_cast(p - dec); + } else if ((p = strchr(lower, character))) { + return static_cast(p - lower + 0xa); + } else if ((p = strchr(upper, character))) { + return static_cast(p - upper + 0xa); + } + + assert(false && "This was called with a non-hex character"); + return 0; +} + +// Outputs the given HexFloat to the stream. +template +std::ostream& operator<<(std::ostream& os, const HexFloat& value) { + typedef HexFloat HF; + typedef typename HF::uint_type uint_type; + typedef typename HF::int_type int_type; + + static_assert(HF::num_used_bits != 0, + "num_used_bits must be non-zero for a valid float"); + static_assert(HF::num_exponent_bits != 0, + "num_exponent_bits must be non-zero for a valid float"); + static_assert(HF::num_fraction_bits != 0, + "num_fractin_bits must be non-zero for a valid float"); + + const uint_type bits = spvutils::BitwiseCast(value.value()); + const char* const sign = (bits & HF::sign_mask) ? "-" : ""; + const uint_type exponent = static_cast( + (bits & HF::exponent_mask) >> HF::num_fraction_bits); + + uint_type fraction = static_cast((bits & HF::fraction_encode_mask) + << HF::num_overflow_bits); + + const bool is_zero = exponent == 0 && fraction == 0; + const bool is_denorm = exponent == 0 && !is_zero; + + // exponent contains the biased exponent we have to convert it back into + // the normal range. + int_type int_exponent = static_cast(exponent - HF::exponent_bias); + // If the number is all zeros, then we actually have to NOT shift the + // exponent. + int_exponent = is_zero ? 0 : int_exponent; + + // If we are denorm, then start shifting, and decreasing the exponent until + // our leading bit is 1. + + if (is_denorm) { + while ((fraction & HF::fraction_top_bit) == 0) { + fraction = static_cast(fraction << 1); + int_exponent = static_cast(int_exponent - 1); + } + // Since this is denormalized, we have to consume the leading 1 since it + // will end up being implicit. + fraction = static_cast(fraction << 1); // eat the leading 1 + fraction &= HF::fraction_represent_mask; + } + + uint_type fraction_nibbles = HF::fraction_nibbles; + // We do not have to display any trailing 0s, since this represents the + // fractional part. + while (fraction_nibbles > 0 && (fraction & 0xF) == 0) { + // Shift off any trailing values; + fraction = static_cast(fraction >> 4); + --fraction_nibbles; + } + + const auto saved_flags = os.flags(); + const auto saved_fill = os.fill(); + + os << sign << "0x" << (is_zero ? '0' : '1'); + if (fraction_nibbles) { + // Make sure to keep the leading 0s in place, since this is the fractional + // part. + os << "." << std::setw(static_cast(fraction_nibbles)) + << std::setfill('0') << std::hex << fraction; + } + os << "p" << std::dec << (int_exponent >= 0 ? "+" : "") << int_exponent; + + os.flags(saved_flags); + os.fill(saved_fill); + + return os; +} + +// Returns true if negate_value is true and the next character on the +// input stream is a plus or minus sign. In that case we also set the fail bit +// on the stream and set the value to the zero value for its type. +template +inline bool RejectParseDueToLeadingSign(std::istream& is, bool negate_value, + HexFloat& value) { + if (negate_value) { + auto next_char = is.peek(); + if (next_char == '-' || next_char == '+') { + // Fail the parse. Emulate standard behaviour by setting the value to + // the zero value, and set the fail bit on the stream. + value = HexFloat(typename HexFloat::uint_type(0)); + is.setstate(std::ios_base::failbit); + return true; + } + } + return false; +} + +// Parses a floating point number from the given stream and stores it into the +// value parameter. +// If negate_value is true then the number may not have a leading minus or +// plus, and if it successfully parses, then the number is negated before +// being stored into the value parameter. +// If the value cannot be correctly parsed or overflows the target floating +// point type, then set the fail bit on the stream. +// TODO(dneto): Promise C++11 standard behavior in how the value is set in +// the error case, but only after all target platforms implement it correctly. +// In particular, the Microsoft C++ runtime appears to be out of spec. +template +inline std::istream& ParseNormalFloat(std::istream& is, bool negate_value, + HexFloat& value) { + if (RejectParseDueToLeadingSign(is, negate_value, value)) { + return is; + } + T val; + is >> val; + if (negate_value) { + val = -val; + } + value.set_value(val); + // In the failure case, map -0.0 to 0.0. + if (is.fail() && value.getUnsignedBits() == 0u) { + value = HexFloat(typename HexFloat::uint_type(0)); + } + if (val.isInfinity()) { + // Fail the parse. Emulate standard behaviour by setting the value to + // the closest normal value, and set the fail bit on the stream. + value.set_value((value.isNegative() || negate_value) ? T::lowest() + : T::max()); + is.setstate(std::ios_base::failbit); + } + return is; +} + +// Specialization of ParseNormalFloat for FloatProxy values. +// This will parse the float as it were a 32-bit floating point number, +// and then round it down to fit into a Float16 value. +// The number is rounded towards zero. +// If negate_value is true then the number may not have a leading minus or +// plus, and if it successfully parses, then the number is negated before +// being stored into the value parameter. +// If the value cannot be correctly parsed or overflows the target floating +// point type, then set the fail bit on the stream. +// TODO(dneto): Promise C++11 standard behavior in how the value is set in +// the error case, but only after all target platforms implement it correctly. +// In particular, the Microsoft C++ runtime appears to be out of spec. +template <> +inline std::istream& +ParseNormalFloat, HexFloatTraits>>( + std::istream& is, bool negate_value, + HexFloat, HexFloatTraits>>& value) { + // First parse as a 32-bit float. + HexFloat> float_val(0.0f); + ParseNormalFloat(is, negate_value, float_val); + + // Then convert to 16-bit float, saturating at infinities, and + // rounding toward zero. + float_val.castTo(value, kRoundToZero); + + // Overflow on 16-bit behaves the same as for 32- and 64-bit: set the + // fail bit and set the lowest or highest value. + if (Float16::isInfinity(value.value().getAsFloat())) { + value.set_value(value.isNegative() ? Float16::lowest() : Float16::max()); + is.setstate(std::ios_base::failbit); + } + return is; +} + +// Reads a HexFloat from the given stream. +// If the float is not encoded as a hex-float then it will be parsed +// as a regular float. +// This may fail if your stream does not support at least one unget. +// Nan values can be encoded with "0x1.p+exponent_bias". +// This would normally overflow a float and round to +// infinity but this special pattern is the exact representation for a NaN, +// and therefore is actually encoded as the correct NaN. To encode inf, +// either 0x0p+exponent_bias can be specified or any exponent greater than +// exponent_bias. +// Examples using IEEE 32-bit float encoding. +// 0x1.0p+128 (+inf) +// -0x1.0p-128 (-inf) +// +// 0x1.1p+128 (+Nan) +// -0x1.1p+128 (-Nan) +// +// 0x1p+129 (+inf) +// -0x1p+129 (-inf) +template +std::istream& operator>>(std::istream& is, HexFloat& value) { + using HF = HexFloat; + using uint_type = typename HF::uint_type; + using int_type = typename HF::int_type; + + value.set_value(static_cast(0.f)); + + if (is.flags() & std::ios::skipws) { + // If the user wants to skip whitespace , then we should obey that. + while (std::isspace(is.peek())) { + is.get(); + } + } + + auto next_char = is.peek(); + bool negate_value = false; + + if (next_char != '-' && next_char != '0') { + return ParseNormalFloat(is, negate_value, value); + } + + if (next_char == '-') { + negate_value = true; + is.get(); + next_char = is.peek(); + } + + if (next_char == '0') { + is.get(); // We may have to unget this. + auto maybe_hex_start = is.peek(); + if (maybe_hex_start != 'x' && maybe_hex_start != 'X') { + is.unget(); + return ParseNormalFloat(is, negate_value, value); + } else { + is.get(); // Throw away the 'x'; + } + } else { + return ParseNormalFloat(is, negate_value, value); + } + + // This "looks" like a hex-float so treat it as one. + bool seen_p = false; + bool seen_dot = false; + uint_type fraction_index = 0; + + uint_type fraction = 0; + int_type exponent = HF::exponent_bias; + + // Strip off leading zeros so we don't have to special-case them later. + while ((next_char = is.peek()) == '0') { + is.get(); + } + + bool is_denorm = + true; // Assume denorm "representation" until we hear otherwise. + // NB: This does not mean the value is actually denorm, + // it just means that it was written 0. + bool bits_written = false; // Stays false until we write a bit. + while (!seen_p && !seen_dot) { + // Handle characters that are left of the fractional part. + if (next_char == '.') { + seen_dot = true; + } else if (next_char == 'p') { + seen_p = true; + } else if (::isxdigit(next_char)) { + // We know this is not denormalized since we have stripped all leading + // zeroes and we are not a ".". + is_denorm = false; + int number = get_nibble_from_character(next_char); + for (int i = 0; i < 4; ++i, number <<= 1) { + uint_type write_bit = (number & 0x8) ? 0x1 : 0x0; + if (bits_written) { + // If we are here the bits represented belong in the fractional + // part of the float, and we have to adjust the exponent accordingly. + fraction = static_cast( + fraction | + static_cast( + write_bit << (HF::top_bit_left_shift - fraction_index++))); + exponent = static_cast(exponent + 1); + } + bits_written |= write_bit != 0; + } + } else { + // We have not found our exponent yet, so we have to fail. + is.setstate(std::ios::failbit); + return is; + } + is.get(); + next_char = is.peek(); + } + bits_written = false; + while (seen_dot && !seen_p) { + // Handle only fractional parts now. + if (next_char == 'p') { + seen_p = true; + } else if (::isxdigit(next_char)) { + int number = get_nibble_from_character(next_char); + for (int i = 0; i < 4; ++i, number <<= 1) { + uint_type write_bit = (number & 0x8) ? 0x01 : 0x00; + bits_written |= write_bit != 0; + if (is_denorm && !bits_written) { + // Handle modifying the exponent here this way we can handle + // an arbitrary number of hex values without overflowing our + // integer. + exponent = static_cast(exponent - 1); + } else { + fraction = static_cast( + fraction | + static_cast( + write_bit << (HF::top_bit_left_shift - fraction_index++))); + } + } + } else { + // We still have not found our 'p' exponent yet, so this is not a valid + // hex-float. + is.setstate(std::ios::failbit); + return is; + } + is.get(); + next_char = is.peek(); + } + + bool seen_sign = false; + int8_t exponent_sign = 1; + int_type written_exponent = 0; + while (true) { + if ((next_char == '-' || next_char == '+')) { + if (seen_sign) { + is.setstate(std::ios::failbit); + return is; + } + seen_sign = true; + exponent_sign = (next_char == '-') ? -1 : 1; + } else if (::isdigit(next_char)) { + // Hex-floats express their exponent as decimal. + written_exponent = static_cast(written_exponent * 10); + written_exponent = + static_cast(written_exponent + (next_char - '0')); + } else { + break; + } + is.get(); + next_char = is.peek(); + } + + written_exponent = static_cast(written_exponent * exponent_sign); + exponent = static_cast(exponent + written_exponent); + + bool is_zero = is_denorm && (fraction == 0); + if (is_denorm && !is_zero) { + fraction = static_cast(fraction << 1); + exponent = static_cast(exponent - 1); + } else if (is_zero) { + exponent = 0; + } + + if (exponent <= 0 && !is_zero) { + fraction = static_cast(fraction >> 1); + fraction |= static_cast(1) << HF::top_bit_left_shift; + } + + fraction = (fraction >> HF::fraction_right_shift) & HF::fraction_encode_mask; + + const int_type max_exponent = + SetBits::get; + + // Handle actual denorm numbers + while (exponent < 0 && !is_zero) { + fraction = static_cast(fraction >> 1); + exponent = static_cast(exponent + 1); + + fraction &= HF::fraction_encode_mask; + if (fraction == 0) { + // We have underflowed our fraction. We should clamp to zero. + is_zero = true; + exponent = 0; + } + } + + // We have overflowed so we should be inf/-inf. + if (exponent > max_exponent) { + exponent = max_exponent; + fraction = 0; + } + + uint_type output_bits = static_cast( + static_cast(negate_value ? 1 : 0) << HF::top_bit_left_shift); + output_bits |= fraction; + + uint_type shifted_exponent = static_cast( + static_cast(exponent << HF::exponent_left_shift) & + HF::exponent_mask); + output_bits |= shifted_exponent; + + T output_float = spvutils::BitwiseCast(output_bits); + value.set_value(output_float); + + return is; +} + +// Writes a FloatProxy value to a stream. +// Zero and normal numbers are printed in the usual notation, but with +// enough digits to fully reproduce the value. Other values (subnormal, +// NaN, and infinity) are printed as a hex float. +template +std::ostream& operator<<(std::ostream& os, const FloatProxy& value) { + auto float_val = value.getAsFloat(); + switch (std::fpclassify(float_val)) { + case FP_ZERO: + case FP_NORMAL: { + auto saved_precision = os.precision(); + os.precision(std::numeric_limits::digits10); + os << float_val; + os.precision(saved_precision); + } break; + default: + os << HexFloat>(value); + break; + } + return os; +} + +template <> +inline std::ostream& operator<<(std::ostream& os, + const FloatProxy& value) { + os << HexFloat>(value); + return os; +} +} + +#endif // LIBSPIRV_UTIL_HEX_FLOAT_H_ diff --git a/android/armeabi-v7a/include/glslang/SPIRV/spirv.hpp b/android/armeabi-v7a/include/glslang/SPIRV/spirv.hpp new file mode 100644 index 00000000..dae36cf2 --- /dev/null +++ b/android/armeabi-v7a/include/glslang/SPIRV/spirv.hpp @@ -0,0 +1,2114 @@ +// Copyright (c) 2014-2020 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and/or associated documentation files (the "Materials"), +// to deal in the Materials without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Materials, and to permit persons to whom the +// Materials are furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +// IN THE MATERIALS. + +// This header is automatically generated by the same tool that creates +// the Binary Section of the SPIR-V specification. + +// Enumeration tokens for SPIR-V, in various styles: +// C, C++, C++11, JSON, Lua, Python, C#, D +// +// - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL +// - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL +// - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL +// - Lua will use tables, e.g.: spv.SourceLanguage.GLSL +// - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] +// - C# will use enum classes in the Specification class located in the "Spv" namespace, +// e.g.: Spv.Specification.SourceLanguage.GLSL +// - D will have tokens under the "spv" module, e.g: spv.SourceLanguage.GLSL +// +// Some tokens act like mask values, which can be OR'd together, +// while others are mutually exclusive. The mask-like ones have +// "Mask" in their name, and a parallel enum that has the shift +// amount (1 << x) for each corresponding enumerant. + +#ifndef spirv_HPP +#define spirv_HPP + +namespace spv { + +typedef unsigned int Id; + +#define SPV_VERSION 0x10500 +#define SPV_REVISION 3 + +static const unsigned int MagicNumber = 0x07230203; +static const unsigned int Version = 0x00010500; +static const unsigned int Revision = 3; +static const unsigned int OpCodeMask = 0xffff; +static const unsigned int WordCountShift = 16; + +enum SourceLanguage { + SourceLanguageUnknown = 0, + SourceLanguageESSL = 1, + SourceLanguageGLSL = 2, + SourceLanguageOpenCL_C = 3, + SourceLanguageOpenCL_CPP = 4, + SourceLanguageHLSL = 5, + SourceLanguageMax = 0x7fffffff, +}; + +enum ExecutionModel { + ExecutionModelVertex = 0, + ExecutionModelTessellationControl = 1, + ExecutionModelTessellationEvaluation = 2, + ExecutionModelGeometry = 3, + ExecutionModelFragment = 4, + ExecutionModelGLCompute = 5, + ExecutionModelKernel = 6, + ExecutionModelTaskNV = 5267, + ExecutionModelMeshNV = 5268, + ExecutionModelRayGenerationKHR = 5313, + ExecutionModelRayGenerationNV = 5313, + ExecutionModelIntersectionKHR = 5314, + ExecutionModelIntersectionNV = 5314, + ExecutionModelAnyHitKHR = 5315, + ExecutionModelAnyHitNV = 5315, + ExecutionModelClosestHitKHR = 5316, + ExecutionModelClosestHitNV = 5316, + ExecutionModelMissKHR = 5317, + ExecutionModelMissNV = 5317, + ExecutionModelCallableKHR = 5318, + ExecutionModelCallableNV = 5318, + ExecutionModelMax = 0x7fffffff, +}; + +enum AddressingModel { + AddressingModelLogical = 0, + AddressingModelPhysical32 = 1, + AddressingModelPhysical64 = 2, + AddressingModelPhysicalStorageBuffer64 = 5348, + AddressingModelPhysicalStorageBuffer64EXT = 5348, + AddressingModelMax = 0x7fffffff, +}; + +enum MemoryModel { + MemoryModelSimple = 0, + MemoryModelGLSL450 = 1, + MemoryModelOpenCL = 2, + MemoryModelVulkan = 3, + MemoryModelVulkanKHR = 3, + MemoryModelMax = 0x7fffffff, +}; + +enum ExecutionMode { + ExecutionModeInvocations = 0, + ExecutionModeSpacingEqual = 1, + ExecutionModeSpacingFractionalEven = 2, + ExecutionModeSpacingFractionalOdd = 3, + ExecutionModeVertexOrderCw = 4, + ExecutionModeVertexOrderCcw = 5, + ExecutionModePixelCenterInteger = 6, + ExecutionModeOriginUpperLeft = 7, + ExecutionModeOriginLowerLeft = 8, + ExecutionModeEarlyFragmentTests = 9, + ExecutionModePointMode = 10, + ExecutionModeXfb = 11, + ExecutionModeDepthReplacing = 12, + ExecutionModeDepthGreater = 14, + ExecutionModeDepthLess = 15, + ExecutionModeDepthUnchanged = 16, + ExecutionModeLocalSize = 17, + ExecutionModeLocalSizeHint = 18, + ExecutionModeInputPoints = 19, + ExecutionModeInputLines = 20, + ExecutionModeInputLinesAdjacency = 21, + ExecutionModeTriangles = 22, + ExecutionModeInputTrianglesAdjacency = 23, + ExecutionModeQuads = 24, + ExecutionModeIsolines = 25, + ExecutionModeOutputVertices = 26, + ExecutionModeOutputPoints = 27, + ExecutionModeOutputLineStrip = 28, + ExecutionModeOutputTriangleStrip = 29, + ExecutionModeVecTypeHint = 30, + ExecutionModeContractionOff = 31, + ExecutionModeInitializer = 33, + ExecutionModeFinalizer = 34, + ExecutionModeSubgroupSize = 35, + ExecutionModeSubgroupsPerWorkgroup = 36, + ExecutionModeSubgroupsPerWorkgroupId = 37, + ExecutionModeLocalSizeId = 38, + ExecutionModeLocalSizeHintId = 39, + ExecutionModePostDepthCoverage = 4446, + ExecutionModeDenormPreserve = 4459, + ExecutionModeDenormFlushToZero = 4460, + ExecutionModeSignedZeroInfNanPreserve = 4461, + ExecutionModeRoundingModeRTE = 4462, + ExecutionModeRoundingModeRTZ = 4463, + ExecutionModeStencilRefReplacingEXT = 5027, + ExecutionModeOutputLinesNV = 5269, + ExecutionModeOutputPrimitivesNV = 5270, + ExecutionModeDerivativeGroupQuadsNV = 5289, + ExecutionModeDerivativeGroupLinearNV = 5290, + ExecutionModeOutputTrianglesNV = 5298, + ExecutionModePixelInterlockOrderedEXT = 5366, + ExecutionModePixelInterlockUnorderedEXT = 5367, + ExecutionModeSampleInterlockOrderedEXT = 5368, + ExecutionModeSampleInterlockUnorderedEXT = 5369, + ExecutionModeShadingRateInterlockOrderedEXT = 5370, + ExecutionModeShadingRateInterlockUnorderedEXT = 5371, + ExecutionModeMax = 0x7fffffff, +}; + +enum StorageClass { + StorageClassUniformConstant = 0, + StorageClassInput = 1, + StorageClassUniform = 2, + StorageClassOutput = 3, + StorageClassWorkgroup = 4, + StorageClassCrossWorkgroup = 5, + StorageClassPrivate = 6, + StorageClassFunction = 7, + StorageClassGeneric = 8, + StorageClassPushConstant = 9, + StorageClassAtomicCounter = 10, + StorageClassImage = 11, + StorageClassStorageBuffer = 12, + StorageClassCallableDataKHR = 5328, + StorageClassCallableDataNV = 5328, + StorageClassIncomingCallableDataKHR = 5329, + StorageClassIncomingCallableDataNV = 5329, + StorageClassRayPayloadKHR = 5338, + StorageClassRayPayloadNV = 5338, + StorageClassHitAttributeKHR = 5339, + StorageClassHitAttributeNV = 5339, + StorageClassIncomingRayPayloadKHR = 5342, + StorageClassIncomingRayPayloadNV = 5342, + StorageClassShaderRecordBufferKHR = 5343, + StorageClassShaderRecordBufferNV = 5343, + StorageClassPhysicalStorageBuffer = 5349, + StorageClassPhysicalStorageBufferEXT = 5349, + StorageClassMax = 0x7fffffff, +}; + +enum Dim { + Dim1D = 0, + Dim2D = 1, + Dim3D = 2, + DimCube = 3, + DimRect = 4, + DimBuffer = 5, + DimSubpassData = 6, + DimMax = 0x7fffffff, +}; + +enum SamplerAddressingMode { + SamplerAddressingModeNone = 0, + SamplerAddressingModeClampToEdge = 1, + SamplerAddressingModeClamp = 2, + SamplerAddressingModeRepeat = 3, + SamplerAddressingModeRepeatMirrored = 4, + SamplerAddressingModeMax = 0x7fffffff, +}; + +enum SamplerFilterMode { + SamplerFilterModeNearest = 0, + SamplerFilterModeLinear = 1, + SamplerFilterModeMax = 0x7fffffff, +}; + +enum ImageFormat { + ImageFormatUnknown = 0, + ImageFormatRgba32f = 1, + ImageFormatRgba16f = 2, + ImageFormatR32f = 3, + ImageFormatRgba8 = 4, + ImageFormatRgba8Snorm = 5, + ImageFormatRg32f = 6, + ImageFormatRg16f = 7, + ImageFormatR11fG11fB10f = 8, + ImageFormatR16f = 9, + ImageFormatRgba16 = 10, + ImageFormatRgb10A2 = 11, + ImageFormatRg16 = 12, + ImageFormatRg8 = 13, + ImageFormatR16 = 14, + ImageFormatR8 = 15, + ImageFormatRgba16Snorm = 16, + ImageFormatRg16Snorm = 17, + ImageFormatRg8Snorm = 18, + ImageFormatR16Snorm = 19, + ImageFormatR8Snorm = 20, + ImageFormatRgba32i = 21, + ImageFormatRgba16i = 22, + ImageFormatRgba8i = 23, + ImageFormatR32i = 24, + ImageFormatRg32i = 25, + ImageFormatRg16i = 26, + ImageFormatRg8i = 27, + ImageFormatR16i = 28, + ImageFormatR8i = 29, + ImageFormatRgba32ui = 30, + ImageFormatRgba16ui = 31, + ImageFormatRgba8ui = 32, + ImageFormatR32ui = 33, + ImageFormatRgb10a2ui = 34, + ImageFormatRg32ui = 35, + ImageFormatRg16ui = 36, + ImageFormatRg8ui = 37, + ImageFormatR16ui = 38, + ImageFormatR8ui = 39, + ImageFormatMax = 0x7fffffff, +}; + +enum ImageChannelOrder { + ImageChannelOrderR = 0, + ImageChannelOrderA = 1, + ImageChannelOrderRG = 2, + ImageChannelOrderRA = 3, + ImageChannelOrderRGB = 4, + ImageChannelOrderRGBA = 5, + ImageChannelOrderBGRA = 6, + ImageChannelOrderARGB = 7, + ImageChannelOrderIntensity = 8, + ImageChannelOrderLuminance = 9, + ImageChannelOrderRx = 10, + ImageChannelOrderRGx = 11, + ImageChannelOrderRGBx = 12, + ImageChannelOrderDepth = 13, + ImageChannelOrderDepthStencil = 14, + ImageChannelOrdersRGB = 15, + ImageChannelOrdersRGBx = 16, + ImageChannelOrdersRGBA = 17, + ImageChannelOrdersBGRA = 18, + ImageChannelOrderABGR = 19, + ImageChannelOrderMax = 0x7fffffff, +}; + +enum ImageChannelDataType { + ImageChannelDataTypeSnormInt8 = 0, + ImageChannelDataTypeSnormInt16 = 1, + ImageChannelDataTypeUnormInt8 = 2, + ImageChannelDataTypeUnormInt16 = 3, + ImageChannelDataTypeUnormShort565 = 4, + ImageChannelDataTypeUnormShort555 = 5, + ImageChannelDataTypeUnormInt101010 = 6, + ImageChannelDataTypeSignedInt8 = 7, + ImageChannelDataTypeSignedInt16 = 8, + ImageChannelDataTypeSignedInt32 = 9, + ImageChannelDataTypeUnsignedInt8 = 10, + ImageChannelDataTypeUnsignedInt16 = 11, + ImageChannelDataTypeUnsignedInt32 = 12, + ImageChannelDataTypeHalfFloat = 13, + ImageChannelDataTypeFloat = 14, + ImageChannelDataTypeUnormInt24 = 15, + ImageChannelDataTypeUnormInt101010_2 = 16, + ImageChannelDataTypeMax = 0x7fffffff, +}; + +enum ImageOperandsShift { + ImageOperandsBiasShift = 0, + ImageOperandsLodShift = 1, + ImageOperandsGradShift = 2, + ImageOperandsConstOffsetShift = 3, + ImageOperandsOffsetShift = 4, + ImageOperandsConstOffsetsShift = 5, + ImageOperandsSampleShift = 6, + ImageOperandsMinLodShift = 7, + ImageOperandsMakeTexelAvailableShift = 8, + ImageOperandsMakeTexelAvailableKHRShift = 8, + ImageOperandsMakeTexelVisibleShift = 9, + ImageOperandsMakeTexelVisibleKHRShift = 9, + ImageOperandsNonPrivateTexelShift = 10, + ImageOperandsNonPrivateTexelKHRShift = 10, + ImageOperandsVolatileTexelShift = 11, + ImageOperandsVolatileTexelKHRShift = 11, + ImageOperandsSignExtendShift = 12, + ImageOperandsZeroExtendShift = 13, + ImageOperandsMax = 0x7fffffff, +}; + +enum ImageOperandsMask { + ImageOperandsMaskNone = 0, + ImageOperandsBiasMask = 0x00000001, + ImageOperandsLodMask = 0x00000002, + ImageOperandsGradMask = 0x00000004, + ImageOperandsConstOffsetMask = 0x00000008, + ImageOperandsOffsetMask = 0x00000010, + ImageOperandsConstOffsetsMask = 0x00000020, + ImageOperandsSampleMask = 0x00000040, + ImageOperandsMinLodMask = 0x00000080, + ImageOperandsMakeTexelAvailableMask = 0x00000100, + ImageOperandsMakeTexelAvailableKHRMask = 0x00000100, + ImageOperandsMakeTexelVisibleMask = 0x00000200, + ImageOperandsMakeTexelVisibleKHRMask = 0x00000200, + ImageOperandsNonPrivateTexelMask = 0x00000400, + ImageOperandsNonPrivateTexelKHRMask = 0x00000400, + ImageOperandsVolatileTexelMask = 0x00000800, + ImageOperandsVolatileTexelKHRMask = 0x00000800, + ImageOperandsSignExtendMask = 0x00001000, + ImageOperandsZeroExtendMask = 0x00002000, +}; + +enum FPFastMathModeShift { + FPFastMathModeNotNaNShift = 0, + FPFastMathModeNotInfShift = 1, + FPFastMathModeNSZShift = 2, + FPFastMathModeAllowRecipShift = 3, + FPFastMathModeFastShift = 4, + FPFastMathModeMax = 0x7fffffff, +}; + +enum FPFastMathModeMask { + FPFastMathModeMaskNone = 0, + FPFastMathModeNotNaNMask = 0x00000001, + FPFastMathModeNotInfMask = 0x00000002, + FPFastMathModeNSZMask = 0x00000004, + FPFastMathModeAllowRecipMask = 0x00000008, + FPFastMathModeFastMask = 0x00000010, +}; + +enum FPRoundingMode { + FPRoundingModeRTE = 0, + FPRoundingModeRTZ = 1, + FPRoundingModeRTP = 2, + FPRoundingModeRTN = 3, + FPRoundingModeMax = 0x7fffffff, +}; + +enum LinkageType { + LinkageTypeExport = 0, + LinkageTypeImport = 1, + LinkageTypeMax = 0x7fffffff, +}; + +enum AccessQualifier { + AccessQualifierReadOnly = 0, + AccessQualifierWriteOnly = 1, + AccessQualifierReadWrite = 2, + AccessQualifierMax = 0x7fffffff, +}; + +enum FunctionParameterAttribute { + FunctionParameterAttributeZext = 0, + FunctionParameterAttributeSext = 1, + FunctionParameterAttributeByVal = 2, + FunctionParameterAttributeSret = 3, + FunctionParameterAttributeNoAlias = 4, + FunctionParameterAttributeNoCapture = 5, + FunctionParameterAttributeNoWrite = 6, + FunctionParameterAttributeNoReadWrite = 7, + FunctionParameterAttributeMax = 0x7fffffff, +}; + +enum Decoration { + DecorationRelaxedPrecision = 0, + DecorationSpecId = 1, + DecorationBlock = 2, + DecorationBufferBlock = 3, + DecorationRowMajor = 4, + DecorationColMajor = 5, + DecorationArrayStride = 6, + DecorationMatrixStride = 7, + DecorationGLSLShared = 8, + DecorationGLSLPacked = 9, + DecorationCPacked = 10, + DecorationBuiltIn = 11, + DecorationNoPerspective = 13, + DecorationFlat = 14, + DecorationPatch = 15, + DecorationCentroid = 16, + DecorationSample = 17, + DecorationInvariant = 18, + DecorationRestrict = 19, + DecorationAliased = 20, + DecorationVolatile = 21, + DecorationConstant = 22, + DecorationCoherent = 23, + DecorationNonWritable = 24, + DecorationNonReadable = 25, + DecorationUniform = 26, + DecorationUniformId = 27, + DecorationSaturatedConversion = 28, + DecorationStream = 29, + DecorationLocation = 30, + DecorationComponent = 31, + DecorationIndex = 32, + DecorationBinding = 33, + DecorationDescriptorSet = 34, + DecorationOffset = 35, + DecorationXfbBuffer = 36, + DecorationXfbStride = 37, + DecorationFuncParamAttr = 38, + DecorationFPRoundingMode = 39, + DecorationFPFastMathMode = 40, + DecorationLinkageAttributes = 41, + DecorationNoContraction = 42, + DecorationInputAttachmentIndex = 43, + DecorationAlignment = 44, + DecorationMaxByteOffset = 45, + DecorationAlignmentId = 46, + DecorationMaxByteOffsetId = 47, + DecorationNoSignedWrap = 4469, + DecorationNoUnsignedWrap = 4470, + DecorationExplicitInterpAMD = 4999, + DecorationOverrideCoverageNV = 5248, + DecorationPassthroughNV = 5250, + DecorationViewportRelativeNV = 5252, + DecorationSecondaryViewportRelativeNV = 5256, + DecorationPerPrimitiveNV = 5271, + DecorationPerViewNV = 5272, + DecorationPerTaskNV = 5273, + DecorationPerVertexNV = 5285, + DecorationNonUniform = 5300, + DecorationNonUniformEXT = 5300, + DecorationRestrictPointer = 5355, + DecorationRestrictPointerEXT = 5355, + DecorationAliasedPointer = 5356, + DecorationAliasedPointerEXT = 5356, + DecorationCounterBuffer = 5634, + DecorationHlslCounterBufferGOOGLE = 5634, + DecorationHlslSemanticGOOGLE = 5635, + DecorationUserSemantic = 5635, + DecorationUserTypeGOOGLE = 5636, + DecorationMax = 0x7fffffff, +}; + +enum BuiltIn { + BuiltInPosition = 0, + BuiltInPointSize = 1, + BuiltInClipDistance = 3, + BuiltInCullDistance = 4, + BuiltInVertexId = 5, + BuiltInInstanceId = 6, + BuiltInPrimitiveId = 7, + BuiltInInvocationId = 8, + BuiltInLayer = 9, + BuiltInViewportIndex = 10, + BuiltInTessLevelOuter = 11, + BuiltInTessLevelInner = 12, + BuiltInTessCoord = 13, + BuiltInPatchVertices = 14, + BuiltInFragCoord = 15, + BuiltInPointCoord = 16, + BuiltInFrontFacing = 17, + BuiltInSampleId = 18, + BuiltInSamplePosition = 19, + BuiltInSampleMask = 20, + BuiltInFragDepth = 22, + BuiltInHelperInvocation = 23, + BuiltInNumWorkgroups = 24, + BuiltInWorkgroupSize = 25, + BuiltInWorkgroupId = 26, + BuiltInLocalInvocationId = 27, + BuiltInGlobalInvocationId = 28, + BuiltInLocalInvocationIndex = 29, + BuiltInWorkDim = 30, + BuiltInGlobalSize = 31, + BuiltInEnqueuedWorkgroupSize = 32, + BuiltInGlobalOffset = 33, + BuiltInGlobalLinearId = 34, + BuiltInSubgroupSize = 36, + BuiltInSubgroupMaxSize = 37, + BuiltInNumSubgroups = 38, + BuiltInNumEnqueuedSubgroups = 39, + BuiltInSubgroupId = 40, + BuiltInSubgroupLocalInvocationId = 41, + BuiltInVertexIndex = 42, + BuiltInInstanceIndex = 43, + BuiltInSubgroupEqMask = 4416, + BuiltInSubgroupEqMaskKHR = 4416, + BuiltInSubgroupGeMask = 4417, + BuiltInSubgroupGeMaskKHR = 4417, + BuiltInSubgroupGtMask = 4418, + BuiltInSubgroupGtMaskKHR = 4418, + BuiltInSubgroupLeMask = 4419, + BuiltInSubgroupLeMaskKHR = 4419, + BuiltInSubgroupLtMask = 4420, + BuiltInSubgroupLtMaskKHR = 4420, + BuiltInBaseVertex = 4424, + BuiltInBaseInstance = 4425, + BuiltInDrawIndex = 4426, + BuiltInDeviceIndex = 4438, + BuiltInViewIndex = 4440, + BuiltInBaryCoordNoPerspAMD = 4992, + BuiltInBaryCoordNoPerspCentroidAMD = 4993, + BuiltInBaryCoordNoPerspSampleAMD = 4994, + BuiltInBaryCoordSmoothAMD = 4995, + BuiltInBaryCoordSmoothCentroidAMD = 4996, + BuiltInBaryCoordSmoothSampleAMD = 4997, + BuiltInBaryCoordPullModelAMD = 4998, + BuiltInFragStencilRefEXT = 5014, + BuiltInViewportMaskNV = 5253, + BuiltInSecondaryPositionNV = 5257, + BuiltInSecondaryViewportMaskNV = 5258, + BuiltInPositionPerViewNV = 5261, + BuiltInViewportMaskPerViewNV = 5262, + BuiltInFullyCoveredEXT = 5264, + BuiltInTaskCountNV = 5274, + BuiltInPrimitiveCountNV = 5275, + BuiltInPrimitiveIndicesNV = 5276, + BuiltInClipDistancePerViewNV = 5277, + BuiltInCullDistancePerViewNV = 5278, + BuiltInLayerPerViewNV = 5279, + BuiltInMeshViewCountNV = 5280, + BuiltInMeshViewIndicesNV = 5281, + BuiltInBaryCoordNV = 5286, + BuiltInBaryCoordNoPerspNV = 5287, + BuiltInFragSizeEXT = 5292, + BuiltInFragmentSizeNV = 5292, + BuiltInFragInvocationCountEXT = 5293, + BuiltInInvocationsPerPixelNV = 5293, + BuiltInLaunchIdKHR = 5319, + BuiltInLaunchIdNV = 5319, + BuiltInLaunchSizeKHR = 5320, + BuiltInLaunchSizeNV = 5320, + BuiltInWorldRayOriginKHR = 5321, + BuiltInWorldRayOriginNV = 5321, + BuiltInWorldRayDirectionKHR = 5322, + BuiltInWorldRayDirectionNV = 5322, + BuiltInObjectRayOriginKHR = 5323, + BuiltInObjectRayOriginNV = 5323, + BuiltInObjectRayDirectionKHR = 5324, + BuiltInObjectRayDirectionNV = 5324, + BuiltInRayTminKHR = 5325, + BuiltInRayTminNV = 5325, + BuiltInRayTmaxKHR = 5326, + BuiltInRayTmaxNV = 5326, + BuiltInInstanceCustomIndexKHR = 5327, + BuiltInInstanceCustomIndexNV = 5327, + BuiltInObjectToWorldKHR = 5330, + BuiltInObjectToWorldNV = 5330, + BuiltInWorldToObjectKHR = 5331, + BuiltInWorldToObjectNV = 5331, + BuiltInHitTKHR = 5332, + BuiltInHitTNV = 5332, + BuiltInHitKindKHR = 5333, + BuiltInHitKindNV = 5333, + BuiltInIncomingRayFlagsKHR = 5351, + BuiltInIncomingRayFlagsNV = 5351, + BuiltInRayGeometryIndexKHR = 5352, + BuiltInWarpsPerSMNV = 5374, + BuiltInSMCountNV = 5375, + BuiltInWarpIDNV = 5376, + BuiltInSMIDNV = 5377, + BuiltInMax = 0x7fffffff, +}; + +enum SelectionControlShift { + SelectionControlFlattenShift = 0, + SelectionControlDontFlattenShift = 1, + SelectionControlMax = 0x7fffffff, +}; + +enum SelectionControlMask { + SelectionControlMaskNone = 0, + SelectionControlFlattenMask = 0x00000001, + SelectionControlDontFlattenMask = 0x00000002, +}; + +enum LoopControlShift { + LoopControlUnrollShift = 0, + LoopControlDontUnrollShift = 1, + LoopControlDependencyInfiniteShift = 2, + LoopControlDependencyLengthShift = 3, + LoopControlMinIterationsShift = 4, + LoopControlMaxIterationsShift = 5, + LoopControlIterationMultipleShift = 6, + LoopControlPeelCountShift = 7, + LoopControlPartialCountShift = 8, + LoopControlMax = 0x7fffffff, +}; + +enum LoopControlMask { + LoopControlMaskNone = 0, + LoopControlUnrollMask = 0x00000001, + LoopControlDontUnrollMask = 0x00000002, + LoopControlDependencyInfiniteMask = 0x00000004, + LoopControlDependencyLengthMask = 0x00000008, + LoopControlMinIterationsMask = 0x00000010, + LoopControlMaxIterationsMask = 0x00000020, + LoopControlIterationMultipleMask = 0x00000040, + LoopControlPeelCountMask = 0x00000080, + LoopControlPartialCountMask = 0x00000100, +}; + +enum FunctionControlShift { + FunctionControlInlineShift = 0, + FunctionControlDontInlineShift = 1, + FunctionControlPureShift = 2, + FunctionControlConstShift = 3, + FunctionControlMax = 0x7fffffff, +}; + +enum FunctionControlMask { + FunctionControlMaskNone = 0, + FunctionControlInlineMask = 0x00000001, + FunctionControlDontInlineMask = 0x00000002, + FunctionControlPureMask = 0x00000004, + FunctionControlConstMask = 0x00000008, +}; + +enum MemorySemanticsShift { + MemorySemanticsAcquireShift = 1, + MemorySemanticsReleaseShift = 2, + MemorySemanticsAcquireReleaseShift = 3, + MemorySemanticsSequentiallyConsistentShift = 4, + MemorySemanticsUniformMemoryShift = 6, + MemorySemanticsSubgroupMemoryShift = 7, + MemorySemanticsWorkgroupMemoryShift = 8, + MemorySemanticsCrossWorkgroupMemoryShift = 9, + MemorySemanticsAtomicCounterMemoryShift = 10, + MemorySemanticsImageMemoryShift = 11, + MemorySemanticsOutputMemoryShift = 12, + MemorySemanticsOutputMemoryKHRShift = 12, + MemorySemanticsMakeAvailableShift = 13, + MemorySemanticsMakeAvailableKHRShift = 13, + MemorySemanticsMakeVisibleShift = 14, + MemorySemanticsMakeVisibleKHRShift = 14, + MemorySemanticsVolatileShift = 15, + MemorySemanticsMax = 0x7fffffff, +}; + +enum MemorySemanticsMask { + MemorySemanticsMaskNone = 0, + MemorySemanticsAcquireMask = 0x00000002, + MemorySemanticsReleaseMask = 0x00000004, + MemorySemanticsAcquireReleaseMask = 0x00000008, + MemorySemanticsSequentiallyConsistentMask = 0x00000010, + MemorySemanticsUniformMemoryMask = 0x00000040, + MemorySemanticsSubgroupMemoryMask = 0x00000080, + MemorySemanticsWorkgroupMemoryMask = 0x00000100, + MemorySemanticsCrossWorkgroupMemoryMask = 0x00000200, + MemorySemanticsAtomicCounterMemoryMask = 0x00000400, + MemorySemanticsImageMemoryMask = 0x00000800, + MemorySemanticsOutputMemoryMask = 0x00001000, + MemorySemanticsOutputMemoryKHRMask = 0x00001000, + MemorySemanticsMakeAvailableMask = 0x00002000, + MemorySemanticsMakeAvailableKHRMask = 0x00002000, + MemorySemanticsMakeVisibleMask = 0x00004000, + MemorySemanticsMakeVisibleKHRMask = 0x00004000, + MemorySemanticsVolatileMask = 0x00008000, +}; + +enum MemoryAccessShift { + MemoryAccessVolatileShift = 0, + MemoryAccessAlignedShift = 1, + MemoryAccessNontemporalShift = 2, + MemoryAccessMakePointerAvailableShift = 3, + MemoryAccessMakePointerAvailableKHRShift = 3, + MemoryAccessMakePointerVisibleShift = 4, + MemoryAccessMakePointerVisibleKHRShift = 4, + MemoryAccessNonPrivatePointerShift = 5, + MemoryAccessNonPrivatePointerKHRShift = 5, + MemoryAccessMax = 0x7fffffff, +}; + +enum MemoryAccessMask { + MemoryAccessMaskNone = 0, + MemoryAccessVolatileMask = 0x00000001, + MemoryAccessAlignedMask = 0x00000002, + MemoryAccessNontemporalMask = 0x00000004, + MemoryAccessMakePointerAvailableMask = 0x00000008, + MemoryAccessMakePointerAvailableKHRMask = 0x00000008, + MemoryAccessMakePointerVisibleMask = 0x00000010, + MemoryAccessMakePointerVisibleKHRMask = 0x00000010, + MemoryAccessNonPrivatePointerMask = 0x00000020, + MemoryAccessNonPrivatePointerKHRMask = 0x00000020, +}; + +enum Scope { + ScopeCrossDevice = 0, + ScopeDevice = 1, + ScopeWorkgroup = 2, + ScopeSubgroup = 3, + ScopeInvocation = 4, + ScopeQueueFamily = 5, + ScopeQueueFamilyKHR = 5, + ScopeShaderCallKHR = 6, + ScopeMax = 0x7fffffff, +}; + +enum GroupOperation { + GroupOperationReduce = 0, + GroupOperationInclusiveScan = 1, + GroupOperationExclusiveScan = 2, + GroupOperationClusteredReduce = 3, + GroupOperationPartitionedReduceNV = 6, + GroupOperationPartitionedInclusiveScanNV = 7, + GroupOperationPartitionedExclusiveScanNV = 8, + GroupOperationMax = 0x7fffffff, +}; + +enum KernelEnqueueFlags { + KernelEnqueueFlagsNoWait = 0, + KernelEnqueueFlagsWaitKernel = 1, + KernelEnqueueFlagsWaitWorkGroup = 2, + KernelEnqueueFlagsMax = 0x7fffffff, +}; + +enum KernelProfilingInfoShift { + KernelProfilingInfoCmdExecTimeShift = 0, + KernelProfilingInfoMax = 0x7fffffff, +}; + +enum KernelProfilingInfoMask { + KernelProfilingInfoMaskNone = 0, + KernelProfilingInfoCmdExecTimeMask = 0x00000001, +}; + +enum Capability { + CapabilityMatrix = 0, + CapabilityShader = 1, + CapabilityGeometry = 2, + CapabilityTessellation = 3, + CapabilityAddresses = 4, + CapabilityLinkage = 5, + CapabilityKernel = 6, + CapabilityVector16 = 7, + CapabilityFloat16Buffer = 8, + CapabilityFloat16 = 9, + CapabilityFloat64 = 10, + CapabilityInt64 = 11, + CapabilityInt64Atomics = 12, + CapabilityImageBasic = 13, + CapabilityImageReadWrite = 14, + CapabilityImageMipmap = 15, + CapabilityPipes = 17, + CapabilityGroups = 18, + CapabilityDeviceEnqueue = 19, + CapabilityLiteralSampler = 20, + CapabilityAtomicStorage = 21, + CapabilityInt16 = 22, + CapabilityTessellationPointSize = 23, + CapabilityGeometryPointSize = 24, + CapabilityImageGatherExtended = 25, + CapabilityStorageImageMultisample = 27, + CapabilityUniformBufferArrayDynamicIndexing = 28, + CapabilitySampledImageArrayDynamicIndexing = 29, + CapabilityStorageBufferArrayDynamicIndexing = 30, + CapabilityStorageImageArrayDynamicIndexing = 31, + CapabilityClipDistance = 32, + CapabilityCullDistance = 33, + CapabilityImageCubeArray = 34, + CapabilitySampleRateShading = 35, + CapabilityImageRect = 36, + CapabilitySampledRect = 37, + CapabilityGenericPointer = 38, + CapabilityInt8 = 39, + CapabilityInputAttachment = 40, + CapabilitySparseResidency = 41, + CapabilityMinLod = 42, + CapabilitySampled1D = 43, + CapabilityImage1D = 44, + CapabilitySampledCubeArray = 45, + CapabilitySampledBuffer = 46, + CapabilityImageBuffer = 47, + CapabilityImageMSArray = 48, + CapabilityStorageImageExtendedFormats = 49, + CapabilityImageQuery = 50, + CapabilityDerivativeControl = 51, + CapabilityInterpolationFunction = 52, + CapabilityTransformFeedback = 53, + CapabilityGeometryStreams = 54, + CapabilityStorageImageReadWithoutFormat = 55, + CapabilityStorageImageWriteWithoutFormat = 56, + CapabilityMultiViewport = 57, + CapabilitySubgroupDispatch = 58, + CapabilityNamedBarrier = 59, + CapabilityPipeStorage = 60, + CapabilityGroupNonUniform = 61, + CapabilityGroupNonUniformVote = 62, + CapabilityGroupNonUniformArithmetic = 63, + CapabilityGroupNonUniformBallot = 64, + CapabilityGroupNonUniformShuffle = 65, + CapabilityGroupNonUniformShuffleRelative = 66, + CapabilityGroupNonUniformClustered = 67, + CapabilityGroupNonUniformQuad = 68, + CapabilityShaderLayer = 69, + CapabilityShaderViewportIndex = 70, + CapabilitySubgroupBallotKHR = 4423, + CapabilityDrawParameters = 4427, + CapabilitySubgroupVoteKHR = 4431, + CapabilityStorageBuffer16BitAccess = 4433, + CapabilityStorageUniformBufferBlock16 = 4433, + CapabilityStorageUniform16 = 4434, + CapabilityUniformAndStorageBuffer16BitAccess = 4434, + CapabilityStoragePushConstant16 = 4435, + CapabilityStorageInputOutput16 = 4436, + CapabilityDeviceGroup = 4437, + CapabilityMultiView = 4439, + CapabilityVariablePointersStorageBuffer = 4441, + CapabilityVariablePointers = 4442, + CapabilityAtomicStorageOps = 4445, + CapabilitySampleMaskPostDepthCoverage = 4447, + CapabilityStorageBuffer8BitAccess = 4448, + CapabilityUniformAndStorageBuffer8BitAccess = 4449, + CapabilityStoragePushConstant8 = 4450, + CapabilityDenormPreserve = 4464, + CapabilityDenormFlushToZero = 4465, + CapabilitySignedZeroInfNanPreserve = 4466, + CapabilityRoundingModeRTE = 4467, + CapabilityRoundingModeRTZ = 4468, + CapabilityRayQueryProvisionalKHR = 4471, + CapabilityRayTraversalPrimitiveCullingProvisionalKHR = 4478, + CapabilityFloat16ImageAMD = 5008, + CapabilityImageGatherBiasLodAMD = 5009, + CapabilityFragmentMaskAMD = 5010, + CapabilityStencilExportEXT = 5013, + CapabilityImageReadWriteLodAMD = 5015, + CapabilityShaderClockKHR = 5055, + CapabilitySampleMaskOverrideCoverageNV = 5249, + CapabilityGeometryShaderPassthroughNV = 5251, + CapabilityShaderViewportIndexLayerEXT = 5254, + CapabilityShaderViewportIndexLayerNV = 5254, + CapabilityShaderViewportMaskNV = 5255, + CapabilityShaderStereoViewNV = 5259, + CapabilityPerViewAttributesNV = 5260, + CapabilityFragmentFullyCoveredEXT = 5265, + CapabilityMeshShadingNV = 5266, + CapabilityImageFootprintNV = 5282, + CapabilityFragmentBarycentricNV = 5284, + CapabilityComputeDerivativeGroupQuadsNV = 5288, + CapabilityFragmentDensityEXT = 5291, + CapabilityShadingRateNV = 5291, + CapabilityGroupNonUniformPartitionedNV = 5297, + CapabilityShaderNonUniform = 5301, + CapabilityShaderNonUniformEXT = 5301, + CapabilityRuntimeDescriptorArray = 5302, + CapabilityRuntimeDescriptorArrayEXT = 5302, + CapabilityInputAttachmentArrayDynamicIndexing = 5303, + CapabilityInputAttachmentArrayDynamicIndexingEXT = 5303, + CapabilityUniformTexelBufferArrayDynamicIndexing = 5304, + CapabilityUniformTexelBufferArrayDynamicIndexingEXT = 5304, + CapabilityStorageTexelBufferArrayDynamicIndexing = 5305, + CapabilityStorageTexelBufferArrayDynamicIndexingEXT = 5305, + CapabilityUniformBufferArrayNonUniformIndexing = 5306, + CapabilityUniformBufferArrayNonUniformIndexingEXT = 5306, + CapabilitySampledImageArrayNonUniformIndexing = 5307, + CapabilitySampledImageArrayNonUniformIndexingEXT = 5307, + CapabilityStorageBufferArrayNonUniformIndexing = 5308, + CapabilityStorageBufferArrayNonUniformIndexingEXT = 5308, + CapabilityStorageImageArrayNonUniformIndexing = 5309, + CapabilityStorageImageArrayNonUniformIndexingEXT = 5309, + CapabilityInputAttachmentArrayNonUniformIndexing = 5310, + CapabilityInputAttachmentArrayNonUniformIndexingEXT = 5310, + CapabilityUniformTexelBufferArrayNonUniformIndexing = 5311, + CapabilityUniformTexelBufferArrayNonUniformIndexingEXT = 5311, + CapabilityStorageTexelBufferArrayNonUniformIndexing = 5312, + CapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312, + CapabilityRayTracingNV = 5340, + CapabilityVulkanMemoryModel = 5345, + CapabilityVulkanMemoryModelKHR = 5345, + CapabilityVulkanMemoryModelDeviceScope = 5346, + CapabilityVulkanMemoryModelDeviceScopeKHR = 5346, + CapabilityPhysicalStorageBufferAddresses = 5347, + CapabilityPhysicalStorageBufferAddressesEXT = 5347, + CapabilityComputeDerivativeGroupLinearNV = 5350, + CapabilityRayTracingProvisionalKHR = 5353, + CapabilityCooperativeMatrixNV = 5357, + CapabilityFragmentShaderSampleInterlockEXT = 5363, + CapabilityFragmentShaderShadingRateInterlockEXT = 5372, + CapabilityShaderSMBuiltinsNV = 5373, + CapabilityFragmentShaderPixelInterlockEXT = 5378, + CapabilityDemoteToHelperInvocationEXT = 5379, + CapabilitySubgroupShuffleINTEL = 5568, + CapabilitySubgroupBufferBlockIOINTEL = 5569, + CapabilitySubgroupImageBlockIOINTEL = 5570, + CapabilitySubgroupImageMediaBlockIOINTEL = 5579, + CapabilityIntegerFunctions2INTEL = 5584, + CapabilitySubgroupAvcMotionEstimationINTEL = 5696, + CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697, + CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698, + CapabilityMax = 0x7fffffff, +}; + +enum RayFlagsShift { + RayFlagsOpaqueKHRShift = 0, + RayFlagsNoOpaqueKHRShift = 1, + RayFlagsTerminateOnFirstHitKHRShift = 2, + RayFlagsSkipClosestHitShaderKHRShift = 3, + RayFlagsCullBackFacingTrianglesKHRShift = 4, + RayFlagsCullFrontFacingTrianglesKHRShift = 5, + RayFlagsCullOpaqueKHRShift = 6, + RayFlagsCullNoOpaqueKHRShift = 7, + RayFlagsSkipTrianglesKHRShift = 8, + RayFlagsSkipAABBsKHRShift = 9, + RayFlagsMax = 0x7fffffff, +}; + +enum RayFlagsMask { + RayFlagsMaskNone = 0, + RayFlagsOpaqueKHRMask = 0x00000001, + RayFlagsNoOpaqueKHRMask = 0x00000002, + RayFlagsTerminateOnFirstHitKHRMask = 0x00000004, + RayFlagsSkipClosestHitShaderKHRMask = 0x00000008, + RayFlagsCullBackFacingTrianglesKHRMask = 0x00000010, + RayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020, + RayFlagsCullOpaqueKHRMask = 0x00000040, + RayFlagsCullNoOpaqueKHRMask = 0x00000080, + RayFlagsSkipTrianglesKHRMask = 0x00000100, + RayFlagsSkipAABBsKHRMask = 0x00000200, +}; + +enum RayQueryIntersection { + RayQueryIntersectionRayQueryCandidateIntersectionKHR = 0, + RayQueryIntersectionRayQueryCommittedIntersectionKHR = 1, + RayQueryIntersectionMax = 0x7fffffff, +}; + +enum RayQueryCommittedIntersectionType { + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR = 0, + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR = 1, + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR = 2, + RayQueryCommittedIntersectionTypeMax = 0x7fffffff, +}; + +enum RayQueryCandidateIntersectionType { + RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR = 0, + RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR = 1, + RayQueryCandidateIntersectionTypeMax = 0x7fffffff, +}; + +enum Op { + OpNop = 0, + OpUndef = 1, + OpSourceContinued = 2, + OpSource = 3, + OpSourceExtension = 4, + OpName = 5, + OpMemberName = 6, + OpString = 7, + OpLine = 8, + OpExtension = 10, + OpExtInstImport = 11, + OpExtInst = 12, + OpMemoryModel = 14, + OpEntryPoint = 15, + OpExecutionMode = 16, + OpCapability = 17, + OpTypeVoid = 19, + OpTypeBool = 20, + OpTypeInt = 21, + OpTypeFloat = 22, + OpTypeVector = 23, + OpTypeMatrix = 24, + OpTypeImage = 25, + OpTypeSampler = 26, + OpTypeSampledImage = 27, + OpTypeArray = 28, + OpTypeRuntimeArray = 29, + OpTypeStruct = 30, + OpTypeOpaque = 31, + OpTypePointer = 32, + OpTypeFunction = 33, + OpTypeEvent = 34, + OpTypeDeviceEvent = 35, + OpTypeReserveId = 36, + OpTypeQueue = 37, + OpTypePipe = 38, + OpTypeForwardPointer = 39, + OpConstantTrue = 41, + OpConstantFalse = 42, + OpConstant = 43, + OpConstantComposite = 44, + OpConstantSampler = 45, + OpConstantNull = 46, + OpSpecConstantTrue = 48, + OpSpecConstantFalse = 49, + OpSpecConstant = 50, + OpSpecConstantComposite = 51, + OpSpecConstantOp = 52, + OpFunction = 54, + OpFunctionParameter = 55, + OpFunctionEnd = 56, + OpFunctionCall = 57, + OpVariable = 59, + OpImageTexelPointer = 60, + OpLoad = 61, + OpStore = 62, + OpCopyMemory = 63, + OpCopyMemorySized = 64, + OpAccessChain = 65, + OpInBoundsAccessChain = 66, + OpPtrAccessChain = 67, + OpArrayLength = 68, + OpGenericPtrMemSemantics = 69, + OpInBoundsPtrAccessChain = 70, + OpDecorate = 71, + OpMemberDecorate = 72, + OpDecorationGroup = 73, + OpGroupDecorate = 74, + OpGroupMemberDecorate = 75, + OpVectorExtractDynamic = 77, + OpVectorInsertDynamic = 78, + OpVectorShuffle = 79, + OpCompositeConstruct = 80, + OpCompositeExtract = 81, + OpCompositeInsert = 82, + OpCopyObject = 83, + OpTranspose = 84, + OpSampledImage = 86, + OpImageSampleImplicitLod = 87, + OpImageSampleExplicitLod = 88, + OpImageSampleDrefImplicitLod = 89, + OpImageSampleDrefExplicitLod = 90, + OpImageSampleProjImplicitLod = 91, + OpImageSampleProjExplicitLod = 92, + OpImageSampleProjDrefImplicitLod = 93, + OpImageSampleProjDrefExplicitLod = 94, + OpImageFetch = 95, + OpImageGather = 96, + OpImageDrefGather = 97, + OpImageRead = 98, + OpImageWrite = 99, + OpImage = 100, + OpImageQueryFormat = 101, + OpImageQueryOrder = 102, + OpImageQuerySizeLod = 103, + OpImageQuerySize = 104, + OpImageQueryLod = 105, + OpImageQueryLevels = 106, + OpImageQuerySamples = 107, + OpConvertFToU = 109, + OpConvertFToS = 110, + OpConvertSToF = 111, + OpConvertUToF = 112, + OpUConvert = 113, + OpSConvert = 114, + OpFConvert = 115, + OpQuantizeToF16 = 116, + OpConvertPtrToU = 117, + OpSatConvertSToU = 118, + OpSatConvertUToS = 119, + OpConvertUToPtr = 120, + OpPtrCastToGeneric = 121, + OpGenericCastToPtr = 122, + OpGenericCastToPtrExplicit = 123, + OpBitcast = 124, + OpSNegate = 126, + OpFNegate = 127, + OpIAdd = 128, + OpFAdd = 129, + OpISub = 130, + OpFSub = 131, + OpIMul = 132, + OpFMul = 133, + OpUDiv = 134, + OpSDiv = 135, + OpFDiv = 136, + OpUMod = 137, + OpSRem = 138, + OpSMod = 139, + OpFRem = 140, + OpFMod = 141, + OpVectorTimesScalar = 142, + OpMatrixTimesScalar = 143, + OpVectorTimesMatrix = 144, + OpMatrixTimesVector = 145, + OpMatrixTimesMatrix = 146, + OpOuterProduct = 147, + OpDot = 148, + OpIAddCarry = 149, + OpISubBorrow = 150, + OpUMulExtended = 151, + OpSMulExtended = 152, + OpAny = 154, + OpAll = 155, + OpIsNan = 156, + OpIsInf = 157, + OpIsFinite = 158, + OpIsNormal = 159, + OpSignBitSet = 160, + OpLessOrGreater = 161, + OpOrdered = 162, + OpUnordered = 163, + OpLogicalEqual = 164, + OpLogicalNotEqual = 165, + OpLogicalOr = 166, + OpLogicalAnd = 167, + OpLogicalNot = 168, + OpSelect = 169, + OpIEqual = 170, + OpINotEqual = 171, + OpUGreaterThan = 172, + OpSGreaterThan = 173, + OpUGreaterThanEqual = 174, + OpSGreaterThanEqual = 175, + OpULessThan = 176, + OpSLessThan = 177, + OpULessThanEqual = 178, + OpSLessThanEqual = 179, + OpFOrdEqual = 180, + OpFUnordEqual = 181, + OpFOrdNotEqual = 182, + OpFUnordNotEqual = 183, + OpFOrdLessThan = 184, + OpFUnordLessThan = 185, + OpFOrdGreaterThan = 186, + OpFUnordGreaterThan = 187, + OpFOrdLessThanEqual = 188, + OpFUnordLessThanEqual = 189, + OpFOrdGreaterThanEqual = 190, + OpFUnordGreaterThanEqual = 191, + OpShiftRightLogical = 194, + OpShiftRightArithmetic = 195, + OpShiftLeftLogical = 196, + OpBitwiseOr = 197, + OpBitwiseXor = 198, + OpBitwiseAnd = 199, + OpNot = 200, + OpBitFieldInsert = 201, + OpBitFieldSExtract = 202, + OpBitFieldUExtract = 203, + OpBitReverse = 204, + OpBitCount = 205, + OpDPdx = 207, + OpDPdy = 208, + OpFwidth = 209, + OpDPdxFine = 210, + OpDPdyFine = 211, + OpFwidthFine = 212, + OpDPdxCoarse = 213, + OpDPdyCoarse = 214, + OpFwidthCoarse = 215, + OpEmitVertex = 218, + OpEndPrimitive = 219, + OpEmitStreamVertex = 220, + OpEndStreamPrimitive = 221, + OpControlBarrier = 224, + OpMemoryBarrier = 225, + OpAtomicLoad = 227, + OpAtomicStore = 228, + OpAtomicExchange = 229, + OpAtomicCompareExchange = 230, + OpAtomicCompareExchangeWeak = 231, + OpAtomicIIncrement = 232, + OpAtomicIDecrement = 233, + OpAtomicIAdd = 234, + OpAtomicISub = 235, + OpAtomicSMin = 236, + OpAtomicUMin = 237, + OpAtomicSMax = 238, + OpAtomicUMax = 239, + OpAtomicAnd = 240, + OpAtomicOr = 241, + OpAtomicXor = 242, + OpPhi = 245, + OpLoopMerge = 246, + OpSelectionMerge = 247, + OpLabel = 248, + OpBranch = 249, + OpBranchConditional = 250, + OpSwitch = 251, + OpKill = 252, + OpReturn = 253, + OpReturnValue = 254, + OpUnreachable = 255, + OpLifetimeStart = 256, + OpLifetimeStop = 257, + OpGroupAsyncCopy = 259, + OpGroupWaitEvents = 260, + OpGroupAll = 261, + OpGroupAny = 262, + OpGroupBroadcast = 263, + OpGroupIAdd = 264, + OpGroupFAdd = 265, + OpGroupFMin = 266, + OpGroupUMin = 267, + OpGroupSMin = 268, + OpGroupFMax = 269, + OpGroupUMax = 270, + OpGroupSMax = 271, + OpReadPipe = 274, + OpWritePipe = 275, + OpReservedReadPipe = 276, + OpReservedWritePipe = 277, + OpReserveReadPipePackets = 278, + OpReserveWritePipePackets = 279, + OpCommitReadPipe = 280, + OpCommitWritePipe = 281, + OpIsValidReserveId = 282, + OpGetNumPipePackets = 283, + OpGetMaxPipePackets = 284, + OpGroupReserveReadPipePackets = 285, + OpGroupReserveWritePipePackets = 286, + OpGroupCommitReadPipe = 287, + OpGroupCommitWritePipe = 288, + OpEnqueueMarker = 291, + OpEnqueueKernel = 292, + OpGetKernelNDrangeSubGroupCount = 293, + OpGetKernelNDrangeMaxSubGroupSize = 294, + OpGetKernelWorkGroupSize = 295, + OpGetKernelPreferredWorkGroupSizeMultiple = 296, + OpRetainEvent = 297, + OpReleaseEvent = 298, + OpCreateUserEvent = 299, + OpIsValidEvent = 300, + OpSetUserEventStatus = 301, + OpCaptureEventProfilingInfo = 302, + OpGetDefaultQueue = 303, + OpBuildNDRange = 304, + OpImageSparseSampleImplicitLod = 305, + OpImageSparseSampleExplicitLod = 306, + OpImageSparseSampleDrefImplicitLod = 307, + OpImageSparseSampleDrefExplicitLod = 308, + OpImageSparseSampleProjImplicitLod = 309, + OpImageSparseSampleProjExplicitLod = 310, + OpImageSparseSampleProjDrefImplicitLod = 311, + OpImageSparseSampleProjDrefExplicitLod = 312, + OpImageSparseFetch = 313, + OpImageSparseGather = 314, + OpImageSparseDrefGather = 315, + OpImageSparseTexelsResident = 316, + OpNoLine = 317, + OpAtomicFlagTestAndSet = 318, + OpAtomicFlagClear = 319, + OpImageSparseRead = 320, + OpSizeOf = 321, + OpTypePipeStorage = 322, + OpConstantPipeStorage = 323, + OpCreatePipeFromPipeStorage = 324, + OpGetKernelLocalSizeForSubgroupCount = 325, + OpGetKernelMaxNumSubgroups = 326, + OpTypeNamedBarrier = 327, + OpNamedBarrierInitialize = 328, + OpMemoryNamedBarrier = 329, + OpModuleProcessed = 330, + OpExecutionModeId = 331, + OpDecorateId = 332, + OpGroupNonUniformElect = 333, + OpGroupNonUniformAll = 334, + OpGroupNonUniformAny = 335, + OpGroupNonUniformAllEqual = 336, + OpGroupNonUniformBroadcast = 337, + OpGroupNonUniformBroadcastFirst = 338, + OpGroupNonUniformBallot = 339, + OpGroupNonUniformInverseBallot = 340, + OpGroupNonUniformBallotBitExtract = 341, + OpGroupNonUniformBallotBitCount = 342, + OpGroupNonUniformBallotFindLSB = 343, + OpGroupNonUniformBallotFindMSB = 344, + OpGroupNonUniformShuffle = 345, + OpGroupNonUniformShuffleXor = 346, + OpGroupNonUniformShuffleUp = 347, + OpGroupNonUniformShuffleDown = 348, + OpGroupNonUniformIAdd = 349, + OpGroupNonUniformFAdd = 350, + OpGroupNonUniformIMul = 351, + OpGroupNonUniformFMul = 352, + OpGroupNonUniformSMin = 353, + OpGroupNonUniformUMin = 354, + OpGroupNonUniformFMin = 355, + OpGroupNonUniformSMax = 356, + OpGroupNonUniformUMax = 357, + OpGroupNonUniformFMax = 358, + OpGroupNonUniformBitwiseAnd = 359, + OpGroupNonUniformBitwiseOr = 360, + OpGroupNonUniformBitwiseXor = 361, + OpGroupNonUniformLogicalAnd = 362, + OpGroupNonUniformLogicalOr = 363, + OpGroupNonUniformLogicalXor = 364, + OpGroupNonUniformQuadBroadcast = 365, + OpGroupNonUniformQuadSwap = 366, + OpCopyLogical = 400, + OpPtrEqual = 401, + OpPtrNotEqual = 402, + OpPtrDiff = 403, + OpSubgroupBallotKHR = 4421, + OpSubgroupFirstInvocationKHR = 4422, + OpSubgroupAllKHR = 4428, + OpSubgroupAnyKHR = 4429, + OpSubgroupAllEqualKHR = 4430, + OpSubgroupReadInvocationKHR = 4432, + OpTypeRayQueryProvisionalKHR = 4472, + OpRayQueryInitializeKHR = 4473, + OpRayQueryTerminateKHR = 4474, + OpRayQueryGenerateIntersectionKHR = 4475, + OpRayQueryConfirmIntersectionKHR = 4476, + OpRayQueryProceedKHR = 4477, + OpRayQueryGetIntersectionTypeKHR = 4479, + OpGroupIAddNonUniformAMD = 5000, + OpGroupFAddNonUniformAMD = 5001, + OpGroupFMinNonUniformAMD = 5002, + OpGroupUMinNonUniformAMD = 5003, + OpGroupSMinNonUniformAMD = 5004, + OpGroupFMaxNonUniformAMD = 5005, + OpGroupUMaxNonUniformAMD = 5006, + OpGroupSMaxNonUniformAMD = 5007, + OpFragmentMaskFetchAMD = 5011, + OpFragmentFetchAMD = 5012, + OpReadClockKHR = 5056, + OpImageSampleFootprintNV = 5283, + OpGroupNonUniformPartitionNV = 5296, + OpWritePackedPrimitiveIndices4x8NV = 5299, + OpReportIntersectionKHR = 5334, + OpReportIntersectionNV = 5334, + OpIgnoreIntersectionKHR = 5335, + OpIgnoreIntersectionNV = 5335, + OpTerminateRayKHR = 5336, + OpTerminateRayNV = 5336, + OpTraceNV = 5337, + OpTraceRayKHR = 5337, + OpTypeAccelerationStructureKHR = 5341, + OpTypeAccelerationStructureNV = 5341, + OpExecuteCallableKHR = 5344, + OpExecuteCallableNV = 5344, + OpTypeCooperativeMatrixNV = 5358, + OpCooperativeMatrixLoadNV = 5359, + OpCooperativeMatrixStoreNV = 5360, + OpCooperativeMatrixMulAddNV = 5361, + OpCooperativeMatrixLengthNV = 5362, + OpBeginInvocationInterlockEXT = 5364, + OpEndInvocationInterlockEXT = 5365, + OpDemoteToHelperInvocationEXT = 5380, + OpIsHelperInvocationEXT = 5381, + OpSubgroupShuffleINTEL = 5571, + OpSubgroupShuffleDownINTEL = 5572, + OpSubgroupShuffleUpINTEL = 5573, + OpSubgroupShuffleXorINTEL = 5574, + OpSubgroupBlockReadINTEL = 5575, + OpSubgroupBlockWriteINTEL = 5576, + OpSubgroupImageBlockReadINTEL = 5577, + OpSubgroupImageBlockWriteINTEL = 5578, + OpSubgroupImageMediaBlockReadINTEL = 5580, + OpSubgroupImageMediaBlockWriteINTEL = 5581, + OpUCountLeadingZerosINTEL = 5585, + OpUCountTrailingZerosINTEL = 5586, + OpAbsISubINTEL = 5587, + OpAbsUSubINTEL = 5588, + OpIAddSatINTEL = 5589, + OpUAddSatINTEL = 5590, + OpIAverageINTEL = 5591, + OpUAverageINTEL = 5592, + OpIAverageRoundedINTEL = 5593, + OpUAverageRoundedINTEL = 5594, + OpISubSatINTEL = 5595, + OpUSubSatINTEL = 5596, + OpIMul32x16INTEL = 5597, + OpUMul32x16INTEL = 5598, + OpDecorateString = 5632, + OpDecorateStringGOOGLE = 5632, + OpMemberDecorateString = 5633, + OpMemberDecorateStringGOOGLE = 5633, + OpVmeImageINTEL = 5699, + OpTypeVmeImageINTEL = 5700, + OpTypeAvcImePayloadINTEL = 5701, + OpTypeAvcRefPayloadINTEL = 5702, + OpTypeAvcSicPayloadINTEL = 5703, + OpTypeAvcMcePayloadINTEL = 5704, + OpTypeAvcMceResultINTEL = 5705, + OpTypeAvcImeResultINTEL = 5706, + OpTypeAvcImeResultSingleReferenceStreamoutINTEL = 5707, + OpTypeAvcImeResultDualReferenceStreamoutINTEL = 5708, + OpTypeAvcImeSingleReferenceStreaminINTEL = 5709, + OpTypeAvcImeDualReferenceStreaminINTEL = 5710, + OpTypeAvcRefResultINTEL = 5711, + OpTypeAvcSicResultINTEL = 5712, + OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL = 5713, + OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL = 5714, + OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL = 5715, + OpSubgroupAvcMceSetInterShapePenaltyINTEL = 5716, + OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL = 5717, + OpSubgroupAvcMceSetInterDirectionPenaltyINTEL = 5718, + OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL = 5719, + OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL = 5720, + OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL = 5721, + OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL = 5722, + OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL = 5723, + OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL = 5724, + OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL = 5725, + OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL = 5726, + OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL = 5727, + OpSubgroupAvcMceSetAcOnlyHaarINTEL = 5728, + OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL = 5729, + OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL = 5730, + OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL = 5731, + OpSubgroupAvcMceConvertToImePayloadINTEL = 5732, + OpSubgroupAvcMceConvertToImeResultINTEL = 5733, + OpSubgroupAvcMceConvertToRefPayloadINTEL = 5734, + OpSubgroupAvcMceConvertToRefResultINTEL = 5735, + OpSubgroupAvcMceConvertToSicPayloadINTEL = 5736, + OpSubgroupAvcMceConvertToSicResultINTEL = 5737, + OpSubgroupAvcMceGetMotionVectorsINTEL = 5738, + OpSubgroupAvcMceGetInterDistortionsINTEL = 5739, + OpSubgroupAvcMceGetBestInterDistortionsINTEL = 5740, + OpSubgroupAvcMceGetInterMajorShapeINTEL = 5741, + OpSubgroupAvcMceGetInterMinorShapeINTEL = 5742, + OpSubgroupAvcMceGetInterDirectionsINTEL = 5743, + OpSubgroupAvcMceGetInterMotionVectorCountINTEL = 5744, + OpSubgroupAvcMceGetInterReferenceIdsINTEL = 5745, + OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL = 5746, + OpSubgroupAvcImeInitializeINTEL = 5747, + OpSubgroupAvcImeSetSingleReferenceINTEL = 5748, + OpSubgroupAvcImeSetDualReferenceINTEL = 5749, + OpSubgroupAvcImeRefWindowSizeINTEL = 5750, + OpSubgroupAvcImeAdjustRefOffsetINTEL = 5751, + OpSubgroupAvcImeConvertToMcePayloadINTEL = 5752, + OpSubgroupAvcImeSetMaxMotionVectorCountINTEL = 5753, + OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL = 5754, + OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL = 5755, + OpSubgroupAvcImeSetWeightedSadINTEL = 5756, + OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL = 5757, + OpSubgroupAvcImeEvaluateWithDualReferenceINTEL = 5758, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL = 5759, + OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL = 5760, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL = 5761, + OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL = 5762, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL = 5763, + OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL = 5764, + OpSubgroupAvcImeConvertToMceResultINTEL = 5765, + OpSubgroupAvcImeGetSingleReferenceStreaminINTEL = 5766, + OpSubgroupAvcImeGetDualReferenceStreaminINTEL = 5767, + OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL = 5768, + OpSubgroupAvcImeStripDualReferenceStreamoutINTEL = 5769, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL = 5770, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL = 5771, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL = 5772, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL = 5773, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL = 5774, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL = 5775, + OpSubgroupAvcImeGetBorderReachedINTEL = 5776, + OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL = 5777, + OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL = 5778, + OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL = 5779, + OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL = 5780, + OpSubgroupAvcFmeInitializeINTEL = 5781, + OpSubgroupAvcBmeInitializeINTEL = 5782, + OpSubgroupAvcRefConvertToMcePayloadINTEL = 5783, + OpSubgroupAvcRefSetBidirectionalMixDisableINTEL = 5784, + OpSubgroupAvcRefSetBilinearFilterEnableINTEL = 5785, + OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL = 5786, + OpSubgroupAvcRefEvaluateWithDualReferenceINTEL = 5787, + OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL = 5788, + OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL = 5789, + OpSubgroupAvcRefConvertToMceResultINTEL = 5790, + OpSubgroupAvcSicInitializeINTEL = 5791, + OpSubgroupAvcSicConfigureSkcINTEL = 5792, + OpSubgroupAvcSicConfigureIpeLumaINTEL = 5793, + OpSubgroupAvcSicConfigureIpeLumaChromaINTEL = 5794, + OpSubgroupAvcSicGetMotionVectorMaskINTEL = 5795, + OpSubgroupAvcSicConvertToMcePayloadINTEL = 5796, + OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL = 5797, + OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL = 5798, + OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL = 5799, + OpSubgroupAvcSicSetBilinearFilterEnableINTEL = 5800, + OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL = 5801, + OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL = 5802, + OpSubgroupAvcSicEvaluateIpeINTEL = 5803, + OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL = 5804, + OpSubgroupAvcSicEvaluateWithDualReferenceINTEL = 5805, + OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL = 5806, + OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL = 5807, + OpSubgroupAvcSicConvertToMceResultINTEL = 5808, + OpSubgroupAvcSicGetIpeLumaShapeINTEL = 5809, + OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL = 5810, + OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL = 5811, + OpSubgroupAvcSicGetPackedIpeLumaModesINTEL = 5812, + OpSubgroupAvcSicGetIpeChromaModeINTEL = 5813, + OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, + OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, + OpSubgroupAvcSicGetInterRawSadsINTEL = 5816, + OpRayQueryGetRayTMinKHR = 6016, + OpRayQueryGetRayFlagsKHR = 6017, + OpRayQueryGetIntersectionTKHR = 6018, + OpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019, + OpRayQueryGetIntersectionInstanceIdKHR = 6020, + OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021, + OpRayQueryGetIntersectionGeometryIndexKHR = 6022, + OpRayQueryGetIntersectionPrimitiveIndexKHR = 6023, + OpRayQueryGetIntersectionBarycentricsKHR = 6024, + OpRayQueryGetIntersectionFrontFaceKHR = 6025, + OpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026, + OpRayQueryGetIntersectionObjectRayDirectionKHR = 6027, + OpRayQueryGetIntersectionObjectRayOriginKHR = 6028, + OpRayQueryGetWorldRayDirectionKHR = 6029, + OpRayQueryGetWorldRayOriginKHR = 6030, + OpRayQueryGetIntersectionObjectToWorldKHR = 6031, + OpRayQueryGetIntersectionWorldToObjectKHR = 6032, + OpMax = 0x7fffffff, +}; + +#ifdef SPV_ENABLE_UTILITY_CODE +inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) { + *hasResult = *hasResultType = false; + switch (opcode) { + default: /* unknown opcode */ break; + case OpNop: *hasResult = false; *hasResultType = false; break; + case OpUndef: *hasResult = true; *hasResultType = true; break; + case OpSourceContinued: *hasResult = false; *hasResultType = false; break; + case OpSource: *hasResult = false; *hasResultType = false; break; + case OpSourceExtension: *hasResult = false; *hasResultType = false; break; + case OpName: *hasResult = false; *hasResultType = false; break; + case OpMemberName: *hasResult = false; *hasResultType = false; break; + case OpString: *hasResult = true; *hasResultType = false; break; + case OpLine: *hasResult = false; *hasResultType = false; break; + case OpExtension: *hasResult = false; *hasResultType = false; break; + case OpExtInstImport: *hasResult = true; *hasResultType = false; break; + case OpExtInst: *hasResult = true; *hasResultType = true; break; + case OpMemoryModel: *hasResult = false; *hasResultType = false; break; + case OpEntryPoint: *hasResult = false; *hasResultType = false; break; + case OpExecutionMode: *hasResult = false; *hasResultType = false; break; + case OpCapability: *hasResult = false; *hasResultType = false; break; + case OpTypeVoid: *hasResult = true; *hasResultType = false; break; + case OpTypeBool: *hasResult = true; *hasResultType = false; break; + case OpTypeInt: *hasResult = true; *hasResultType = false; break; + case OpTypeFloat: *hasResult = true; *hasResultType = false; break; + case OpTypeVector: *hasResult = true; *hasResultType = false; break; + case OpTypeMatrix: *hasResult = true; *hasResultType = false; break; + case OpTypeImage: *hasResult = true; *hasResultType = false; break; + case OpTypeSampler: *hasResult = true; *hasResultType = false; break; + case OpTypeSampledImage: *hasResult = true; *hasResultType = false; break; + case OpTypeArray: *hasResult = true; *hasResultType = false; break; + case OpTypeRuntimeArray: *hasResult = true; *hasResultType = false; break; + case OpTypeStruct: *hasResult = true; *hasResultType = false; break; + case OpTypeOpaque: *hasResult = true; *hasResultType = false; break; + case OpTypePointer: *hasResult = true; *hasResultType = false; break; + case OpTypeFunction: *hasResult = true; *hasResultType = false; break; + case OpTypeEvent: *hasResult = true; *hasResultType = false; break; + case OpTypeDeviceEvent: *hasResult = true; *hasResultType = false; break; + case OpTypeReserveId: *hasResult = true; *hasResultType = false; break; + case OpTypeQueue: *hasResult = true; *hasResultType = false; break; + case OpTypePipe: *hasResult = true; *hasResultType = false; break; + case OpTypeForwardPointer: *hasResult = false; *hasResultType = false; break; + case OpConstantTrue: *hasResult = true; *hasResultType = true; break; + case OpConstantFalse: *hasResult = true; *hasResultType = true; break; + case OpConstant: *hasResult = true; *hasResultType = true; break; + case OpConstantComposite: *hasResult = true; *hasResultType = true; break; + case OpConstantSampler: *hasResult = true; *hasResultType = true; break; + case OpConstantNull: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantTrue: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantFalse: *hasResult = true; *hasResultType = true; break; + case OpSpecConstant: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantComposite: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantOp: *hasResult = true; *hasResultType = true; break; + case OpFunction: *hasResult = true; *hasResultType = true; break; + case OpFunctionParameter: *hasResult = true; *hasResultType = true; break; + case OpFunctionEnd: *hasResult = false; *hasResultType = false; break; + case OpFunctionCall: *hasResult = true; *hasResultType = true; break; + case OpVariable: *hasResult = true; *hasResultType = true; break; + case OpImageTexelPointer: *hasResult = true; *hasResultType = true; break; + case OpLoad: *hasResult = true; *hasResultType = true; break; + case OpStore: *hasResult = false; *hasResultType = false; break; + case OpCopyMemory: *hasResult = false; *hasResultType = false; break; + case OpCopyMemorySized: *hasResult = false; *hasResultType = false; break; + case OpAccessChain: *hasResult = true; *hasResultType = true; break; + case OpInBoundsAccessChain: *hasResult = true; *hasResultType = true; break; + case OpPtrAccessChain: *hasResult = true; *hasResultType = true; break; + case OpArrayLength: *hasResult = true; *hasResultType = true; break; + case OpGenericPtrMemSemantics: *hasResult = true; *hasResultType = true; break; + case OpInBoundsPtrAccessChain: *hasResult = true; *hasResultType = true; break; + case OpDecorate: *hasResult = false; *hasResultType = false; break; + case OpMemberDecorate: *hasResult = false; *hasResultType = false; break; + case OpDecorationGroup: *hasResult = true; *hasResultType = false; break; + case OpGroupDecorate: *hasResult = false; *hasResultType = false; break; + case OpGroupMemberDecorate: *hasResult = false; *hasResultType = false; break; + case OpVectorExtractDynamic: *hasResult = true; *hasResultType = true; break; + case OpVectorInsertDynamic: *hasResult = true; *hasResultType = true; break; + case OpVectorShuffle: *hasResult = true; *hasResultType = true; break; + case OpCompositeConstruct: *hasResult = true; *hasResultType = true; break; + case OpCompositeExtract: *hasResult = true; *hasResultType = true; break; + case OpCompositeInsert: *hasResult = true; *hasResultType = true; break; + case OpCopyObject: *hasResult = true; *hasResultType = true; break; + case OpTranspose: *hasResult = true; *hasResultType = true; break; + case OpSampledImage: *hasResult = true; *hasResultType = true; break; + case OpImageSampleImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageFetch: *hasResult = true; *hasResultType = true; break; + case OpImageGather: *hasResult = true; *hasResultType = true; break; + case OpImageDrefGather: *hasResult = true; *hasResultType = true; break; + case OpImageRead: *hasResult = true; *hasResultType = true; break; + case OpImageWrite: *hasResult = false; *hasResultType = false; break; + case OpImage: *hasResult = true; *hasResultType = true; break; + case OpImageQueryFormat: *hasResult = true; *hasResultType = true; break; + case OpImageQueryOrder: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySizeLod: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySize: *hasResult = true; *hasResultType = true; break; + case OpImageQueryLod: *hasResult = true; *hasResultType = true; break; + case OpImageQueryLevels: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySamples: *hasResult = true; *hasResultType = true; break; + case OpConvertFToU: *hasResult = true; *hasResultType = true; break; + case OpConvertFToS: *hasResult = true; *hasResultType = true; break; + case OpConvertSToF: *hasResult = true; *hasResultType = true; break; + case OpConvertUToF: *hasResult = true; *hasResultType = true; break; + case OpUConvert: *hasResult = true; *hasResultType = true; break; + case OpSConvert: *hasResult = true; *hasResultType = true; break; + case OpFConvert: *hasResult = true; *hasResultType = true; break; + case OpQuantizeToF16: *hasResult = true; *hasResultType = true; break; + case OpConvertPtrToU: *hasResult = true; *hasResultType = true; break; + case OpSatConvertSToU: *hasResult = true; *hasResultType = true; break; + case OpSatConvertUToS: *hasResult = true; *hasResultType = true; break; + case OpConvertUToPtr: *hasResult = true; *hasResultType = true; break; + case OpPtrCastToGeneric: *hasResult = true; *hasResultType = true; break; + case OpGenericCastToPtr: *hasResult = true; *hasResultType = true; break; + case OpGenericCastToPtrExplicit: *hasResult = true; *hasResultType = true; break; + case OpBitcast: *hasResult = true; *hasResultType = true; break; + case OpSNegate: *hasResult = true; *hasResultType = true; break; + case OpFNegate: *hasResult = true; *hasResultType = true; break; + case OpIAdd: *hasResult = true; *hasResultType = true; break; + case OpFAdd: *hasResult = true; *hasResultType = true; break; + case OpISub: *hasResult = true; *hasResultType = true; break; + case OpFSub: *hasResult = true; *hasResultType = true; break; + case OpIMul: *hasResult = true; *hasResultType = true; break; + case OpFMul: *hasResult = true; *hasResultType = true; break; + case OpUDiv: *hasResult = true; *hasResultType = true; break; + case OpSDiv: *hasResult = true; *hasResultType = true; break; + case OpFDiv: *hasResult = true; *hasResultType = true; break; + case OpUMod: *hasResult = true; *hasResultType = true; break; + case OpSRem: *hasResult = true; *hasResultType = true; break; + case OpSMod: *hasResult = true; *hasResultType = true; break; + case OpFRem: *hasResult = true; *hasResultType = true; break; + case OpFMod: *hasResult = true; *hasResultType = true; break; + case OpVectorTimesScalar: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesScalar: *hasResult = true; *hasResultType = true; break; + case OpVectorTimesMatrix: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesVector: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesMatrix: *hasResult = true; *hasResultType = true; break; + case OpOuterProduct: *hasResult = true; *hasResultType = true; break; + case OpDot: *hasResult = true; *hasResultType = true; break; + case OpIAddCarry: *hasResult = true; *hasResultType = true; break; + case OpISubBorrow: *hasResult = true; *hasResultType = true; break; + case OpUMulExtended: *hasResult = true; *hasResultType = true; break; + case OpSMulExtended: *hasResult = true; *hasResultType = true; break; + case OpAny: *hasResult = true; *hasResultType = true; break; + case OpAll: *hasResult = true; *hasResultType = true; break; + case OpIsNan: *hasResult = true; *hasResultType = true; break; + case OpIsInf: *hasResult = true; *hasResultType = true; break; + case OpIsFinite: *hasResult = true; *hasResultType = true; break; + case OpIsNormal: *hasResult = true; *hasResultType = true; break; + case OpSignBitSet: *hasResult = true; *hasResultType = true; break; + case OpLessOrGreater: *hasResult = true; *hasResultType = true; break; + case OpOrdered: *hasResult = true; *hasResultType = true; break; + case OpUnordered: *hasResult = true; *hasResultType = true; break; + case OpLogicalEqual: *hasResult = true; *hasResultType = true; break; + case OpLogicalNotEqual: *hasResult = true; *hasResultType = true; break; + case OpLogicalOr: *hasResult = true; *hasResultType = true; break; + case OpLogicalAnd: *hasResult = true; *hasResultType = true; break; + case OpLogicalNot: *hasResult = true; *hasResultType = true; break; + case OpSelect: *hasResult = true; *hasResultType = true; break; + case OpIEqual: *hasResult = true; *hasResultType = true; break; + case OpINotEqual: *hasResult = true; *hasResultType = true; break; + case OpUGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpSGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpUGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpSGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpULessThan: *hasResult = true; *hasResultType = true; break; + case OpSLessThan: *hasResult = true; *hasResultType = true; break; + case OpULessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpSLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdNotEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordNotEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdLessThan: *hasResult = true; *hasResultType = true; break; + case OpFUnordLessThan: *hasResult = true; *hasResultType = true; break; + case OpFOrdGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpFUnordGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpFOrdLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpShiftRightLogical: *hasResult = true; *hasResultType = true; break; + case OpShiftRightArithmetic: *hasResult = true; *hasResultType = true; break; + case OpShiftLeftLogical: *hasResult = true; *hasResultType = true; break; + case OpBitwiseOr: *hasResult = true; *hasResultType = true; break; + case OpBitwiseXor: *hasResult = true; *hasResultType = true; break; + case OpBitwiseAnd: *hasResult = true; *hasResultType = true; break; + case OpNot: *hasResult = true; *hasResultType = true; break; + case OpBitFieldInsert: *hasResult = true; *hasResultType = true; break; + case OpBitFieldSExtract: *hasResult = true; *hasResultType = true; break; + case OpBitFieldUExtract: *hasResult = true; *hasResultType = true; break; + case OpBitReverse: *hasResult = true; *hasResultType = true; break; + case OpBitCount: *hasResult = true; *hasResultType = true; break; + case OpDPdx: *hasResult = true; *hasResultType = true; break; + case OpDPdy: *hasResult = true; *hasResultType = true; break; + case OpFwidth: *hasResult = true; *hasResultType = true; break; + case OpDPdxFine: *hasResult = true; *hasResultType = true; break; + case OpDPdyFine: *hasResult = true; *hasResultType = true; break; + case OpFwidthFine: *hasResult = true; *hasResultType = true; break; + case OpDPdxCoarse: *hasResult = true; *hasResultType = true; break; + case OpDPdyCoarse: *hasResult = true; *hasResultType = true; break; + case OpFwidthCoarse: *hasResult = true; *hasResultType = true; break; + case OpEmitVertex: *hasResult = false; *hasResultType = false; break; + case OpEndPrimitive: *hasResult = false; *hasResultType = false; break; + case OpEmitStreamVertex: *hasResult = false; *hasResultType = false; break; + case OpEndStreamPrimitive: *hasResult = false; *hasResultType = false; break; + case OpControlBarrier: *hasResult = false; *hasResultType = false; break; + case OpMemoryBarrier: *hasResult = false; *hasResultType = false; break; + case OpAtomicLoad: *hasResult = true; *hasResultType = true; break; + case OpAtomicStore: *hasResult = false; *hasResultType = false; break; + case OpAtomicExchange: *hasResult = true; *hasResultType = true; break; + case OpAtomicCompareExchange: *hasResult = true; *hasResultType = true; break; + case OpAtomicCompareExchangeWeak: *hasResult = true; *hasResultType = true; break; + case OpAtomicIIncrement: *hasResult = true; *hasResultType = true; break; + case OpAtomicIDecrement: *hasResult = true; *hasResultType = true; break; + case OpAtomicIAdd: *hasResult = true; *hasResultType = true; break; + case OpAtomicISub: *hasResult = true; *hasResultType = true; break; + case OpAtomicSMin: *hasResult = true; *hasResultType = true; break; + case OpAtomicUMin: *hasResult = true; *hasResultType = true; break; + case OpAtomicSMax: *hasResult = true; *hasResultType = true; break; + case OpAtomicUMax: *hasResult = true; *hasResultType = true; break; + case OpAtomicAnd: *hasResult = true; *hasResultType = true; break; + case OpAtomicOr: *hasResult = true; *hasResultType = true; break; + case OpAtomicXor: *hasResult = true; *hasResultType = true; break; + case OpPhi: *hasResult = true; *hasResultType = true; break; + case OpLoopMerge: *hasResult = false; *hasResultType = false; break; + case OpSelectionMerge: *hasResult = false; *hasResultType = false; break; + case OpLabel: *hasResult = true; *hasResultType = false; break; + case OpBranch: *hasResult = false; *hasResultType = false; break; + case OpBranchConditional: *hasResult = false; *hasResultType = false; break; + case OpSwitch: *hasResult = false; *hasResultType = false; break; + case OpKill: *hasResult = false; *hasResultType = false; break; + case OpReturn: *hasResult = false; *hasResultType = false; break; + case OpReturnValue: *hasResult = false; *hasResultType = false; break; + case OpUnreachable: *hasResult = false; *hasResultType = false; break; + case OpLifetimeStart: *hasResult = false; *hasResultType = false; break; + case OpLifetimeStop: *hasResult = false; *hasResultType = false; break; + case OpGroupAsyncCopy: *hasResult = true; *hasResultType = true; break; + case OpGroupWaitEvents: *hasResult = false; *hasResultType = false; break; + case OpGroupAll: *hasResult = true; *hasResultType = true; break; + case OpGroupAny: *hasResult = true; *hasResultType = true; break; + case OpGroupBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupIAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupFAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupFMin: *hasResult = true; *hasResultType = true; break; + case OpGroupUMin: *hasResult = true; *hasResultType = true; break; + case OpGroupSMin: *hasResult = true; *hasResultType = true; break; + case OpGroupFMax: *hasResult = true; *hasResultType = true; break; + case OpGroupUMax: *hasResult = true; *hasResultType = true; break; + case OpGroupSMax: *hasResult = true; *hasResultType = true; break; + case OpReadPipe: *hasResult = true; *hasResultType = true; break; + case OpWritePipe: *hasResult = true; *hasResultType = true; break; + case OpReservedReadPipe: *hasResult = true; *hasResultType = true; break; + case OpReservedWritePipe: *hasResult = true; *hasResultType = true; break; + case OpReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; + case OpReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; + case OpCommitReadPipe: *hasResult = false; *hasResultType = false; break; + case OpCommitWritePipe: *hasResult = false; *hasResultType = false; break; + case OpIsValidReserveId: *hasResult = true; *hasResultType = true; break; + case OpGetNumPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGetMaxPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupCommitReadPipe: *hasResult = false; *hasResultType = false; break; + case OpGroupCommitWritePipe: *hasResult = false; *hasResultType = false; break; + case OpEnqueueMarker: *hasResult = true; *hasResultType = true; break; + case OpEnqueueKernel: *hasResult = true; *hasResultType = true; break; + case OpGetKernelNDrangeSubGroupCount: *hasResult = true; *hasResultType = true; break; + case OpGetKernelNDrangeMaxSubGroupSize: *hasResult = true; *hasResultType = true; break; + case OpGetKernelWorkGroupSize: *hasResult = true; *hasResultType = true; break; + case OpGetKernelPreferredWorkGroupSizeMultiple: *hasResult = true; *hasResultType = true; break; + case OpRetainEvent: *hasResult = false; *hasResultType = false; break; + case OpReleaseEvent: *hasResult = false; *hasResultType = false; break; + case OpCreateUserEvent: *hasResult = true; *hasResultType = true; break; + case OpIsValidEvent: *hasResult = true; *hasResultType = true; break; + case OpSetUserEventStatus: *hasResult = false; *hasResultType = false; break; + case OpCaptureEventProfilingInfo: *hasResult = false; *hasResultType = false; break; + case OpGetDefaultQueue: *hasResult = true; *hasResultType = true; break; + case OpBuildNDRange: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseFetch: *hasResult = true; *hasResultType = true; break; + case OpImageSparseGather: *hasResult = true; *hasResultType = true; break; + case OpImageSparseDrefGather: *hasResult = true; *hasResultType = true; break; + case OpImageSparseTexelsResident: *hasResult = true; *hasResultType = true; break; + case OpNoLine: *hasResult = false; *hasResultType = false; break; + case OpAtomicFlagTestAndSet: *hasResult = true; *hasResultType = true; break; + case OpAtomicFlagClear: *hasResult = false; *hasResultType = false; break; + case OpImageSparseRead: *hasResult = true; *hasResultType = true; break; + case OpSizeOf: *hasResult = true; *hasResultType = true; break; + case OpTypePipeStorage: *hasResult = true; *hasResultType = false; break; + case OpConstantPipeStorage: *hasResult = true; *hasResultType = true; break; + case OpCreatePipeFromPipeStorage: *hasResult = true; *hasResultType = true; break; + case OpGetKernelLocalSizeForSubgroupCount: *hasResult = true; *hasResultType = true; break; + case OpGetKernelMaxNumSubgroups: *hasResult = true; *hasResultType = true; break; + case OpTypeNamedBarrier: *hasResult = true; *hasResultType = false; break; + case OpNamedBarrierInitialize: *hasResult = true; *hasResultType = true; break; + case OpMemoryNamedBarrier: *hasResult = false; *hasResultType = false; break; + case OpModuleProcessed: *hasResult = false; *hasResultType = false; break; + case OpExecutionModeId: *hasResult = false; *hasResultType = false; break; + case OpDecorateId: *hasResult = false; *hasResultType = false; break; + case OpGroupNonUniformElect: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAll: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAny: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAllEqual: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBroadcastFirst: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallot: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformInverseBallot: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotBitExtract: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotBitCount: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotFindLSB: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotFindMSB: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffle: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleUp: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleDown: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformIAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformIMul: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMul: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformSMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformUMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformSMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformUMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseAnd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseOr: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalAnd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalOr: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformQuadBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformQuadSwap: *hasResult = true; *hasResultType = true; break; + case OpCopyLogical: *hasResult = true; *hasResultType = true; break; + case OpPtrEqual: *hasResult = true; *hasResultType = true; break; + case OpPtrNotEqual: *hasResult = true; *hasResultType = true; break; + case OpPtrDiff: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break; + case OpTypeRayQueryProvisionalKHR: *hasResult = true; *hasResultType = false; break; + case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break; + case OpGroupIAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupUMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupSMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupUMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupSMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpFragmentMaskFetchAMD: *hasResult = true; *hasResultType = true; break; + case OpFragmentFetchAMD: *hasResult = true; *hasResultType = true; break; + case OpReadClockKHR: *hasResult = true; *hasResultType = true; break; + case OpImageSampleFootprintNV: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformPartitionNV: *hasResult = true; *hasResultType = true; break; + case OpWritePackedPrimitiveIndices4x8NV: *hasResult = false; *hasResultType = false; break; + case OpReportIntersectionNV: *hasResult = true; *hasResultType = true; break; + case OpIgnoreIntersectionNV: *hasResult = false; *hasResultType = false; break; + case OpTerminateRayNV: *hasResult = false; *hasResultType = false; break; + case OpTraceNV: *hasResult = false; *hasResultType = false; break; + case OpTypeAccelerationStructureNV: *hasResult = true; *hasResultType = false; break; + case OpExecuteCallableNV: *hasResult = false; *hasResultType = false; break; + case OpTypeCooperativeMatrixNV: *hasResult = true; *hasResultType = false; break; + case OpCooperativeMatrixLoadNV: *hasResult = true; *hasResultType = true; break; + case OpCooperativeMatrixStoreNV: *hasResult = false; *hasResultType = false; break; + case OpCooperativeMatrixMulAddNV: *hasResult = true; *hasResultType = true; break; + case OpCooperativeMatrixLengthNV: *hasResult = true; *hasResultType = true; break; + case OpBeginInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; + case OpEndInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; + case OpDemoteToHelperInvocationEXT: *hasResult = false; *hasResultType = false; break; + case OpIsHelperInvocationEXT: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleDownINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleUpINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleXorINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpSubgroupImageBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupImageBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpSubgroupImageMediaBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupImageMediaBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpUCountLeadingZerosINTEL: *hasResult = true; *hasResultType = true; break; + case OpUCountTrailingZerosINTEL: *hasResult = true; *hasResultType = true; break; + case OpAbsISubINTEL: *hasResult = true; *hasResultType = true; break; + case OpAbsUSubINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAddSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAddSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAverageINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAverageINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; + case OpISubSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break; + case OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break; + case OpDecorateString: *hasResult = false; *hasResultType = false; break; + case OpMemberDecorateString: *hasResult = false; *hasResultType = false; break; + case OpVmeImageINTEL: *hasResult = true; *hasResultType = true; break; + case OpTypeVmeImageINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImePayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcRefPayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcSicPayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcMcePayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcMceResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcRefResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcSicResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetAcOnlyHaarINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToImePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToImeResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToRefPayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToRefResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToSicPayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToSicResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetBestInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMajorShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMinorShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterDirectionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeRefWindowSizeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeAdjustRefOffsetINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetMaxMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetWeightedSadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeStripDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetBorderReachedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcFmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcBmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefSetBidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureSkcINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureIpeLumaINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureIpeLumaChromaINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetMotionVectorMaskINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateIpeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetIpeLumaShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedIpeLumaModesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetIpeChromaModeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetRayTMinKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetRayFlagsKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionTKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceCustomIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceIdKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionGeometryIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionPrimitiveIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionBarycentricsKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionFrontFaceKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetWorldRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetWorldRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break; + } +} +#endif /* SPV_ENABLE_UTILITY_CODE */ + +// Overload operator| for mask bit combining + +inline ImageOperandsMask operator|(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) | unsigned(b)); } +inline FPFastMathModeMask operator|(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) | unsigned(b)); } +inline SelectionControlMask operator|(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) | unsigned(b)); } +inline LoopControlMask operator|(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) | unsigned(b)); } +inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) | unsigned(b)); } +inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); } +inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); } +inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); } +inline RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); } + +} // end namespace spv + +#endif // #ifndef spirv_HPP + diff --git a/android/armeabi-v7a/include/glslang/SPIRV/spvIR.h b/android/armeabi-v7a/include/glslang/SPIRV/spvIR.h new file mode 100644 index 00000000..6523035e --- /dev/null +++ b/android/armeabi-v7a/include/glslang/SPIRV/spvIR.h @@ -0,0 +1,485 @@ +// +// Copyright (C) 2014 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// SPIRV-IR +// +// Simple in-memory representation (IR) of SPIRV. Just for holding +// Each function's CFG of blocks. Has this hierarchy: +// - Module, which is a list of +// - Function, which is a list of +// - Block, which is a list of +// - Instruction +// + +#pragma once +#ifndef spvIR_H +#define spvIR_H + +#include "spirv.hpp" + +#include +#include +#include +#include +#include +#include + +namespace spv { + +class Block; +class Function; +class Module; + +const Id NoResult = 0; +const Id NoType = 0; + +const Decoration NoPrecision = DecorationMax; + +#ifdef __GNUC__ +# define POTENTIALLY_UNUSED __attribute__((unused)) +#else +# define POTENTIALLY_UNUSED +#endif + +POTENTIALLY_UNUSED +const MemorySemanticsMask MemorySemanticsAllMemory = + (MemorySemanticsMask)(MemorySemanticsUniformMemoryMask | + MemorySemanticsWorkgroupMemoryMask | + MemorySemanticsAtomicCounterMemoryMask | + MemorySemanticsImageMemoryMask); + +struct IdImmediate { + bool isId; // true if word is an Id, false if word is an immediate + unsigned word; + IdImmediate(bool i, unsigned w) : isId(i), word(w) {} +}; + +// +// SPIR-V IR instruction. +// + +class Instruction { +public: + Instruction(Id resultId, Id typeId, Op opCode) : resultId(resultId), typeId(typeId), opCode(opCode), block(nullptr) { } + explicit Instruction(Op opCode) : resultId(NoResult), typeId(NoType), opCode(opCode), block(nullptr) { } + virtual ~Instruction() {} + void addIdOperand(Id id) { + operands.push_back(id); + idOperand.push_back(true); + } + void addImmediateOperand(unsigned int immediate) { + operands.push_back(immediate); + idOperand.push_back(false); + } + void setImmediateOperand(unsigned idx, unsigned int immediate) { + assert(!idOperand[idx]); + operands[idx] = immediate; + } + + void addStringOperand(const char* str) + { + unsigned int word; + char* wordString = (char*)&word; + char* wordPtr = wordString; + int charCount = 0; + char c; + do { + c = *(str++); + *(wordPtr++) = c; + ++charCount; + if (charCount == 4) { + addImmediateOperand(word); + wordPtr = wordString; + charCount = 0; + } + } while (c != 0); + + // deal with partial last word + if (charCount > 0) { + // pad with 0s + for (; charCount < 4; ++charCount) + *(wordPtr++) = 0; + addImmediateOperand(word); + } + } + bool isIdOperand(int op) const { return idOperand[op]; } + void setBlock(Block* b) { block = b; } + Block* getBlock() const { return block; } + Op getOpCode() const { return opCode; } + int getNumOperands() const + { + assert(operands.size() == idOperand.size()); + return (int)operands.size(); + } + Id getResultId() const { return resultId; } + Id getTypeId() const { return typeId; } + Id getIdOperand(int op) const { + assert(idOperand[op]); + return operands[op]; + } + unsigned int getImmediateOperand(int op) const { + assert(!idOperand[op]); + return operands[op]; + } + + // Write out the binary form. + void dump(std::vector& out) const + { + // Compute the wordCount + unsigned int wordCount = 1; + if (typeId) + ++wordCount; + if (resultId) + ++wordCount; + wordCount += (unsigned int)operands.size(); + + // Write out the beginning of the instruction + out.push_back(((wordCount) << WordCountShift) | opCode); + if (typeId) + out.push_back(typeId); + if (resultId) + out.push_back(resultId); + + // Write out the operands + for (int op = 0; op < (int)operands.size(); ++op) + out.push_back(operands[op]); + } + +protected: + Instruction(const Instruction&); + Id resultId; + Id typeId; + Op opCode; + std::vector operands; // operands, both and immediates (both are unsigned int) + std::vector idOperand; // true for operands that are , false for immediates + Block* block; +}; + +// +// SPIR-V IR block. +// + +class Block { +public: + Block(Id id, Function& parent); + virtual ~Block() + { + } + + Id getId() { return instructions.front()->getResultId(); } + + Function& getParent() const { return parent; } + void addInstruction(std::unique_ptr inst); + void addPredecessor(Block* pred) { predecessors.push_back(pred); pred->successors.push_back(this);} + void addLocalVariable(std::unique_ptr inst) { localVariables.push_back(std::move(inst)); } + const std::vector& getPredecessors() const { return predecessors; } + const std::vector& getSuccessors() const { return successors; } + const std::vector >& getInstructions() const { + return instructions; + } + const std::vector >& getLocalVariables() const { return localVariables; } + void setUnreachable() { unreachable = true; } + bool isUnreachable() const { return unreachable; } + // Returns the block's merge instruction, if one exists (otherwise null). + const Instruction* getMergeInstruction() const { + if (instructions.size() < 2) return nullptr; + const Instruction* nextToLast = (instructions.cend() - 2)->get(); + switch (nextToLast->getOpCode()) { + case OpSelectionMerge: + case OpLoopMerge: + return nextToLast; + default: + return nullptr; + } + return nullptr; + } + + // Change this block into a canonical dead merge block. Delete instructions + // as necessary. A canonical dead merge block has only an OpLabel and an + // OpUnreachable. + void rewriteAsCanonicalUnreachableMerge() { + assert(localVariables.empty()); + // Delete all instructions except for the label. + assert(instructions.size() > 0); + instructions.resize(1); + successors.clear(); + addInstruction(std::unique_ptr(new Instruction(OpUnreachable))); + } + // Change this block into a canonical dead continue target branching to the + // given header ID. Delete instructions as necessary. A canonical dead continue + // target has only an OpLabel and an unconditional branch back to the corresponding + // header. + void rewriteAsCanonicalUnreachableContinue(Block* header) { + assert(localVariables.empty()); + // Delete all instructions except for the label. + assert(instructions.size() > 0); + instructions.resize(1); + successors.clear(); + // Add OpBranch back to the header. + assert(header != nullptr); + Instruction* branch = new Instruction(OpBranch); + branch->addIdOperand(header->getId()); + addInstruction(std::unique_ptr(branch)); + successors.push_back(header); + } + + bool isTerminated() const + { + switch (instructions.back()->getOpCode()) { + case OpBranch: + case OpBranchConditional: + case OpSwitch: + case OpKill: + case OpReturn: + case OpReturnValue: + case OpUnreachable: + return true; + default: + return false; + } + } + + void dump(std::vector& out) const + { + instructions[0]->dump(out); + for (int i = 0; i < (int)localVariables.size(); ++i) + localVariables[i]->dump(out); + for (int i = 1; i < (int)instructions.size(); ++i) + instructions[i]->dump(out); + } + +protected: + Block(const Block&); + Block& operator=(Block&); + + // To enforce keeping parent and ownership in sync: + friend Function; + + std::vector > instructions; + std::vector predecessors, successors; + std::vector > localVariables; + Function& parent; + + // track whether this block is known to be uncreachable (not necessarily + // true for all unreachable blocks, but should be set at least + // for the extraneous ones introduced by the builder). + bool unreachable; +}; + +// The different reasons for reaching a block in the inReadableOrder traversal. +enum ReachReason { + // Reachable from the entry block via transfers of control, i.e. branches. + ReachViaControlFlow = 0, + // A continue target that is not reachable via control flow. + ReachDeadContinue, + // A merge block that is not reachable via control flow. + ReachDeadMerge +}; + +// Traverses the control-flow graph rooted at root in an order suited for +// readable code generation. Invokes callback at every node in the traversal +// order. The callback arguments are: +// - the block, +// - the reason we reached the block, +// - if the reason was that block is an unreachable continue or unreachable merge block +// then the last parameter is the corresponding header block. +void inReadableOrder(Block* root, std::function callback); + +// +// SPIR-V IR Function. +// + +class Function { +public: + Function(Id id, Id resultType, Id functionType, Id firstParam, Module& parent); + virtual ~Function() + { + for (int i = 0; i < (int)parameterInstructions.size(); ++i) + delete parameterInstructions[i]; + + for (int i = 0; i < (int)blocks.size(); ++i) + delete blocks[i]; + } + Id getId() const { return functionInstruction.getResultId(); } + Id getParamId(int p) const { return parameterInstructions[p]->getResultId(); } + Id getParamType(int p) const { return parameterInstructions[p]->getTypeId(); } + + void addBlock(Block* block) { blocks.push_back(block); } + void removeBlock(Block* block) + { + auto found = find(blocks.begin(), blocks.end(), block); + assert(found != blocks.end()); + blocks.erase(found); + delete block; + } + + Module& getParent() const { return parent; } + Block* getEntryBlock() const { return blocks.front(); } + Block* getLastBlock() const { return blocks.back(); } + const std::vector& getBlocks() const { return blocks; } + void addLocalVariable(std::unique_ptr inst); + Id getReturnType() const { return functionInstruction.getTypeId(); } + + void setImplicitThis() { implicitThis = true; } + bool hasImplicitThis() const { return implicitThis; } + + void dump(std::vector& out) const + { + // OpFunction + functionInstruction.dump(out); + + // OpFunctionParameter + for (int p = 0; p < (int)parameterInstructions.size(); ++p) + parameterInstructions[p]->dump(out); + + // Blocks + inReadableOrder(blocks[0], [&out](const Block* b, ReachReason, Block*) { b->dump(out); }); + Instruction end(0, 0, OpFunctionEnd); + end.dump(out); + } + +protected: + Function(const Function&); + Function& operator=(Function&); + + Module& parent; + Instruction functionInstruction; + std::vector parameterInstructions; + std::vector blocks; + bool implicitThis; // true if this is a member function expecting to be passed a 'this' as the first argument +}; + +// +// SPIR-V IR Module. +// + +class Module { +public: + Module() {} + virtual ~Module() + { + // TODO delete things + } + + void addFunction(Function *fun) { functions.push_back(fun); } + + void mapInstruction(Instruction *instruction) + { + spv::Id resultId = instruction->getResultId(); + // map the instruction's result id + if (resultId >= idToInstruction.size()) + idToInstruction.resize(resultId + 16); + idToInstruction[resultId] = instruction; + } + + Instruction* getInstruction(Id id) const { return idToInstruction[id]; } + const std::vector& getFunctions() const { return functions; } + spv::Id getTypeId(Id resultId) const { + return idToInstruction[resultId] == nullptr ? NoType : idToInstruction[resultId]->getTypeId(); + } + StorageClass getStorageClass(Id typeId) const + { + assert(idToInstruction[typeId]->getOpCode() == spv::OpTypePointer); + return (StorageClass)idToInstruction[typeId]->getImmediateOperand(0); + } + + void dump(std::vector& out) const + { + for (int f = 0; f < (int)functions.size(); ++f) + functions[f]->dump(out); + } + +protected: + Module(const Module&); + std::vector functions; + + // map from result id to instruction having that result id + std::vector idToInstruction; + + // map from a result id to its type id +}; + +// +// Implementation (it's here due to circular type definitions). +// + +// Add both +// - the OpFunction instruction +// - all the OpFunctionParameter instructions +__inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, Module& parent) + : parent(parent), functionInstruction(id, resultType, OpFunction), implicitThis(false) +{ + // OpFunction + functionInstruction.addImmediateOperand(FunctionControlMaskNone); + functionInstruction.addIdOperand(functionType); + parent.mapInstruction(&functionInstruction); + parent.addFunction(this); + + // OpFunctionParameter + Instruction* typeInst = parent.getInstruction(functionType); + int numParams = typeInst->getNumOperands() - 1; + for (int p = 0; p < numParams; ++p) { + Instruction* param = new Instruction(firstParamId + p, typeInst->getIdOperand(p + 1), OpFunctionParameter); + parent.mapInstruction(param); + parameterInstructions.push_back(param); + } +} + +__inline void Function::addLocalVariable(std::unique_ptr inst) +{ + Instruction* raw_instruction = inst.get(); + blocks[0]->addLocalVariable(std::move(inst)); + parent.mapInstruction(raw_instruction); +} + +__inline Block::Block(Id id, Function& parent) : parent(parent), unreachable(false) +{ + instructions.push_back(std::unique_ptr(new Instruction(id, NoType, OpLabel))); + instructions.back()->setBlock(this); + parent.getParent().mapInstruction(instructions.back().get()); +} + +__inline void Block::addInstruction(std::unique_ptr inst) +{ + Instruction* raw_instruction = inst.get(); + instructions.push_back(std::move(inst)); + raw_instruction->setBlock(this); + if (raw_instruction->getResultId()) + parent.getParent().mapInstruction(raw_instruction); +} + +} // end spv namespace + +#endif // spvIR_H diff --git a/android/x86/glslang/libOGLCompiler.a b/android/x86/glslang/libOGLCompiler.a new file mode 100644 index 0000000000000000000000000000000000000000..a27cb1cb5e771d938d1c1ee070208ca5a55565e7 GIT binary patch literal 23824 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 fA8!NF{u=h~A2CTfjLUxmKRh~? literal 0 HcmV?d00001 diff --git a/android/x86/glslang/libOSDependent.a b/android/x86/glslang/libOSDependent.a new file mode 100644 index 0000000000000000000000000000000000000000..a6a3d55d6d4bd5eee6a122017980631a79c5c997 GIT binary patch literal 14622 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 literal 0 HcmV?d00001 diff --git a/android/x86/glslang/libSPIRV.a b/android/x86/glslang/libSPIRV.a new file mode 100644 index 0000000000000000000000000000000000000000..85c633f0069162f735be684c22606b79af8783dd GIT binary patch literal 653462 zcmd?S3w%>W7C$~WP1_VwZh!zms-zIL2uQ1-?OG&YTZ$GaZ%|&Y=wg?Z3aQjx#MUIh z^%6uyWtCN2#YM#xUsx2OMQj0;m#pF&T^5M}DT-JS$^U!iK9i<^{&s(#&;RqQk~?=E zXU?2C=ggTikDHl)%|Er(;2E=L+<4m`M$a5oe#fOZm6u;S zvrnrbw~f5{#%VYHe#XtiXHC0#mKKd1gDP&F5gSuFbGEN^*36r3o;_R3H|^HhH_o1Y z^Pf;&i|Ugdi(pQ_+}tZKzp`ImU$?tob`BCR<2iD&v#;ojxXZKq&MPhd&Rcw@|2Y2`_M`EM4xT)51f%tnnH>pxU}kWz1`eme;d`BhI99ydSf#IID~ znc+WV5BU*hp}8JsS<-ZtEU?nDY2yx_ibkXU%}y;~FC8~ljdLiauR`gHRR8Ak$y084 zn$*z=%^jC<%<1{!0o{7O)Uws4GOH?BWAt0Gldl)PT4B;QgAfLe7 z2tEg2q!p|?VaeM*cbAMN1*4%Eo($hqV3i?zT~aSkbf;7=4-Bva;_j z$*ZkwQPL#Dgp(FSTB48T2p3JZ)d)gR=(S!DUJ|kx`&h6=1oo9+XY8<${EHxbFLY#v z=mGwng^ri(>|Vk4qMf}aNS1f)Y(rA720QycX%fOatQWmwXTMmN3V69c<)XLkY-37i zgjb|yd~9d?Qr%zL*$Xzu=XSQ+)(v4ftrOz^o_5jucD6Gu6X6xDF4&52tF))=?7LRe z5&p3C7Dc?Hj|~+D4YD1x2;G-?f>+imxUy6&?`S*FgMh;erFj?E5x% z9w}!3a(pH{JcLEt{pIUo_OP?V&&6zEhx3r|c85hNM~m5-4CjxK1snWz`mj zfA&X`Sjh66O8cmANa%abrl~9-jM^}jg@rB%KV>+!ycW=_Ds2i zvC~tW$nn6`S)?1N506>c^H4<3TW2>7WzQ#fT0WF*O1|>gPjIyyae9s9wtTzIvF zt!!6}s0Z5jJa`@Zw0*nphq9-fH?1mRjUDz2DEDEf^H9Zd*TBbzvT)~K2*1)5sof_gNg{o(6a;QT8$l(6^Ce@FOaDBIJO5>~h~)|Ie>?&8mevYnYv3J(uu zwcR_dypH|5yBqi|@N_?L9ed7m!3!m9yQkCJCG6n~r=#%W7da6A;v&b2>)3Y}Wg)!! zVmn&(_QlauB!AiGUr9;`vR|bVghqB|j_OGsEyYd|G z0;}IWP57+8>WYW2WB&Yz6%7mw++#u9$!i9Fe;wOgcpbv4ivIi}kT3p>GOxP!89uHM z?Ozbs{osT9g-#1D1(Ujim$H{FovJTopIZ9=)SInHn)GvTcCYpBXm9pJ^0od;+2bjW z6TR7+DQ$n~%@(D0`=vK~*>;a0UCP$9>i1)B_EW3*0!lw(zsG{Oe~LYj`Ly_Cd%SG# zo^_-*TkaW%@VB0e5q|i>J_sMWF#T|E_S!{lKj_UO7yTLW(Tg7yj`n8zdVENLPxpLR zK;+imQ&fKG$=-zQylDwoKTn71EB`c|y_otFTJcQUtCqv*>{#m;1f)EfK2G7Uuvb!4)LIcUiY=@`Z9_vX-%}kvNeZIqi=8>3uREtbiP-PD{P_e>d*J*|4Ug z$ot%jEc80Rd#4q6jdbty7#>?a?eE9qo(nrI!sDHby8H}it1j;H4Qkxiqgo)SO_%Hx zJ_lMGdy9X^Yv|H$6#LetUFdE9rETeLO`o)X0zh4#F)Q%)Z1(i0@pw3=(>j1#eR-F! z0nXpI>=k5rq@R-)=-26SWO?$63!lNG;mT{~qlSOyc3Fd*3xC(;pLj@DeJ4=tsr>ZN zdji|tKYbw{FJ7JQ$K&&>yRJr_l>^dGzbmkx2c)0C<5_RUbBKJ$+u<2JzVNnPg~t(Z zpLKZb9w-v9ql40GP<-1p&PVWgt>8}-xu$ULcDy|__-PBhzB?qHx?#(;X`yWbJ9Mq% zNtA!~x?T%V#gdYRyvx2Fdiet=a%5Pq`w_ckxbyT@^kZqKL&&h3SOXlC2MXx7sb=IK# zGiAdz09@lA`_fzejK!SG_S`m{v8QJC+5*HMD(^{9cHKT^6G}fbYxWjA*3Gu>K-$sS zogPEA3-0K$4H%xdqYFhoUpe#xWLa|Ou&0ss(VtgZ=ylm$!#2YX`0=heeq=p;_uz$i zY^xHcJ%H!)_Xu4dM&@Jp2>lrWa&Eq}b18fw%vWMZ!hP5x;Gb(4Gk34+)dj;Qeq& zSeZl-Z`?0*d>#=mJ|Nsq?<*dpO7=b|I3Gdms-?o`oaJ74SSWe}5kEXEbbJO+|1zQI zH9WU26FNSL=Z3!ubE)`yj|vL}f_LCCK@uqEJ%2-hvb^=U@WTa^=l!>Y0rSyVg1s6M+v^1PHau5v5+1fv!lruRcE(<55ZaUWsK@gG0QwkDYU3e1saRBfN7^nJ zfr^eA!tR3tyHEHy>2*7+O78cHoxPQO>1%fOT#D@lJBy^O6!7w>Z8VafN+ZkgyR_#7 zygc3dQW%SST3>?j>DI8v6nGQa!+`g&&@Rx59T#j>t=MT{C}Zzh#{9h%doQWo!dC1N zs}tcDtWJdAPj;S4V+&Gp?`g#vQ*5WxSZ!+Yy{*{yHV0zvN&6#=)ie=MPNmJ{WA^#% zXXxOcEsm-bCMTUjT?>+PmZz|qp8+%5g<3G72p`o0P5dr$g@6WD_nmwq;ZZOn4)p1^iw?L+-9UNY{J3GCIL-w0n! zV1K>zJ=@~z+1e{R?U}$Dugo|wfo;wG%!;V!)jju4V9yPBpcP*3xppPx-dK{ce**io z1hWuUGr{@Z1oqy9MM~RR>eIGtJ9uil#qnVh`@-@BGUE@lXeqxJEob=G^=KOVQGkT8 z`lPN$(%65JK0~-Jx$EIHwl5hPldVbZ8cAb2Qr|*&QCin<8hbwN77ja}N87Sm;81IE zY)N7}Eg|IBa7Y~Aj~#8r@bAX&JF zX;XR(dBjb8o=ok!fISG_elW>-q&0g#DeY)$_I1)LNk6n^52b#~4K(DzL~}hdtxq~4 zY@34FUdHAr?B$eyShh@I-`G0UPGOIxb=ok61??S{OhMJ%mQG_fKY@bxlW} z*WKN|o6J7ROh?RX-MSr`%--zo+Bk_V^SIua#7=qAQRRIXyVgu%A6?w_gGuc19*(t> z+3_CfM<=m8mvr7ci9OWw?#9V%d3Lvt@tgCkFn)q`Nil3}jX6WP1N9M4T=O~YJUC$SfYXCnMw>0H$N;|N!15_@nIQ7}9z z^T1^G!sztJCbO?b2Zhs$rakpzX&K{sO4gH@N(h*b_IjT{M}k zxuL^?$*kdqw)aeCdv6$eYBF0n@kg+Y!n-{l68b#RmTeY>z@KI5^S8F_m?itMw(RMo z#o*nS(+57;mi>^vN6+7}pvS)~Y?+Yzk%dKsJcOUNj86L>X?Er;wZw{-Z~%3iXxJ7HySTYmS8l`T#h{F9Y6B^Cc*WwqA7s51QuWa|~7 z>yjk4Tlhkkvm0+ZX>AhOizzo97ukl?4tqpaYfC>VvMI768zOtJOWB;;t_{7GJSaT7xBe?@&UPvka&co($W*dv9kcIG&O?<<~p07U5aTL=ZR0whWG$q;$p}O-g<)NqEBS)Z#QEo9C1uu1#XH1y-?w zCvfR++ad^adcG$JezvJh~^;XWraqqYMwhh7M^vfUMZ;JT9zp-G{P=9{B>@r zcxtG8s=rn*tb1uUTPNS}wz58O3I)ty^!0%zg0$4LiXJ{siFt{jn3f0vJV{+8kS2OE zILcTaXhaG6L+}_Le5Jro5h1?5kcBk{4xqr(O9P^|6N?2-@QHuDXA$M+>jlNidOhO=2B;w_>PKl&d52ugwkChdlr<) zSZj|>btf%(yTs5+Uq&30eGaStz-#{PHVGj_G!!`O z#L`fF4F$H6Yy=_TL`S_afMPD%0dlKSZ=>Nqg-ZO|64;8s1 zsT8(wG!_2VYdBYy>aO)5ad&r9gB5{PgqDY8THLI&@s6o$viLzJH-55hwCb5xCoa18 zG*(?zQSe=muq8x61(>3wFiOlsQ%bP_(duI~_i zw#@2c;2D%6AY_3E(3iS;1p}2x>N;RZRon5)f~4(fS&)Wv2c z+c=mQY)hh7(xy1L)z=EWq4ZUXzxEjA7G$O>(-}~v>N2TWnOe0-sX+_r1N`U|mo(bb z3j=+LzbRTV99%cgcq(k~eCUJnV zf#)Ipq5hrYw3($3Xx~iL0#7Np zeKc5o{LOMdvdl<)#c{P_j{=XIejH*Ct4I1~A7cUv` zJeyQ+&V{hHT?W22?N70H7r}mx!D*3a1)_AbcOhQnfnG?D3xjvy`|fxRc(84O$?H9< z@PGz))9eKL#KVHM(spbCaf^iq6?6~Tb-d*}vTs4=0{FQLJVgS6*AXgsV$#E(qtqwn zar}L}`W#J9rCrz{67tiC0ff8|{HZ8DP0co4eU{S`I>N_`V4$h2+lRS`E$Z|5O2>{+ z5Zmmy1>;OUjbE%j;JKOtp@63VPsG!M{tzrygRsrL2+9h5q(z<*yxm*rm zGEY=9BRJj&PB((njNnuwID-eP2B4VFh%GmQbB$o75v<}tUTmQe8!&=PjNl?8xReKZ zvE@eWG9&o35nN#eSMeY(w#JBEZ3JtK;HyS(JrD9?n~m67Blw;X++qZG@*pp^*NEL? z1os)i&y3)H9^}Oi8LoJ1aMzEI=?8}3^SiTXPYXl37pw|c%^B^x)YQ&Zp!SP0Lv=N-hgS^-@ zBX+70oM8l~8^LlO^x&j=pm zL0+uUh&^Nkn~dNwBY27jc`+;0GyOrWFe7L;f;J=Q;6Yx@WyCs-pxX#$7(r#fAura; zh|MyBeT`tY5zOU5Ud(I6<{QCcBUoSrOO0TO5gcy>M;pPZMsT7LoW_Gy1EA_>APCCP zLnTtV8icB!t|V3(i9RD(Wd!FM!2l0d4UlPQ<0SGorO#(WP zfjSi9<^!G%8iGR)QeoKWPCi9HUMKjjg85z60RwFYY~;R1D_1KOJj5&T!KztXa9PtT z!S@&0ewkcw*{Mh+=I~wCTGV^hBEIo< zwo4NH%6439WRjj40T2R6c!?NWkY7h8a;1`M*TGQ9Wha1e>4+F)5u;3X%Y@RH1WY~b zgXM>aJaUj)(qogf3se1Dk3Rq0bI-|t%C7!Jr4(k-4%+T(&-+PSv>&tR>R+O;kyJX* zIX}32UT32k^p}}f;@bJs0UXq6BQGwe%I43&Z^RZ_d@G*24pK=>j!H+2)Jz#Pk!H-| zT1=g&8(P7l%mzJsMN)Q!k+%nmj2Nj?K;Ga3pwQY%{N|nZO;_j<8te!S2aj4uG~*vQ zH86j?z)amGOQbDwT5xMcQ>2>`FAuim<@!4K8*J*kC=ayd*+O^PDvssVOAQr|9|zwF zJ`rL74$0S$r+)GSd)BO4uv=HJHWvLQ*v(ty=)WIU_guKhVY&WPaVU~yWa|HKB>6gr=2_t(3D#EZh@|Hnj@%kj zAWJ{JMMeDsSOsR~_A;l|oCdFh3N}!SSc4ag3>hi6NvYu5od^@rd})wn{*p@K8hzEX z4=EaiXuz|VGHT7X@n(-Vnlw&pQX2zX^apRx*Rk!n+{n@YD{4 zkF?hNTxyU9JNnDJpCytX^1 z_+~+OkDW5>#s)UHWXiBxpw|DO(VFDX6@n{6lY=voTBR&dCR+QhCpStNbgstQX)47b zKgEvf6Q4Vwu-ePE;8qNok?10KYLG>LdW+ySqq_T*9(syU*xM}enUAK!($B0UzKNF_82X?m@?dFQ(psZJ5yDAa-wn$dF)yaekv21trpgc^Q5ftIuk?u=J<&IdMwB z0ko()gXI)Zw0rb5iY+@Yk%re)ca;lS!UOT6gH6~n;?)0T%YZUaS_Ps-*Bk`HN7wA< zzx(i8*7gi7@aLwB!MicbQyUE^YdDma+a8~DJX$~fVKndz)ySMsTwpdKyT2(}43I|< z+$07Ws;_wn0KzXLszvS~W%a+LVYm|8)>K|?`~?f4aYjDbvFBR9##=4h`h}d|0!vU) zDCk7HWul6&t-mSF*WTY`tH`Nwp~8s0277_96S<}{9xCa}qBI~iGdonKl&jnT7b=eW zPgv$$aE?VhN@uKt;IlVirQIzS>_T_dkQj=EoBC6f@7#b@)${@|2vrs~VCdDCwMv9? zm^Nt`qIfk1w|-#R@CN{3mMAg!DRxK2_Xu*HbB_R#7N%X{DuC82(|V4^*`8=e7~Aog zbVT|N#*G*pPb2Ryh_2~^y3s2ygDLekChV1PCcrDUQM0*4^9HnR8)=BO*p8~VGKlWJ zt~x$tDT!#VvPo6V`IKG8e8beSWvMhHS&9VB)Nx1PBGAlTK3|DR)uHu{uRQIHm0wEP z#Q<&H*9RV-SM7#K3Jr>iJvtSJ+T3(?1U?jg7v=g-K^&%p2emj; z%FaonlFCRWm0^X-$UvP?87gzq(Fwisgv=RVZOd9ed_63M7EJtK!^Wtw1vx|tn*STd zFu97HMi@$bllU0EhHNH<5y(Jp4;It-%A(rD&q8d$RAh74!{$yymg*C$5D9C$T(!3M zNbhi&zm8Dfsuv!csCNH$q5AYsMEpNgpZ*z7F}Mab>RqUI zo){RGpeKJpeiL^TBTMy(Qv}S+9Sxj2dQeYZjvOjz6)@a~so|RttukB^&hMB&Uc*6J z5E%m!UStk*50b;AA)Dj-Jcu99dBtgJ{$D_{Mf^zC{+swc_v`T^;{`(v4L!64 zGIGB9l0?K^MZ|63#1(@_IseDHk%`4(8_=@UhaVFtNlL_Dvf5pI~6&I_C(S*=s{#tX~w591-2=-|VPb@97U-WfdN>Q)F*} z>^+4=0@|bpV-TZ#03pp%p}SVR$c^X%Jn|aFzyT!d^J{sAX9heJv~5i;bY4~H@})~Q zKX!)~IwPHsD^!TBHa7UxvW>kr@=&)t#v|>l+n1bISCJPg%#d~r78f1|+>K-tSD(OQ z&wx3Oy026Gb#DJx`|`Gl*KCt^0MIxCuc7YHKtU>W%P79B?%U*zU3Hc9Fjt9#_Iiipw`ovJr4!jtcl zLryK1or8&79qAJ39LbGzh_sJf77@Xd_Ao8WV(XkGLT3f+k$%uJc*fTfE$ax>uPF>Q`>H|>>e@T}mE%ML;HyF~vC9}litefF++N-B|9Fzl*PAu#>l6XM} zg04u4Jj?3eWX*#I%O@5|M|-xaKEWL5q{ET_05@&HoVNEiCC$pAR$ZwzDi%S1gH=*6 zCRBL=%bXpspp=oieGP%dNX@YH3z?&4R?Ia+25&T>{e`TdFd>w@A1gM42UY+Q zXSPev%4~Mt9LlLx^9*NLH0~Qg`7K8)I0R;d(S^!XaW&q_10D80lV44EpJVnJO z5>ntXQ2|4bL|_!@EI}%?6g^CG+g!u@3536v)QVTeZc4P@ituRSN}tE2a=M*OZ_n6e z?Ua8t2%kjQg)!`7@N}Yo%aBh0%zw)MT>C+aGY(w2<#`^gpMcY{aQx{KeRRS2G5y$a z99HqQra?;GY@ByQI#_W)F7m*g-6YM+(&FWLE&$1si!uP@LIuc~%Da^E8Af@#Qr>ZH zye4tRZz4~8ah4X?dcOww*5J1iZk z_)?zFWuE^wuYmSZY31bkv;zwWbWu=k0pEkj)G(iZgMh1w>2j;pJ&M*)X4eo0s>T zLwRzNHO%L(G60C>F@`jGu@%2&9t#!ejH(OEaltxD*+l1!fu%=ro znrcQ{m0*KH4%+nI0z7O@*HBWa{%5!)cM zNj*?QlmCXnUVf%9-Eg`Ux!RdT~+ zRHQYo!%c;);O|tc*2u)QbmTE4#JBMfub*&8)c=|W;pHil=`X(j!CzW++S4DyzjS=5 zd4JFKc;plmh?ctaGn{&>q@n_G?Y!${QdiLt84HW97uRmd+aU&?2OKdWfb~V=1Aj#yzBG>zWD!@W zs26X2U!o>OArmrOq0%D<;B!-30ioVGP*4wStYVQOrkwql$AmsEcL zsyO@|Pz{wO!!12$y-vP{H9};KN(l9lm>wRvsDRwI8<0z716R&r|2!`|{tFR@RRJF+ z@Yn&9*62&C!PGYzjLy3Q5gw^drhWip1#5Xi#T42X=|5>%N7?3#rA)HdE57(s&f#EG z9QGsTV>t84Pj)Jes#5@NRl3$D z!E3>3h1)*kWhilb-7@;gf47(Uddk=wXdegk!9CC+T|($uYy-kNK!r6r$IIdIB%iwh z-gqtv)UbvkD?RjnLfshqrNPB=p-n2XeJ?r++4o}Gl*s2)NdHst$v8+6nteONbfJJN z=eYkaBKvr_E964nEB~P2(9y^192FNHud|7P-|>hNn!{Gzbv-h_0BCZBqi2OZ{0;>R zT~`%4eJ&t`;jAn=CR*ATZNLFSF|Zlwp~7PF0FcoDPR^F$BpF&DkLfFHl4ZmYQS5kll->^6(Utkp zauX57U=>m#b7lCP?4{8WM0I(nN3O`~u{~HjZ>~Jl(Q~L>d~u7g9a@`fo}a#;?hwYJ zVy#jr>Qr8Bq+b>G|1w`HDso7LpuJlv%#sQ{4TU6Nm>??3t58u_g`+7l=eT|v(N!^o zIxvHq64)GgRiVSTKps=jv(P60jwpePc1uS9ctNz>JqENY85tet20?n%CslZQR=C&D z-3#{cc#wc2$A732?JuV`##~4=zTqTg7MnK@&^^S}ImdNlj{0YiUB1?lw`KMfJ?g-; zSv`Kr+cD1~?SQa%0A0qFj^R~ukpn3Q*@a((CTWm8;!&W;7BpjIv@}cUe_!W?g{+Xf z!l*9c^i`1SxsOIHIdJc&QWS%*!mqtz_|@m}swda5wM$VF_oBVWi$>eTAZ>YqrT_i>0w8kY;-+Ha9iq zHk))CH4>bQh8D8$HSpZ>-l3RqKfIwJX=6uHpS*+cA@S@yt4qroZi5h~1pfiDroROC zk!t98pzg4_zsMdc7NlWzFpkO?vGx-DeKwAf|4s}C9(ja4Z-i}j29BEB{Xavay%2 zNp?Y?Pm|>5ou0cX;vv$=t)SIQM@C1eO5N9{u!y7?Iab6=aw7S~A#aoXViXhuZkmLR z_7of+Jlau_)i7Amo`V&!8qCE?9^Th~B5jtZ>Td9PDQxJ-h|o-@JlH7@&j8QZaI67# z0MsE)h%^l579r9b26KZkG?=_74TDup0Nt+Cpjze;k32Y69-bd6u|=i9E|il7J418m zS`7j%0W@+p06BEM|727i?($_~FJoIS!cYd%aF;Y3g)$bloO}A=mXf_%a8obXKT~@A_{~*?se-e;kHU1!d6247t-S^-pNw*nVWz0L)Oef0zzQ#SGQwpu zS4q0s1$X=GSVC6bQsLKpN7^n+gcL_woyJAyuczFoNeW8?br%nZs{JI=XC)hDEjlLX0oTep~1a?g42JZ_3U=i7Pf_ME`s=VMoW7}24YRI z!Qua=QOfs7+m$W@VNt;C-yuL?T?7IeiYq`MUZD1Y^uCfgTyJf|prhyv2%VGTeS~~Y zNfUxxOhJw#0~UY~@7CgV3l+A@W58aMG^rlsr}i1-FLq(B0SK6EcpX}6@r$QunRB z`rmwIFXNF2&cMjGTm5y`ydP+t?)#o?t55QEx+9TqFreEoiFJb#)<{xln6m*qfa^$= zH9LJtK~B}WK;|fs^Jkvbv{?6rzE~&5EY=k{uu#`?iBVozraOYgX4r&qU5GKub7Mhj zv%g8Ry~DIwO(B(uUK6Me)|>vokbvbPczzx2aMj7AxJ zJs-|FX(7^ibZK-KW&(j)F;Imlbh?iw@N!j+mO#L}tf?li{+I5sGRGJGOafFtT!y2J1c~xJ8pb7sHniLI2e73ys z>{ika+>rNW=8lLhXScNFrypV9l8$4twFVtCLe35zujmvRqL0){K)wP?ihXfbF>gyn z`@CT`oVU2srY#O23!ppl4$ex+*$s$0vCy+Ul9IU>Px`8fN^7+ zU%LPFAGLZaCX#z120G;_OG*gbhBRk_+}5(BcvM^jMkh&?N^p&Ztx{d}R|6QU@*lNu zoNSnyNe(iBH7dpyAqK4cJ+Ln3T&-n_Behv(3RKD}RnpAwkLUv(yf-%8UpqZ~OH4Y+ zFi_L@Llp>$QTl3K?cI!ZFSb@6tpZA7@E3@ph990KgeRV*^hB-Ya+RH$x2BP5si6}J zMrXy)KWD4|bX0t(j_5LCTs&R5nB(#^$Z{!iIE_6!C`CnJEING3?PJhTvP88;U!q#e zglPFG#aRI+GUIfN<3wjCfD>_>p6e{gKu$_9y)PC0*~t)e0g4~0s3d$9-V9PtjUlD~ zU=?bCnkqqQpL7yPJIWX?wNyTS<&YYJydh$61eGVWd#Q5=C^*r~;SbPSV@EO7Jd4b9r_|W;kM14U+t+^*+x)0~H6vi|W z>-UIJa8iy7EBN@ETA9w16&Tpi`L{GN(3eVS*t{RUPywrsq_O-iy+g`p3&<(IMrx3H zXg16-x=9T_Sk7hW%gV8eseo8b^{6qiyc_mW+22C_+E}*G&tua0Io|0eei)Q#@WUuh z|HZNVa5uH*oUt&O7+^_FD4Xe2*=zOh8vt=A53M8i^*5%-)f5ne9njxFE>2?LH8<*} zOfOMdGyYc2mvV+u&X>|&_qS0-Vesk`#89RU$lGx)kG8J93&Mt1Azz3~63*v9diaUT zmyiPO6La|iNlADl^~Esyd|uyhEzTV@D>)}YNvb~V;t9O-p~{QNHXE(0z%#0HQr0c2 z@+Pjz=`h@HROPc<>uNmGS!K_bF@(pY`Cvmha18bP+f-b}NndDM9x>7nP_B9wya_O6 zOGcQY$OJAX>G}2q)_E|fq7z_}YB0hdAX;OJ7jQwgi78CyLlu4?E>_PQ6F+>2>>581 zt0dqD`j%4oP2^Kg$30K)KjP#X@x5H$R~^;Lyc#~(MvPIJjDUgQOELm-@I*_&NDf77 zm*p7Es~?<$M4FVA8b{qRi7Uo=(qyy@@SztbYS6<+n=tc>XU&d4DxNi|so~er2`b|J zK=2(voKOQsv`l7bnK4}NU_1PGRX`Q~FJ)Y&@zqf#7$2a-D2HNIwY*8(G*U_)X99fS zUVOXH%LN7(&5SdTP2t`qyy=+e_3`-Pq*&Z8YkrT24^&>fgwUm{L~N20PE{(wUhB0a z{Tg+m^ZCdbV;KIQkIpnFSM(& zICRuLOh^kl_899X_}|jPYBonIVl0(pbCMW%ADjkSz^RYbMY?X)-(*+TrfEbB-i;U{ z6bv2UzqNWgyI`t5 zNwr6AjIF=YumJkg(L6Db7F+*Gl~aCo^IIpbpBiauzs*!Xp(X~tM1`jI?~LcvJe5XT^XJ7a@~0U52yo-&^7A<{_)(R8xX9_!2Q%*Ctb;)Sn;u@xI##!k z=4>-OL*Ucx8=YPqQsf@R$j3*K(s5(7yLKBf ziK{2e6qk&7igArr3cNfe5vx?c>pMc57Qg(bllj?ZanN?C(2IB`3^x(FM|cQnd%j1{ zbY&LMOGcs2wZU3tz!D3ZsQVeI^uDy3(o5C2v?Bqvzy(XbDAlh*`V!eyLSo$nP0q&Z zj8_@wyl_wzqm)y*FCW8wX(_x@fa=w5bJ6@#n9#XsF&7#oR7D$PO>QoNFb1GXMvhJ3 z)PfPXH;(s3}IPUGpGm|q7Lmz-=QU_aFXPj|&Y45b?}@nx%Q75z5Su|b~Tt;kyC z;Q4%AH!i@|Zp}3FBL|D|5&&a+S#(@1N^lv1ja=v6+KmpXny(}{#9$X_DMF0SFFs5A zMa7^EQ5>OX8AvGxnvg`@rOiWqb3&^U+UGRi@Hcr>ee@&NKSmj&CC#t8`wBw0skf2s zisY(R%ux6T!pnb#A*ft)(x2YHFy4F9`#}}>kit%!^9$`WnJT0q@`-W`RCzo;r{R>G2fMEsf02s@ZE{w zpH^|J>vd9|KbSc3?mF!lN8O1pKe zYJe)6Rb8PkX@gcv>X&;Ey>xLZDsd@xH;qz3A~9{I)-htTHt1B$^MP$9gV7!dT0XR|igfkWHC&O~~P=ue?Mq&`?#Hz?G6 zvr-L*$t{u?_G{+=`+fs*S@zo%^E`_}KVlUVuWcA7gb@u*IESq7MK02bb?810j>H0;}UNNwK+KGz} zPTh?|d}qbF?qItMqg~NHUQg^;hg(gZWU%`9Fb@=*Wpp283`6LMG#{>|<)B-PVXZ8a zD0`?i7nNz!#V1>_0M(vQO?1UPC+DBC+$FAkiSCj`9hfAHmg@8)&B#)m2Op#FGSe1c z+|JqerFi^{C@bnL>9Ga-6Y}b3eT?}NouMZeq&8QfHM9g)bu4n!0}6s~pxx1&t<{_G z6mZXU_hMW3Qft~a+%W>t|CNpdUy*8EtNxO;PTgPdBkr%fR96Q}`oD%GUsv6t-Vtff z&35YA$ep^e{3>#hv5aXXB_uSN2~xA6_BWc$n4y5^vF0*u1ESRxK8aFF+N=&S1l@ z0oxYprq=y0>pnyORaf?6@MVjEj?{%`(V^(!XnC*c)K3W%|57v=+gOTP?B7KwXX3vF z$glCAj3l2+x0rWC>~S4faTAnO%v_g>{C9|^n&G~`CGNR1P_L@;VsJmMhu65DMC^>* zKh#7W(|Qhg>y(G!f6ZJ~22p=gy9(OQ_AC4<>*y*E47UCg zLQMpy`**6ujq}=J5tl1pzEuN5y;HU?#HgPv53ylS|5nH5a3S}n1v49m4kA-!i>~+Yd?K{<# z*->1yBtAl4)xf?X|2B*NWRlP3t`h^V5F_ycg-&-v;S37ZP>A5tUQPPr>sNVo*pIAS z&wC_x`DzJHN*K#mv>$m5KPgU5xVQ_G2&z=`e(kB60y0<0x)#xfpRZVAcM z%pa@Hf*X^>;H~-)pNozO9;dz%1LF`InimcJgqw7LTHf|K?Q(Vlw)3as(ymB~bfPQf3G>eR}2=S$3P(xLUVl_Ibzg>@1afV zvPv17PBWS^Hikd>4+@#qI$D~SBx+I_i(LUn&w7!McIMJzzp>Q~kukKu$&r|)b1Dd0 zs9Wsz6Gv%V>_}ULzad$%KFdk$5`%j12aKFt5u%H$YEGj<=DQdq zRXxW6PExz33u)IT7ez_wJS3QbH7iGbr6@%zDK4x9I3ts~xMXC)zG<%8=%zyGwsJ+* zZFxtrwfKE(E&e6*eRXT`ap_+?YgGZK*eYx<9>itb7Wo~?H}(@>qwFWX4*Q8C*D0D& z`GtHtAm6l~81juHawAj!RNGW50=86GU_d-))kKvNT`DRuzT|{4>gLZt%KhxqWxy zRLIRY`DWry|66_TJ8&g!!{XuKAPJ6-%?mOT6{;O zoB#OzBkqF~r5$(2cQ88sdcnK=5{?Yl9>O(WY-!V9?_bfz|yvS39hl&}# zPllJ!K>8kbmV%o@F1KkRYzXw(uvlM_ich`d)JBppN+Kt}+5q&-lC+~;Ds0}kCAGjq zy7j*NNspWmMZda} z-(UbGlXA|cmWWK>>n6Z9c`5H1P@S#}itf^Tintkl;7QOAvYEHcpovyz1WhciU=fqG zQmIV}QEx6L4Ml3%RcqT#-mlA#P z9IZab(=&uL&ZkHR3An}uYNSc!Dmp}jsS=JT6kG8*Hc}`+V)Ru7p7El;j~yM$Z-Yft zI2UgyM|>bFoTIRV_<8_ew1aUW%|8WbIPDm~c}X5vgexp4&~`D60(j0pMD+zc#5vH< zq7+cL$3Tlfs41KgjTB<{1VWlnJaDfG_8w(}IjNL9Xa=?}rHX3@b#Jys2b9U>r}89c zj5>j@#mcwwth)pl!HtYQ=nKqsETDiiJ)v+GN?>npP-!4hS998TR7@V~gP0Ch`#^U* ze}OrP;;)Ic(rirSJch}CkMHw^-=vwR^2h!6xCx4iYOCb$hL_{@Et<20k0E5nn(t=Q z5l^Jx^ajSVtP`vQ1?ZgtR^h6zWvFV8K!KL?LJ-$rE_H*6da-yIC8ld70x3obD7lxY z6N2C47x#Y>m(m}CeT^VhL4Tkz>E%-FE-S_EGE#+noHSIS(ZpKh*Qt?^lN!#3bx8SU zoT`}5mYWbl6BQv;OO{|vFTnjcbDJ9{;Ym>IiD620{yHc2>|n{3w*bB`F}Q%*e-32U zItKdyl-wXOnK~6i&RRNF@6a?yS79hid@rq`;ju+PQWa8pH$w}{(5YfDjr4B}B1-(x zI8~dFYxt4ZVzqA7h*FHFQkbc9{M(6VDV~lHAAk_b#XmbAv(98l$+&>8#G~0~@+$gT zaquulEihI=joKSpvxmg5Fd96Fe(Wm-=C;CxzhP;cc+VXODaTjCe?(Ao#lOYZ)8HZ- zkK^KKyW%~;Of2CVTB@pU6Yh6kyp*VkR)7gOSLu7*$u2HM_s}BbXz<;5bB|!q(iB*1 zhrVOZrDcIA)BPaPT>#|(NIHUU$1@*K8<#Oehvf9>=W|VLXbE)zb%;rW3SuSx#$sPi?lz%)l-YAJU(Kv4G#E)N%C}bYL_Te1^ z*&+|kLK2K$REauD?L`o@(S}vRS54Uxn{r0217kxYnlg(5b>rnqbreW7s(2NE)M{15 zBz6W8q!rZ^(u!J2POVzUy`w#S7T!&oKf*o({s`NgTmSrL@;OwxXE(4v z-RPTD@5RLo2G?lpa$JeRINN~o=uLthenknlK;T4!oFcYFM{J|EY87b&j3vDRHpYfa z1h$2&2?rL8Qf5(0q}pJJnss?h^~R8?SRZnwjUU{}kb1$6kxt+X$napG_xw%R!t;A8 zs72>`dhul1p(F-bvJzRfoajKs$gt+8b1AEvM`3T9P`A(4pQR8ZTtG!syM^!Hg>4+z zkIq)?mhij8A!eLw3AAP>H6z*C$8s~QnD)EC)UZczpp#d@l@pz`9d4zscF(&b=Xhu} zANMs&N_ooGH8is`TQfA#DFxCbG*>Ach3{!|vsa0XsCRi2gb*n@(zd-6i7$dhPF3Oy z*m>LMKG|~H6Y{{>jf)b`)N`~f)G^MmE~u!o7jeZ3E`v*U?16ryy+oYY{01en3#ajAmDOKfM|<%Sok*RQ2h9f)QlQL@LNOqp^dY zHatnoVcf8;LIy=+AQ#5iEZ9S27n$rgWV0ccnoYgLm9ursM2R?=$5wI<#-X*+SltS! z#Tao$W4&fPu3+OAtZBaU(cu?S0~eYcQIU@rp-G2G5%5@{p`Gx&%0xoboe~wHImao1 zE?NSSlpod(yU|M^X)%!mqlGfwsEtseo2PSLD>8cXb{Qu&M@Jke?=_d#)GCoWL6`if z)0)h@Qj93nA*0b@O6?{+8J>rp;S^955Z|BLn6AbtT1Q)wOA&)B$k%dj#Hej zK_VnJ#sRb3~@?9R7phHWmkxH?t6K zMGlS_J{d`w4MMzxS7}q`HjHceI7Dt;f+MhGV+U4J2jS8bvnywy`Fz zjT4Zg|LdI2rIgud<3PM}I>!uL>oGz#BV|{zx?{SNdd^JBB;??XCI(K%@>B$`yyIfo zH(3mJ0+E|lmC~%LH{+`M76AJbe~N*xVyoJ%Ru#)RYXGrD&Uug$e;e(8pvq&2Lh@lI z%14ALb%+?)9*gNldgb~_I>Pt1wFVw>vlt?A_@Br~)&bvGOhQqs358Toqs_WQ*c6QW z3<{uxqC4TAxrW}Rs&8;;s_B(H#_;p1S_J#w7uvrIM!aoFa#ol1P$0 zq4^Gi%P1FIqOb$WEJU!cY7*kRNHp0p^TVAjIT7m3xeVbTAyzxHC69s!=PN;C&QEje!Y7kR1rYkq(0ZFsZaNK55j+aG4ko`Fg1%sE&; zXBD^o@wR%en}xIqgX-|Wl5nYVnc#RywWHPu;c1OPvzg^UU!B&F*G)qDTuZF-CWFYV zyqm~Cp|M8{93gAQ7&!OQt66yu1F$&dO(SmjXne*Cn`fkI!*p{Enn()_9cr9MzPhkT@nF!I2L)6&j9n_A>q zgWTshp@QojvtYX8Ho6m+?PF`*En&8Qryxu_giM5#MqEG!7-=&6k-dqg?E+ z3%946uGt6w5nq2*!DYQ7XNnU}uHJ*xtE$PTgb(rM`tfBG9u?^vs@{pnkg`MrDjV~> z^@@PsM=K}Nmb6Cy0YTd2|JqXhl>q&pb~J4lz2YbVJjP$ylsAX+=2qUkQhoJ-Dilxq z@InUs(i+pY+#)R?fN3u_;TKHU!g!&JGvC(82|_mS1BbcTovn~*fne&nl<<1dB^Yu; zb_x6ONS!EsAe%1e%c%`r`<4I1IB|hUAQ#CQXn^o>^egZ=LYi-qvs3t64D2xi(I3r^ z69}4wg!iFjOh!^kaT&=-55FFtF@lJ=jAR0a7sqGZ)I1|iJtEU%>Lrsm4jdV8kwKRJjm8-0BHR3Q{C$Quq_TAsVxm2A(I1OF3u}!Gt~lwQ}RyxZisd8 z(p8E}JyobT-dRgLN71oM&WjL*0!tDU;ND#-qSj!nPOd_v*}F@F9QW?7;DKhVlT?Z7 zKIIh|^WC{>bQN-d**O!PgK(Jmd@T6pTuMyWWyy0cB^3Rk?G8BW_zP8yOY+VM{dm8U z_&V*U)EHww2+=dN55N8sR*bThBRmHEYVEtd!`r&2Ys2BT(CxHjU z`SkNRk^8Us!R|Ii)Zu5YR9KWdER4-p{S?mha-l;81g*a8{CXdNmrg)nBM>Y{EylZ|L=d*p7?s=-@yXv_b28aq_DQZa+c4W!q05QeSP#=1YfDL@87_V??yrm27+|irGnsbZ;D$C zHh`UBTQ|?>)-%E?9Ccbw}I4R)H0SHNR3=pUB#<#&_;~hKJ9efxC-63#e zX;-`+5x$Agg?nhd0!rDvt_&_-6js^^vW}(sf)Rtw7_Xv4#Q=&f)iWk+nL#17J2V>r zbVo_Ov-p)saisQLVun5B3^a_S={eyP$F#^qQ01b(ThP(vXl)T(Qzd+>WqY`${#0e> zuBndL3P{eV6G^jLb50P03!$CN2ofW!{1>VsR-z5z*uPP#AE*{z$G~|D9NXnk@FgG{ zF+Y(<+j~u06Y|w~qNWi~?sq$46kNF!>7GC7Sp;xjryW64Dx#Ih10gY=*JwU$2EJK~iW7j9G&nnm;QQON99Hb(oG5tNGOZ zX;IV>nrW2>TjA(^H_R=7JnQxYDw@W^tz)ViZF7larWUaxzN4@Z9L~ta1ACMJ}xcVV8~@|Gb)J zzI{5F(_V2g)RUQeRF$vpPMm5DAW_7grh-A z+((KkO!tYYEmoNh2XkqJYxHli`kQ)*!JqI(OvB2k?K&GaF!!~h#-Q$s54F6vA%_%^Zu zb_irr3#K?S+ zlKIR%0v(StIEy^X71T_J5$&aPBF{a&N=eZnho@mdP@%+UDb$g-Kme`ceSZa`qE~%s zMC4!?D`iUk4!xxsl6n)v`}JIB#?ru1+61Ixu*5qZYjjV4J|59Gb?9gA-QNa%k`DdM z-S*p{M`xtD7gQhBPJ^v3w&^9Y1FKX_*}eibmD~D zl0rC#K|ul6eCUV+w@Dpigt9YBvxZ%Kt~hYB^&u-hW2}*+VHck(4jefy6LhLtdOFOt z0p<=0(=_tes$C-uA6tG4sx4ATO#WpT-t%7NM zuEd0j&lL*`Ul`EG8|iyg`~R``F7Q!R*Z%kf2AE*r3=$#LD1(felvER&){LHTID6as=es-!C?gP z1p$Hif4}>2=A6mof!g1%pZn{4K4;E8`?2=gYp=cb+OM@8S#EB0g&c8*K%>I#rdrHD zn$ez;x2%i8D>)g4Df~-B$0QW7(VZ&%dRPFP8d--0=)#kJcI4~?gFK7wFg6gyhKQVb zgK>$|K-kQJ#1oNphc3Lr9xtA%x&Xq^LLsm#NvWB)*WrTc&Q#JC9kWY?6r?kcBo>4h z;2_8t)t$>5a~x~RA#wdid?lr#nj@*M8(9LrT{J4zbTHQDH)4K#Q9rB~{G-NZFs*3B z?-D*xKH9VLUL+d%2Q+plXZ}T{BRL-`&jyV=m(KWaWLgj^ukJOtok6a>9LS7(97!W{ zN3O!l$w$OpfF0E7xOGIlJ#IaW_&b1^y&YVE{K2~d+N++NPn8l~g#5shkB|ANE=8=O zmmncmW{cFjly4AxmhR{{G%sa@p)z90DSTH2qu>A5oK9BEu^~MFb^zjG^V0O$Z7iA> znngRMMmdh9plg5*2KEl z;XGqGr(F*BsE2nndZ$SnIWvJd-GaW@!fUMByq2+xw}3K=|Ft!Usi2f| z5FYoBvJ$kt3JM5aAt6aTr^PA+tg5=$?&C1lk8h5k)$WPtN%9bnn4t#`2c%U3`w*gV z+$9EF*L{c?9g^8KAQ6MBSvp`=s8&~2J2?w{RHN)ff2~J;?n0owVoMn}CyV*4$T&A0 zz0+)IQgN+C-Q9~>I&-5GMkJ0yjrPQG5yM>Z7oZ^yPtfD(PGJ9U38^C!Him#U(&&RU?&p@nWd>ha2@caScryyLveOTKl z#d9s5CD7mW^D5ljI;x+{@B0y^pIt$pPd^d(>qo=ln{YB=xW6?lzBMeqH7vd};dKV{ z)57ZrW_RE{3>@9hLVUZQWB_Ug9(NqN-ErtX(Rk0JKIem0^YG^LEx@=4`J97?@62!d zb@%zID=y(>es>p+j>q(Fd@{dvyzai;>6u1V zPaMC8ZoQtk0NV*7;cK0h#2RJ&V>RNy`UeiUnb@c{Nm)i&ro8DjKW(&ySCC5!C0wlH z>iJ_-`qD;A==C7H>K8?z%5rW@1=g$hKVbYZ;cKNiR%Li@UWtrVtBj0Hy0)SzFp!?oC?A;`BKFucKeq$*FK={>FKvszGoLyX__xq%ANP&3<##yv@_I(*wXeWZ#BmYtT2X3QiEe+rUkS#tfRxohu z;9}Y%uo_k(cLaviToi{JoQujA74N|EP%(h2$0!0Fff#O}BM@&tdIO(SMp{;5JOieT zVyls{YTRu(O<3jNF{J>CQiwM%Ei2M{B0v!Ohv+XsLk0?vLGH3fRw4@tTCJ$7G~p9U zqlpgoQkpdH$i#xa;APzyN^qFLb=j@a7=n@&Z@T?_p>1^;n<^P9iwSfRwlE^}u?vWN8^QqwOP%=lj?kREzSH-E~|@ z{w&Q8^&Q5l9Ia!9xH^Y7R})3$%eLcx6o^V7tr|(9sJGzDgX-|OXMFgy3@dgu(Y~+` zxnaB*F9{e)3WsYkx;jmct}td$J1j9iK}O;y?SmDfEqS`Y<>3l8FYJ!S%drnufDh;H z^>NPK>p0IgS>L?wS}S)9ND+qW6L3KJ5tTEXzeqb*q@Bys&gE$*$LsuI377E9!`QV- z93{D065}dxX5mZ>foc(hCj3PJ#-}ZdKSHt`^U1&9l^o70!^lY#Z+=~3@e^q4yjySa zO9)=m3zCr*jAC2xrKOh|Xn{8dVwV|lVm2B+Cb}Mh7jnM=IkQNWha%N_S>GDB8|e&l z+?(z+iCg|+joT&zo_7aS?l<4VSwKl89GE;{J}yAI;~oGX<%o_EMm$%^r}g!v&WL zo5A^-(kR3>Q3zBGwhgA8FDWPIxf;XQ;w$lZn4Vx@QCi6n=8^Oam^H3$WEsj3nKzQN zQjyss&&Mk|!i}GI9ba&r6#CO@XVJ>IgP7T3_dx27(n1E$W(A7fF;vash>Q|ElrF); zY3C!#3EWv)0A)!@R0xa0;!P00_bvjd%MPw%%(Bg8`;w<=c3Xyx#Ds;!gflMI;s+}f zCj6z9&qfA9%fSw~jeb)`N|xY0AZ&O5&3=K%X^xh3MwW%H+{seI;l&#oS{FRnQDLRX z(7j^|idhdV`Gd1jy69Y@oPa|*D7=|x@y5v2qEp=8e7r})am1@KVtu|TT3!0uzE(6v zg2SsGuY`XkTm%Y(GU!nko(lHi{CHSTi3D@r!;vc{L0zE8OW^{Ucqfecfm3#DCX)bF zYgh4|aD}c4C8^y_6K*$OAhMKwQUYl+KCD)DqT+frS-ox`b|a_b+)D-yqbY#;#sZ`9 zFpDlW#6VaGQ{?k8(Y&CavM&9u{WnAyIS+nDBX<`#Hm!EpEwcQgeQ<#Q_cvf~S>u_q zNUFhlYE!gE&Vf1j*gYscyN7Bk0DDor#*6B&5n<%j0@a^0t~S55!(NV0DOa?du?Is8 zY3o0vN&L%Ck!Ov(s-Ajx9_=E+dDNsOEC*8wZLLJe*4MR7YGwXtt`gzrb=w`%)-WrRn)lb@eE?IU+ zQ8paWzujIJPsu8f^e`Gnas(!82c(!RVbrvk}fD}!=!inq(>G2`2w)DgFNe8<@DJ) zd5kt`7SI9g?u0?UEE_mo1_ilQyIU!9A~&i=sTXMnby(3tV5sAwkxF&+SlO}=2aiv} zz!Ez(dGI)tdEWS?r17*kZ#+kx7TXV_^pQSK^U!hf8W7DRwAyc5R7Z{l4q1*I3phe@ zJwd%xYf35ixnrS4V9byHQD_oMHR^y;-db+aEau`Q)Ixem4S5@@V8mK!TILb4ie3cX zs+opP_Fc#%-FM2xG!NHh=^yR8KN44`i*~MMuWC%mFK4eL(e8>eB4cB>(m*(P0~L_I4CAgapt0poIf=)JvE;uHg884-a63`{I30RuH0w&9)^g3Z?j zSf1ggLJoL?n7GjqlS7fd*Y#pNbM8EtW{ZWfV54F#=Xe&2xE}cdRf#$ttQ2DPuiOVK z?LtI_5KW3G$RD!_`MN#y-hZ|;87q0Fqkb;4a0dYx#3f4;O29;-HGbBL!fdR}o7yPcQ>@=y+m#cOZLi6lY%H$uBaoLMMaG$ybeH z$UtqF8y1|5(E@_-3&F3l8P!9FnG?Z2c|T4-Fsgo~uP~q-Dn$rd1zWD!@Twpp6O51v z#0!l?w^(u5vRxA7TgB|wNN@)e0ET{&J zQ0^R3p+%XYf&<$1HC}QhmI@2BN~^cJlLYIN=)ou`_lTQguG1FXPE|((IiYIO`8wfY|cWwAj z^L*w&j7l+5Y{Cl?r35C0DM(aZu7qz!O+O4T70Lp+L%YmmgUkdA17f1%#GtEUC6)^W z1@FO&Lc+QX$3$aq9BMfH6f!WzZZltuz4KnfVV>MK#vbViEo@*y1U4kXkh|bBFMZ(U zJf(<2Dt#)f&9>Mkj4|IrZ)}WhZBb)#vju%6DGAW*0$|0C;(zX7G&>mut{ zE(Su2%|}$H@tFr!^oU%o0i)%VW(PeaJLq8$i}ocr_0V}11xDi?q!O;LU(paDMI_OP zys@gDJz63!jsp3T*Foai`wjyl1nz@P_FHhSVaSRe(He9mr5N4#R``whAK=Mvq{Z#% zMx0|ZenYqQt-xiuKg9Qn&>D=xeDZpBVbZzOz61VX)lyslWyHUa4-Yo?2xK@3awUUs z7rk|HJQY0^m-q0po{QmW?*>TSqd<({Jk0-~elR-Xd6?rk53?E(M!vy1Yy2&oiFxWE z%nthzd@AuIx-xbfQsVzE2T0)zhtYTlx5{OYqt1!pZkLQGAqNbkRr?;X!+r(*yS)Uk z*vsADWZw>_xQM9zaFwO;j#tE0L2|OwbzUW)&a3nWLu9=v2;CC4rEr6!GfEd5H_Iv8 z952O?IoX-bc-H@QuRdW5ajq$MyRf9zA+0?;EUWS^pWUL#X1;f z)xU|F9p11T|CoRhMwnidVBEz5@NMvg;JFU3i=+|Oxih3KLg{I*1p}vZL=Mh?fhc!p z3{%8gFwUt;;_#+hYq$wnI_=)R64|I*GTKdK3SH-?WK~BiT2lkPEoW1#ZGf>jhLAOf zFX+jc=()EmR+WRnj3blAs#4as+=A;=?kt};HtBq4rOKRHonapb_9|nk(4~j1Ud=#> zeLdfomHq=f^#3A2cb0Wu8IEdgrvrjqzW{9@j#uDi#F8YToF+8`YMQ6D3R)%FQdJ&b z2o+}rb8$5e%4O|%!qQYS0D zRQomj9Cia`y4C!+fRWk!!1eAngimSKdzNof?W{fslB;F04WTq6El1{PUJv0lx4*7l zdM2?1<8BlWd$5$plVZ(Bfv;$x^3It^(8|>YV(Fdy0)R|PG=@D*N;FyoWaA8)|KTln zH(cx+wt$wkW_?NQvgiKs5Z}T z{9Tdsb%A57YaAnpBIem6x5yqYtSZnw%jF%KqM}ut`g+jb>7qbOGCC+LsIC(2ohA+_ zR_U=H2K{;Vt7sSv$4DO|KEN*;2erD`>H_L^Q5?l}9Zzt24G1#EG8-5xi;P$*TIZx$ zSOg67qPNuV7?D~=T3#Uc?7(f_B8MOkE3g^?OqA!cJcrs#g(|LCVeXxsvqAFKPNAmx z%mdYk{TP(!9I}0nAb)$5LF4&gM=IICo+>wdW<%So1J%%~BB(zaWoktF+DVhA=>;h+ zu8FcTnb6nuC5+Tk*C940F>H*6KOLb$ofjtwRU&Iyu5DMA87K>;J6M*PD9d#iT;Jp= z2y~EXbqCNvy8DsjXmMXdG~{u}&NCeoHa(d5r7jI@|UTGyctDc@Agp)wKEe}PWiC-~iOMR3UDTi^X|7l%9w zt|yZuB)Ie{H!KQ~emRkoNtMTij-W+@T&%E!H^_l14L9^e z1ZA<|2#V@hY}jEZ@reoP0!3X+&quq{7jP0#7|5*$l~AX0xRR*(BzCxuaeoUhDOkQ< z%h1P#j%6My-fA9eKGp--m1si8Q*ea=Lk#Kpj*PX6)!rIw-AZ^^CBH?SQijF%>DZAz z*3G=2B#g#Z(qqm5>qfsd;{1*jajfOWJ79`e<=8SdfBs3;taUN(8dSMAh`iVN` z8rlqqc;^q3?-7WbvX=kxDO>=P^GfOs2ov;eY-T72x0yiP6nZa@7QNczB&b@5%(?{l zxvv1rWd{3USn&c|JHtlrx*b;G1JHqrHipc&o95l6?6CY>whpF)5P0;K> z4{zxDNSQ{85HYL0za8 zS-<)y8)1ZdfTVytMoB?A;hHCK0!8Fx5H>JmbYpov@1s>hyn_q`%t~=oZKXC*{ zC}1|J0imJgW11??BluoP?vn3Xs3XEdq$YlFKAd(wqMQ($UN+ISm_`dodP(4{G~q4` zs1M8l#3yjGrT7Kxjk)pouO55sG4r|NQGQQlOJqo5 z{zq2LN4R3$Fl*XKc-;|H9yi;fuVdgu&?q*SlrK}1Phc=!wxjGI_ZxtqL3Q1Shxc5| zDiDH7YgD^q(f@!ZoW7^5mMa0)Y(G5en-JjmVgK_m#!9aj#NNInb`UokJi%x%P9EoY zS3{R3iyyuRo^_i2Jt(8CP!Uo?JDz-X+8kGk?=kl!{L?#)16lXw6H z*+8u15(;;LO1rC=$I(ku-~&!@Iv&VX^qTTj%d!@ss@-GbJi9+ol^Q@Dz`M2ZpcfH< z<$^7&GNAxrXFpX2@p<ax}xc13$??yXB=ANP*-Lajwk&j667!e84%uL`X3 zVe)1uX2Eh+qc`xywsCuxP^?|Vc5dJp2@N=V z(Tux>I`!DDO!hhKD7k^S6P*Uaw-4`R#0=>=L|?>81oyUON#|{;Tk;dS@0uOKTlvqi$YEs)HqhM;68&mWv@SIS8S z<_}0X69uuh14eAn1@LS;36}{q`Xae2&PKT#kOX{ z{8%g|Edg4|FNsTMVr@kWoNYS$k^^FG=S2D^^rZl=V)G>T<+NXxIR_xT%Q9VT$N^rp zscd_3TzL1^czcV}M|&HMKSQ<_H$p|RuRIzAa(AK?$M2B^;y%w<+u#L##V*f}qx)H& zK`77n{m>_25biaU=VK;`UWID$>@XVCu0Yrp3BzdZ_C@BJa*rfUW@g_Q>8^^NY1}#E zi%~$ibpcQ}u-tVCFkei}OT-SIjZq}y`#iro2Z8S!Bbufd0 zZe|4VDH=_C2kO={;4=1Op-y*KQI;AxI`pbAu79zrj+zbBr4>w=GOH=W7-V&(792U# zs)3D#9+6XNYWkE8hA3&owk}wUvUV3KpC}LpLD(kshv!h94iWH2dI5`Qmk2mxq^%2n zZ`To|3mX!>8*6t);}0QSA)<`L|77XIZR2C|7qaf;NCX4T6W!fu?z-BicEX)L}P z4aaKy)rgZJ!?E{D1Az^?f3j?Q-y-FrFp_! z=ggzYR2kBuuH`Pz8ojN^{xdRY178Bo*uebq+TyVHNM;=47s3KLJ zmc-5-XtC6o3tono(b$7m4N3NQ_TLpIR=q9eW6i%~J)5U;el!+k;r5TeH>uDxDIWdiYvgiCd0iM?L!k|19n zs>y8TUauR>aop#XgGX%fx`O+>`XHx|08$B)HaJN*4HltqrbG9%4<*fzAU)Gsz7iC6 z)HZjJTbT}312V}zT#}vZ?;Fc2Ta3F_VzSR(xEFPx2G6b|S={1LihX@ZOFlN&x6~g+ z@u0eft(q~`Wk=0>D5T8MMfQ{LrBWR&l_R+$aq73p0?2mG40_89(lIuL$~X+tD(KL3VXhkttC>1H?i@ zVj?tLHbO9J;@4sWQewH#V&(EIPUKO}1s4&mhZf z>@+R#hFik3HZg%Cb8I)QhtNEPmaGKjngGQbu@ah)P^d9F8xJk^4ysNJ0$i;)MQ`Ac z(KY{ZObwwYN_epmD}&L|07(j2wMP{RM8#{FkIfDUMBzwVtZAVrdTpKo_Ra7BH=!um zwpOt6AX!;)#{WB8D_H8xtreafd?5Lopqmo9+{S@gb2tN`Y}6`LGFF1m$MduViD^PzJLe$4ngul47QAE*#$j{PLbs zIH;cXRd_pPM45$L#8j>5X@$IVc2zSfdRp;v87KpeyAhJ5r{zW)cFlZY7^u5M(bKj| zg1iqPqO+^Iq{Cg+pSt2R1O^%?C3y-&K^a(|XlSfUF*C&=Ju}5HEsDfU9*|`}=@72n zhL8){2`>T{TSD%{Myv?JCC2X9x-~lxEz?z-zrrmv(1FKoKt?D9G=?JikZAUFAcG3? zoNq;GI@uCL^kv@I{EzLlu{Hzy3^4ihz4kot3&eGbl2DzM<^lFxCRXI$0y=VXjnPr9 z;^pOo70gsAtuBr0ahX88TznudIZ0E+U7pnJfOnG<2_Y;|q=xVSZ5ZHkHSa8xqF-E+xXfe(YI~#kl*7^!#Pc zyaBUP*vjYu#3cw0-MJx(%WJg%3fR;zodH01WMCNO*GxOYk$vTqeWLZqj@pO|WeUdU zNH3OHm^t9G&?3+j18mV@OW#uv@~m9Ibn z9Ua_k`5wk88G_S2(;ozlMT66gMhK6b2#%6*F@#a|%iCaP6DeJl>~3U&1u}tnxf%?% z@o~+C>xlM467zNdfJr@4cY{+Sh^9DoKAahxdR;n{5-%gPiMi*mfG@BY<4WDmAWg&V zq+t=Hp(3-&krFivOchFPDkGHAP+amH6vrT*&y4Z7(0JnqjmGQ9eNPFkxAKtDNbIa} zy8-#c?LAP5wz&f9ZYkcmcrlzY8vg)%tlI)M84A-YDI@-tOvXlF%`bl?<#4jE<=E$zUaY6P!BhZ#`RB89_Sq> z_LILx4aR1F%5%2Vi=qAj*_wz8?k%gcOO30hrp|Dc2ZS*5z^l z_P88?{gEWWPOeEDDLf8ZY02vhz-sc%2}PP95nR}yiJ`gInowkos)9v^IJ5(Db+y1C~jh%I0*8T}oJR$jtn+YG(CxBWMS^lb2jrQL;&v4f=*! zTAI~UY-mgiNaTj0YfX-^czggQCoavG=Ji08M>X z4=>WH)037U)CWaUFI2bJ$^uW8xGW3o#lq^y*Wrij+~9O(-gnqL@R=qX}jGzOEQ-k{@L@Nt;t>3i0{nXyvm? zbsHB)(OmMGLRm@DVWNd=`8>=mpNDlSpR?@-bPC9Wz()KUU}WEmKkY9|mg8kYyVMnf zCA$Oc>R}lpBLdBBdm`+&(|JHJ*VVA?<#?j}*%KvDM^oCK2#;k%xIHt1nGxZo%nGPO z1oL<|ST4)iDo7|dHt0?t0@t(8z)Uk-kYudC^tD?I5`C&CovweexllJ~$o(%v?t1qa zHldxW!*JYVSbzv4*TK(dG#FRk3bn)Lfrw9CDq*eI=`}v@QXM8?giQskn~9y18KwFg zBB)aBV%&78TJV|XO2IA}T=^4h(9Jlw}#`O74j;3IiUR`h$Bn2}w)n8`J#cBpZ>f@+aMO)ds&+*&hm6KhZ!w`p~( z(RR2!Nc8_PaYM04Rc;TQ@s`-@P5lR?)5={?EL|D#Q3$nf#UCold(slzmMIP}2LfIU zEgcLc?=eiaw@U*>O2oK}F_wrJ?WBy3vj~z++>HdRGDs_6ya2&wkC8A?5gb|7win7j zc$27eLr0O=P3G_{vsuF$vIi(UGENq1JmSRlRqmk_gMOLM?o6qAGV*D!+yTZ2`+Ge* zp+r5QF9dXB70hJx+X94;C}e*RUfJP+!nAtovwL7uFe{-0ycZL4SmND5@gE?VlM#h5 zYxwaS82QMat-vpKAUAfb=bAo@`V+x09Z{CM;_WA~k%6Eu<;Rt2`yuLt`vC0rvGSK$ zlY`cUR{l!9zi7eKu=Ki2?8V`s_mj?_hHcn|Q#rxp)Zd{N-vRamtQpmCEg@vp2Q7wN zP9h4K0?E748XFV`sTcHjY}nZ6B8Jis&thb~OJ=)02%p4#B5;qj^~4!)8t%y2o!K-j z&$#EaoZl1iI-(0jn*HyP*w&HH=r7 z)u~Lr4Iez7y|}u!L$vzULC8Gc>f!iXJBcaBY{M3;eEVF)L3u&*3OC)so!FMu&RY#> zEPbqp)(R?OsbGgEu9OP6WF@jhm5F&CEHgDwBy9tO@jTELyg~bD2lk4xQ-Y->1?)FE zZ`X}%A2bHc1U!Rc{|*VPYQ5Uz6onZ5C&nnm=x2B%erP%3gVe@d&ybQl7A9sSbm^I7 zHJG1Cey1Uk%D9M}f+Hhx5hK^i$aWIpiBW-C zZgZ=0SC%4dqQ;NIgDhtmQnZg|KM7`!wH#%PQpA|n4v_tTY7XNNY%gK-%>H0j&slzt zmZt^iG7|b<*htL=WI2-&0*!TmS^W%`Ku|0c9mPS*# z-FW1h*F@jwM0h!~QyVEFWbJ)T(yK-EZ0Q`@jaH7nDst$ki;59QLk5sPWMc880Ft47 zbjWT0LYQ9?FtZ|lC)J962=7>WP#)U9pzO)6dECP+wjdVSse|6PfpLB*;$&dXL>a>< zr4=QZW==3&T+Y$aZc?BZgyNOrg<9;05U;LdBM=~Ws7E~6mw-hTgmVZ1GAN7e`GStM_KT>Q;`QvFvd4T6jb5I_bW1@( z=6Dy0!CShiK`}t_!2I-gjro2pwo70VR19dv?57&mPMtixcA7p)!r4!%&{j?GqME$O zd}Pq1GQhU$^styKpPV`U1>)9DpPFeX&H)1%QFRpSJ^7V2{^%DK)gXN+A+4Zw>ru1R zoJ0v7dK3^Tsj=#qN(xmN9>V8bypfVgVogVDu{c6!W~TtnJ|B1C=!&)1QtI)Dn{n58 zYy^y+4J<+m0k(kI{!}SogxM)LbCXH#9b>00xDp{ncpT--+^C^r3toYJU-oJd_fqC~ zv^rE(UhFv5MUS9`Y9i>h98Zt@TSh?l`Y4;SIvS@l729y@U!v^sj#4=n*h*^Qz$tqU zWhhnm-pk;Vb(Csf3~3<6u-rV|Zv5LGve-P`6=Y%B2IcH{{EI-LT8J|}^{d4OB%|@? zFQRa%oXAP2xB|?f{t(|frXYs;;52D5y9Lp&KnoUjbCrpq-Z<)d2(v2v5kZ+4>czO} z>A-`ixXwqg?aTeSjjqWD@wG3c3noaAHmdaRuAs~^r>6xvD02Z=SCyGJj=Re2!)I0* zQi9ef)YKfDP!n}>|4K4U{$24MI5;vnfSV6?u)*Bwubo`ih#+@^!ICql@^Q=IL3PXF z2#+!#3>W2lys+FOn&r|x;BjF9TZ7OSC61ugXQ$PPmgIo|Y{ad@;kx=vbT*FDt)&u~ zME}E{j7{OXA&CZb$*%Sdh|0&OYCy+Og!WWLU#R7WQwkvh#2te{6t2WwKm<|Vm7s=% zyer2WYgwXF;GOWt;h|Uel#}xs%E_ro{=|YO%!vI5+-8f*@OCSZB+2v)6nX_F$BU9a zk+%{i=?DY@vILuy>k?BEzQmlP*yB)@$V-5Jsb;&!D2%(t#}4!4aA?lp%56qWES(}r zB5z5hZQMN-Juyx-?!_$)3;OxY5&dJ${>m-U4*<1lI7Dyk^`nU~0l&(e0u&)5;+t>p zr(5_EZrTE(5W(CwL=p<=Od0G*XbgBI-fH!iC2!ENYNO$zACfp z(dz6xfqKwW;Mnm&(F$T(KI<0zI~@FjI{+cse0L&nbP zs5D=%8zncrg74k?M3k3k3aaUL)60%P3$Q;y%dlsltFs3}0NDNcm&-pt|59jc_7VOq z2TMT&@m_~tBZ+EPD>K>^LLU~PM&lcJqZvPfmwgrgc&n?;VZ8zq5fR1Ki}`T6n#KL1LYH3AQ<~6bhqiR zrSuwuzvO_Vk?fZ|DVdw>V{=6=S-}FM9D2oocZsOp$@Vi@KmLhbJAeF9O zl+bAWCcWfM7H;J1ag4v2e;fF>8_{hp$TPWJL$5#LPXYT#025874Nf;8p!lW;H5%__ zg2wP3eA+xQYZvj4=2mR7cyf_Fm>wtd?;8FE_}3GEBGa9WC|b!V`m>d&?91U)wN(LU zM)qM5YBWBL^vIr>x?_l~nf87LlA_KDyzc^Y$_#M=udXB01^dlC(bp04A;g4Mt54u1 zPq!0*n7mA3$Y6ybVY>5o)gcFwx(@GS^1jKhC#NT;Ca+9RQh>VC1|vlP@=``N$$^9* z5wcr!X&WUkOMAQRcK*o0q{92U41mC!Lo*dhG3+Uob1Bi)Xd%BqXywO|Ik2GDK_j`d zqegPvJm%a-gxyJm&qt2fi3yZ{ zKL4b_=fML{Vj_ZY^t&UNPas~l=K}C#M``})|9^)z5B(kMq$57r2p;02>s)_ld+Rva z-X|JA8;pPYrR(AIq{XAXeZJ0~zF+qF{CM1XUWznbJvzRwdw%~`J#^Dw$LZ)j9V+9e zc_txUSI?(``+2143a|gu;hAOXPX0O#>&@-%s2>06-!-rQBhcu2=mXgv-Bxv5*6*!| z?|vS_^vLJ+d>-`Bc)H(@U=!Yc?2zf|>2AEP;QVh0|0C$7pZ^Wz`DYor=Kqdp^cHxb zJC8g4iNwDF8+h6FK2XmQy!p7{eID+PaMG|l3fKOO=XSfl?>-aD3fL-XUM8RW$N7Av z_>ST^2YwUqJsi(l)#*4ouKQh$xVIqQXv7QPJsIf_j_o{+JN-Z1e;-9o8bOWJfrb^$L0Tdk+0zL)TPg6Gr1`oEd3 z@7H|3-FOC1@%iSIXMfrzXZPHnGbpY;1D51bee9721a44K`AgAcPH?|+K#)2=!(7^HdrbgYR0hNk}| zfb$dhCD5j);{77RK7{Pw5BCq@z60TtAa8Dk`!@J}h<@fY_`L?dop?Wr_gCOwhIh`_ zu~!iBqHwiH)|QH#6>nM?2AuK)9=!c{7ny#w6=`dLC?$Kww)(BRx$4?5ztrc?@fmlWhm}cd zY!Mb!nTp1bOD-B8E_E!9hf9+A*+B+HDaV#D_Y+MUl4(n^(QM9%rmd1`aYIYwf)hfy zVQW2TCsS8^iqt-miZu)4!9KGjoZ4p91*|dQ8L&f3pFH|-c{=mrF<{AkfIJMAud4*^ zka;%^VTg*tmPS;(Fha)I2xVn@Qy}a5J3~IB@!z>HekW}iK0uUQP+|5vBbE6y^RUJi z2xGU{qv!_)sqM;RzW6ZT*Vi0_9l?^kMy3$&KqfF`RVb0R?)Lcs_Fg~!i<`}@&F}QR z0v6iF9JcNaGT=vf_|Mr=`63AxJu`9lQErn_?5GpFW125EzlWoKs~g@(8PFB|!JJX1 z1T{7vB<-JpJ{wF%Nv*qyjLbhVDP{hM;LY{Je?&|Ho*3>h#vEA-n)!;i43{V#X*l8w zL13IrBf`452uMd!+5%NtR5A=7WyK?uiHE(Dm6GO>`Q7J{1sOF?a@qBtm#Ij$ZFb2~l9<;U838;h&ZMOck7B0$^EI*wgL ze`ablwjm4|LzqmOPh22G*k05vD6Q7rD;dGRnsI4ikEb*y@jV7{*IV_X@!unu`F;wE z#F${pT;IGm5BC4hq710Vek*Ag-pT$^q<22JtqC9K8~rqFBFHPPOt9v3G-hXsV-L8p z={j|Wu7CPA+-1w8F$Q59C12dP3=OpI{jCeb}Ea5L5)s@)Zq{&Pk7r?Thd& ziY?-yw^^Wb5$q~`6+@Bp3kBz+w?ZDv@NC7ygBGj7M|=w5mi&E_hrb^WFF{Ng8mq_4 z(W2_C-e@1G+6ed#qEhf)z~x6?WMdFKX&%sA(REG zoS@B2^}d#G8o8U#jJ82`hzp7cal1IpRHGtdj!Pu0;zNK~p#nyzcNO1} z(dKd20fR&A3zaqqL@E;HD|vW85YsOhnu#PavGp5QB3NVn>p=b#ELb+q0L{|eiT!Q8 z0i%dwu3X>=iBMvBd>ZEGZ$cv2n_m!~IebBQMsuo%y$e|gFy6RG{e7Ak z4w}IlHWY;M!^ekfz%mu4zppoe61o(TP&BG;f^tMfw;Zv?LnzkHy-=F|#Ak9c@CR6U zUmNKMs6`0Ew?A2_)FSG!GXP0YBRR~aiq>dfH!;wN1_jx{8iaHXN9U7 zT|S~oweA6lFNTE*F@;;qB~Bud=ckn)9uVmCUi*u|L)=W4)b zZW7{~{V4pLJ{-tYD8CV=)>}~>%5S{OZ-(-lsr{V(zfSi5H>LZ3QL|djeAk~0W5;bM z+1qSMj!70cDgmXpgNZo0_8G9z^u;MFR0HG+|GwVP3|3%g?6*vM#F_(U0H;`Sps6P= z?|FuP@^_-~T}cIi%Ko?L>`Rh#044xY_fO6*oE#&YwX=01p7V$SoojtkJM zbzC0%-qvx{2Jn(S>$pPsRUltQ@)ee^5MNd#968vV*HVdVq{=p%djL4Bnvt<;(30RN zUTD&*Dmg^R(^A3RBf?9jgog>Fj8$+kU3KG*=yUPSfEZp_8av!`(P=#Qi{TKOCp%6E zCc!0Av`|%JJJEd=Z@U~Ho^3TyXSk?g8~*2>f+VGI_{@q}liw6U$w7&RP4G%!CIK{M zPwfEI(FH+eU+uSGu7DQ^<35-9)}#f+>uEQ9*PO2=CIoTU-wU^$&d^xXe3Y87)Wuck zr%{Y#kpFZ0;#eId{cQ8{1?Gqq$fTS&>CEsJ9kZ#`YhJGPJdtjuxy?c5Cf_Dpkyn~n z5H1tcDT)qHjxwK%wFF~tA3!Q|tE}9^VuW20doBmKux#bXy@-4R6s25-D)p?4Y`6Fg z4)00C8qlH&@$&Jm!8<6;OT$I6BNTYVtVQWWTFG^_0A6Cw&OZnkIneXjEvN{NjF}Pb z%Nx9AdSpzgjs`eFs+4LeH2n9Wcd*^6k{Kfv_Bi77tdF)6|q%d}*N2Gu3NYCi$#;Qp@ zn%@YPZG$7H`HcV_xn<2aHWQrnJ%8C|+W+a#mW`1`zq0i=t`~W?Hos?-wI;@<;(IVJ zLus2A30A&m9+}f0w`jHYeF98(E`!$Bqjt#kx1|ffMMN6vZ>t(lq0?OZ&(`xt7rDY`z zP&*Q>w^hw)5Vl*{qN@Qma*|n1ZBKIU2LClzxh4E(gy(RhhAXC9gB}#o^uUgx>#cs2 ztZY-(#QcjUf=Kc*h>7{hfr;uMnjWXO(&A`h$eI>5w>9tXRoNUZPgED0TgT0xNlklE z!(ph8m&^+`ztKC^jKjFQabwn{Tguz6~=8&6KnRTPT_+#*AK5jBjjLjK|xK&2%U-5!Lnd0}w z?Fz*8l7=J5cL)Sh!MszpAFjl79IijaaQ9}YKu9z9wuJvra5(dCLL!tW@}9<|rT;gH zn|?#-i&-{wi3JNeuO^3Akb00;vZQbzPARNU)cMVt0DuQ{ub@YHWvQ}*$zPgkhzb@| zgK^Cly2MxF45+*II*3Mu#V<>JFTmiJFDo5QYv8n@Px;7)W8tEXL zLrjjh?Do|t16r*xjCDoxd%aMFY^R!k#-UUp9UrAH5~IKZ_y}zRH<1a3O!$|@ULS(E z971q7L0K2TTg;x~9nt{Nnc~p7*`IKc8j>n(PUD~^Y)uT{tH_+jK^*mDr|~;XUP2}> zb(q`@S9d@mcS2nQ2-N&9*H6;@3w!k$5L{ENo3M`JH0%mUWZqdTI?du{YpUOTarhnn zo(uhn5nIhW{g8hB65mKA#-++$inR^7?ethGWL@o>7vQ0OoNo(~maTqa&n4LtA>isM z7`&%_ZROk zw%4KwrgrW%n|JQr`39;wU>QTVAKEc&VD1)kV9rK!PxBstjm6#?!nPc1^(QB?b3-Ah z7jRU}!W5zTmY6e91)w|$2w_!}m;#jq%^GwF)=rwN`7bZI5EU(yNakn00tN_}A2%Nx z(!B4qoR5)XTQ7jjQpl6orK5 z+d#^D2U3mphcO}FcmM?bBdID$yWR4KD>s?X850i_zt8K4Q#<#V+js8SxqDb2z$>>Z ztx5jkom2%YKQu;v2uEJ=hfg!2`SQ;Fh`N90+lO8NNrJ;JFfR~ECi$(a{pQQXn8Vq* z&)i=8G71sEydP+^^PS39jOt^+wp^4w_YezWUSv)1=QNwoHSh10DF1^Q^|2XEV6W;g zekT6c#GU?y!_1cty}WZTYI=}42-%dNaL`}@dFP(oZDwzCi1{)r#wrXCM=}JIz!qMs z->gUuV0MYIexiYl5Mwn7P`pVLW9Qo}TZAaCbBYn*==q+sqw^A>-sWw#5J*zqBYo<{z$ z{~1DR#Q(Z*fpwlJ*jqdIRla2Y4b=b`<>r=qE<+2E?D0nN0dV^p<^h)8x`5@s=L*01 z-p+S&UoSVG-s!G> z(rDZZ;>*6$hvjVywRyau$$QozK$rhu31 zmB@R{JO-&;&F=!UI)G!}!#&_|zV&G9SOG0@^HEA!t=?C@7yX|OI_e$v7ujC)XsE-! znm9^&mxvDS8x89zM}g!RRC5)_ZR4Qf7u&p2^nD}7wk*`-A;qtm^fb4Cc|(c(GIKix z8y4Gy62o}KFPY7VL6*8iXj?-dUW(=o-OihvDFW6TqqkE)tU_d+utjE2nD9RU7exq~ zq?)znq9v_@6@pZug#WHY-aX8``RyKPPwccHG=;7!)da49 zGcRmz6p_q5z@^Z{IXIl^w{FJZaI792+T@TqRUjy? zwKn(Oc)l2u9cq5BpzP3%hxnn!g9p6h!2*s4Ux>Yp@!(hd#UGr=SP-0M_tOJIQx5-- z{}k-Rh;Igy6h=--+?t9%7a3T&6{ElbVifp(GS_||wSa-(2O=_AJER7LFEIcU4^}CS zYjJp}TO}?eu561GQ-g|ciJXFA+dya77K#k8{|#}6ats$T;`hUCteO}wH(}t|oMW!X zFmYNQCRz)kHzlS8M#GOj!RUo$n_(G+Oa6a>^wC*~H^z_sb1$6I&lj!a0P=u6)f6=V7igzWs#`1*F^-1YNvA!|Z*BhsQjElBut#S%WI3Fh=O zw_FzAzLsE(2iE7V$4m&O-Jqd-Xk63$AxzzbmCEz-%y8+;7{I&+tqKGws%+&A@xae4 z2?MBKii8RN#Hdt!6S6B1OmTAMR*tzbBk;cYVzPJH=H#TIt=0seFd`NBUQ8o0Dg5mrRiCF?3V&?jAkI`pnYQ*u3B6 z0GnE~bP4-8p-7>h6PigOZxufY_gd{I@jm}mHUmmW`Z5HG({Z#WO=>vW&s!t`>oL1EzLjyN5fi)uP+6e*+*xcVeWL_mF9eNt@^pn^#tP@>fAd z<06E_k62^y4SR$U!1|F(Vq!Dl#ySrF-inJPppNKDAZtHOMby)c?Y$ZW-xV1X4m zku$6-@?amTz=;10>EUs@H7=Me)JU7n+ieC%-m)7IzAP~=PzB&<^c7;#D|)VwT#<=t z&P&aA1)|eNRX&ILuCHo9>Mdi3P*CoP6MK+QVdzF>rNMzgX!HwWsUBz=@hiY1E*KOR zxT}%Fs~j=~Mz&L+di$4QwxbU|{L9QD#F;`$0$90K%*nGK9;X@2bj=v?2KeZ~O(z|- z;>Wy<0e=y)4jHR@ugHm>WUk-7_fLI6n`EwaF6K&OZyldt+Qr)|56>NjB4X%zp?Mes zNn9P2D&C8Urn`Ee{*ZD=qBJdMkQQw_)7 z#;n!6(-LF8+6oFwwWXDzBwyj@c4jX>%^N^8DzRI7!zR^z3cowu8}V zGyE^xTp2VTXg152aQbad08KpBl4rgTC@oca(8B!I0JE0!Ts=)7QX636+CbS~D|;9Z zJY(kl#LP*~tUN#RB@CXeGINd}1D4*HyJH5ULCm+ z8SDf&rZ{Q>oajr_FFU{eZ*N~-d5_)|JQ%iS!@@o&ZZv)b`hXLQj8y~VAP7@XmthdJ zeJ>4z`oXwhPV{cz8*E4lqD2O*@8>7`;M?4|eP88X(>6wL0dt&-png_$LDHG_!9qqA z#VN#c+D0iR@42=#pscBKuW^4<<*qg86H>7 zrLk%pbM9r$%g1t8%l7@1FPPhn(O4gjlnVcG1xbHmoXn0EFy#avgtyEt(igzy=b3lH zZdm09aL@h7gkHNx$!|4dlbt^}?^$Zq33}~|sX&irH$-pnPAX&C-S>=(rg%|^1+_=Yx-vTNpr@O%|LyjdJxAkI9IRbjR zs!&S>f_{;}{Ju%Cg{JbwxgpF2S`#o7HR5LgAaX4?i^VR~ak9 zLAG$7)%Zl}G~CWxE6xF6a9l0)75L;q6HkNCL*yg8)zMfH-9QuMn=0+1@$Qk^iSZ30? z*)N8D7_`1OCr?rqL*E`4_MYS(^?oIBX~4RYqu#ktLFK4-7)HH7CT?Rbea{@Mq?4p# z)ZAZ=d3$2Wd#N1qR;eMcm?slMUd@YU#_;z4(ebUff8j(EL^c>V(r_HCgLPo;sZRKx zAS0m~1rI_hLHjbv$E?Ayziyq3b(q1H|1PW}kYHSUL59gQ%)Gm?6tf=Dl(z$m4uNuf8sx4X zcXT$|)AJ97?(yE`u_Lz|i~kFoyUgdxQunZDTPo(da$ZiozHSF*#q8;)!+85nx+c)Y zxi$Mzy2PDBm2{m-zw_uijjprk;%csa8eMpBNg4jF-z|&;p}Ik zawFN%gXn9F=0dl$=(>fg88JqVgC}lHVq}f%cKgxpW%1<6U1jmFh@rB$pOMp9 z#Q52DDQ@X9i!0MvT<*={qV8pJPM2Anl+L1uH;WHJy>67^zZtF5x_AaL6rt8Ka+*-T z>RuKPc9{ilPE}dV@n-Rz?qzXBmsxx{oy8ZuS)7JXFZ+Kllk6D{X%fN(`+I72m(5!B zLaOWn(hv=)fDtuiciFl86m7=3dpVnUlWgL5LDfh+O&@F%?qNP>O$^2kUyS=u`$Gpk z6y0xgD?scp+W6^gC%Cs`B2>xf3wD2gW&wCR<9Up%8D+a2!sm(P zW%lnXubUA=<#in+r}LVM&lAb3qRYGr(|HZ_=7lLFdBI6zlMz3A5ZaYEt8DqOdJ#K} zD=FSV!Oa7fARAPB49twiXFz!8YBb(!6Kg9#+u*G>AERwNhTvG+VBD3%cvx1i#*8Q0 z#&UeFL!ZCM{u67sC+d*7uEa-X4!j#_aY{5TTj!&=DJ5GPi(9dGCE7s@0&SIdv zKf2Ez%v?~3jX~xD2IF`)y35Yt=e+`+kRY7x?vLS<`LP3ywy0-a z@|Fsv8*>st&C{-{N3raA9R@crct(f8cQKeX9R}ac z;6EYwL?m4Qc9lH?5YiQtv_HUF&&cWUG#YIqaFQYg$HLk29~S zBClV0^Lm({U2C*MAv(NS{2DdyE>17R82KxB8jVNM|GA2@kDpy<@dBfHN|BkxTEtLU z{LY)j|A)_Yab!*@dNTXLZ24tMyn04-OT3XwSSZ~sylY>N2qPDZGRKVdVo$d+>8h+!zRW} zXZSmOu1ly4DJ{EI!k@OwkRV(ny^9&L)JEg&-VA3kL-rf2!-?I^u%xRD2c$C$cr!dq zp3YWnUh!x{uk-Td{VbAeNct>djJ!{jX#*pt#r6~Y>^cjYgYjmO$@>3^7>f1(jgiw? z{0l$3&SHL-Srr^0Ia!As(jmEH7gq*_9uIZQyUCmonnOW>39c318dg-`}bo>d+a|?Qhb^l7&^>jT<*Hv`= zl&(p1{Tp55==yiMM$+{NU0)2-_R6rR8Uwa65D(RqN z9dtH>p60Bq4yr;gFH)Vvpr5;gM(Lmf5QO#;chG1Zw2MJEyMr#(L2DT_*&Q@S2l0}6 zc{SL6^F47PWC7@5uLi@L+UM8wA( z!=r#8R++H-WxxG%Flp>?RitlXwqI<&j=o}UwC{tjx!=BruYUwA2V}*Pmp}r`HopE5 zuv`R0+SBr8iRBIdC|KGMn(eWCky3rX&D#Y3A!vDJRxEk(AF#ZTuj6R6(W|+WB%=jY zvhA?tI4uYUoqC(^S&3!v6IY1`%zqK?-qydcWr$4}dKdDs)Z&L2k9$qxG|spVBX`W^ z^)MC>71=l3IU)sPjq|<$Wy*ZE{X!dd4Cm;@f+0xZXt8X44Tm|*bsAvOo`)P74&Mz= zR~vjDh7c&KRw8Hn+vJ>$X3IK9_!lgI)xx0Yqo{Y>wh-&XAL8(VXH`{lR zRIctNx+){ZP^Ne)GuE<9PN$HFL@HV425rQrW3D+PA?wAynhEz4q3f~a zoyl2*{n-g5xe9wzxcLYZy^FVCYcmBrr=m1tdDu#C)ZJ_K;O_Ukfkx*{_1}n*g{jsH zdR&F<>@A3a<326I=Q8*xYM9T8t6#m;Do%%srDSN)oP$iV)uzWI7Sg3_Rb)a}%E1@YLfW z5%N*v^YFZaXCx~45j;K7-Q0j@GoFFygs;Z)8$2mIwNL_nhUWu3NAdJVPaecWW%_PB zAK_^BA7T@euCQ>P`11xOd=r)#dj# z+z0Sn32F9IJn!InAI~RvPR01P63+}g^YHu#&l7l_$Aew2zF*@pFjGGV&;Q_=f=Q!| zc)p71vH!%=7n5{1d~OfD^cfs%e1}L6 z!JN$4!2DZRR2hv4)VN%)NldH2Y7O^Z8F6+zmb3J+8W5xgnUvdSlzqY0WxWQIn3FEV4c=?t%ckIIm{PqjV7jQnUO*qfi| zXn6jUD=&Yxg9Ia&fR9mEkIsZR<8cGewc$jyl|*v)lxUFI%pUTp@RXP}79s$96s6fi zZgfSMT!^UEXWGpph=46We(aMHbZ6G7x(AWrBpiG{gvvPz5e&;T#}O+W+Ymyvtf-F+ zN1rOAJ|v>n;<&9lG6ubf%Duf+fk(MX%4qxm=wrD-ruwl+rBCLU*e@Y4gAUj&|97E- zfUD^+$+1x6qJtv9^huh6vdn`~W(2Xo)18AI2omLs3_{ru%7RVTm{|hGPNtqUylh{;fWK(PUJ$KRJLE zItE4#bcR8ZupSA&&4d^+F(J-!S8ifbeygN7T9TPmMAZ4o1YPF^DHk31s1E`pI`&at z2(Nke&yWq_u(hZ07GvU0@dl8{ADNIHP&y&MIxlbt3D09f?g~pMs_M&Zn;r_M9hqUZ9h3HmB}BkG)8Ya!%eaMRx}vPDK-)&!5T9gR&xo)bt5X zD9#(Geb@ds7_T1Y$)n4x#nguDSF@+|MaJkD3c&-tqh)K+Pxu-ZiES6gVsTio)xAWi z_L7Qd_DHmU2gZDV?43(ut)FO*SSn}U*=x~VA@8%G!v)ik3(I!I+JeUN^*K9iS_RSs z3JTg8i{GMOV+=`gVL9A%xPEH?dq)*ewhzFg*K0g<;d(`eW_tC86>LSigH^dXkuv=S z(bT->3$fistgY9))7F$AbJo`YC%i7uyzdLKw+!teh9AOoF6k#&oNt&+{Xj{ILU90# zo?`!P!@ElvzRTU>CEuBi!c;4Gc0MEHy+FJh!}WaQ$J0Vm_F}&Vc8OY5vmp+rrpQbX z6OH#E4h^2n^3C#1b;MEGLD*so@zjGf;WR$Hpjspz;UvZ((Zn3o820a@qs=pq%<`ok z5C0nA)N9WuR3dUgaSIV+!9`2M^$4BwUs7a*YZHy(MtC@xRwo}8dEDgWK?F@i=@7w_ zGVv>S(h|QN5Gx(y_cL(I3F3EfZ10c}=Xi{m)-Qp>$&kqM(5N-G$|}8Rw%=&H64`@} z^HtX^Ue+LmP&;y+?4T2Jk!x;$rv{SwfFOxiR4We)0{vJEs_t%}G{;Z`^vN^Vs`pIwu2b*p)O)si-=yBcb$EcW9>RqGW)CL(|!Z!#5lRH!&^4bySW2g`9>&l3UiM1SQ z0Cs`>29$A8{!*v>9C0ljLb^b%C#ra&EeK0ljulj^QQR?~;;^JZ@_0Hicqn!+VDhN0 ziU@1Njp0XtEkp&jWAiqN;Q<)Zxbg6>9((LDn0HHMR6q?*fzJCeBvdUD(VRDqxlM1n zbEt;rvzAJDm-(&Sgueq!uP^+{IyvW{=Fa zW#@z9$a!foB9%4SqwoUV^9Zo=_?@ASurXHo8$hx=)D0wru*0Rb8PpNZB=Oizq4q*d zFG~G8Ly1Rx(>Od$RPG$s5h7N8160~PE7IU6E;+NR+!>>~XZfbVCq#To6h5JL_$g~av@jPALprPoHwqzlC3J@& zjzOj95QW)5K~})&9px@s2U-TKV0c=FVB`+jaB*k39{I#m@Q$0pI(Nx~CtC8Jo#Aj> zcX46>+e3^@nN5XUb? z?UWJwe-2Zx6rBU+?z}R(enbN-o-{!ap+}wN>r4jDbu2YVEx_r`?Yodchq+(x1cnn* zZ>miXBRTYJrpfa8DsLwUXHekFehH#)0i>d%T&Z!2)EABTJ_u%WPs4_#r~#pD>Y|=# z_g1zK9o#@;@x1`3)NpokFe4wRI00d5tZEFe1};E5;PiUV33K#z_HdCw_WH0&8gOqb z%rh8}vSaN$%32~|9w<9l*|rXFeVy=6d4sh;_9~K%rO{2~3HlkUmWCfk@=4RDv6ki0 zn%IVr{jfKWI}0@dGkL{WRo;;9JssEtyn=uQT*uoU1>~6*N`Sz zC&gJOi<2Xyj{~5i;zTuE>KWnQ@&Za4c77tiH6{fUR? zo}|qF+&TGM8fus2e^Rp!C4JZB&wzVcM=WV+vQk=h3HJBwG}5fmeU6kmnghSH)-=(Z z$DLiFE(N^v_pbAei#80wFAtBb_r-CM=Q{NsHv1spQoyVYK(!sneCAbXrsiVo*bw-Gb|1 zw9I!2?SnupCo&OmQ6c3TrR2ztD$w2kEEQvJ^h1-_t{sw~C(t7sdk;Dj3H05(1O{8W zQ^-r!2ovPUdq!s77UC_#ekO>c8RleZ0AG%Kek`MGLT+ z=vhxt(=8}WVif0|S<9M?>}$gqBIYGl{e=Y=8buB47(<=qpcN#Tf?4m`7=e#aT{Fq; z4j-fZYux^@L0e_+6;O;P$H3hjdp#$&&0HUQqesI#IT$_VZpD}=1hbzAp|#+0c)%&F z+ro*6!Q3PCsWMv|-l+$2GD7GqF$)00Ot~~~S_EGl*UfFa0VTlqj}mYC@|~iCE0!7c9AT z6x*r^HQNJ~q!*&rGKF7a{j7txoo+>K3bJJQHzNz00*fGEwONo1L2p-`=*k8^&Af@FjWUfuEH!T){A%y z>JaX;8m2>+EgSg+f+G1mG$+nNZA}K$LMrbs%6}Z8*d_!ELC7UJ6Xa1VI9PXK=2+__ zfL0RIS;Y}MhVEI$BIJtm=hEGWFi?)#)bE!g%zQyJq+H3tT+0YddceAk@P`ZvG(^sX z4P9~U%UD$(K!1|Rk3%&7|LnaDoLohf_urH0Bt4eQ*KQ>V^}xLY{7d4xJ7ii<8l zMOZT8zAWiT9cm{sop&+FBJ!UW$((4^-pK(I`MA3niV?DIPGpYc)ub(X>@LP2aszjp zF6rEDG-1W+_GX{jP46VL`&h_rR}7+hePTkdHg(Bupoe1UU?j{lB2IL`to%APu2|=T z*uwuez^DxV&1LX^hM@Gj%iur7ic48Bm`jTXxVu%1WVJ3}bZHSdstc6Io9luS_ygbz z%Z7Wut~QXnDe8sjnIKt{>`hD)6QhYo#5|Y@PzD#GtdJl(6nFX`QV!(h_1>bd=q*?> z&3C=PC9mZtQfD2+g_9e6tlT$=W!Is}1^&!LR$}{h+jzx`xv3{ESmw*rn&O*FliVh9 z3|w(kST-yuofWl1{nB$05giP&51Lw*dG@E`5@Vo_e3O27w0qIQp6^kupq{idJWg4G zVGYzrtu&hxlYof)s^~}IK#^)E%hbYK%X{5Rowa8~#g>hMs&_;{w`1l+>$XUp?-}#l z)8~0-w7I9Z!BUvp!uoFxe~GzG`rofF5_22$#b07>jK4F)e2^|q^l+|=a2$Tj z8PQ{hcS4Po^Sa1R-^U4kh-Bgr$&bT9m-Ttc`gn7vyK|;{b35HRo!;CocTSf*EVzCZ zP4?z?xN|zZx!vxZZm4K7a?IT5y5Zqp4!ZGLm-8J47zJB-#Ewq$ls%;`S> z*XB9X1-rt4M)b^=Iq`9>k)BfUr^!2`Lwv_xZ+f4=^*L!=xWri_r6@S;puU`1JQ?{?|Vk0!48G3?m*wu z!_LlO&=c*^fF(2c*kR|XVU~0WKpHK!`Nv^B+?UU7NKYa9&X z0hEr{<~iM_o66NCS$kT(Vk0O_)ax~I&_intU1=hT>?fQdpfL++=!*JzGawX?wcI#1Gw6Yat0@^5{a>jaeTS4=&CA=$mPEei(gZ zR{y<*!HFK5FGY`U9oSdf{>sYVe%deJmOs6s{)CTkcZ_g%kLj*vkH;P>_i#FY zgg+>j@a>-$n<;<+5|c$w8Tav{ES*+Ue3AKZw7nER!g=n%Ej77&GqKfkCZrM@wxi;B zgl!=8xDQ_x)jeI`$3AiRDCZjk1KaDfPu0Y>&KMNhcBg5R+}Rb=#r`zzvCCgd zr4t^+Q(cv9Qwom9{6<)0S0m5y^KjAS$7fywQ$J#eK^R}Y1 zG3*`_U-+Eez_d8d`KoPISiLZuy+o}-Ro?2ZXz#!ud-v2WKj01tr9ZqKXx-Cll7`{G z@7*(D`NUg3`Ox-M5T;y5>Q5y;+aOm)Q=6UJJEAvlxC;3Jc*{SH88wg9;zN%nXO8hx zB~h%4mcfJB8y*`OMyN5uE|(0FTP(C~HerLt%{tocGE_-E%sBINoQ6mK3?27IZ{;^iAAjZJ6WUz*_LiK**{BSethhZHo zni+3^Y-sR);Y073NI{>3k@=_wk5T0}{MVNMR_pucjBomGEPI&fs7Tj&Q;bH``B8u7 zER9|D!+$otozJa)#9%(hU{uKOX)+>~PVQ>T@)y;0D_1bdc6b?djb=`?nDIhvaU#Sq z=6Y2voa*hwZ|8budah_<&_Z^Uk}yE9{K>`$A}KD0Hf~m2CdKZs8TMnnEDr_39wpO1 zO)~vs&0JLCZ+UwHu%^-T2t$V)(E&Ym6AHJl{Z1{bEcTz2Enb$?Y<9ZO5A3b=R&XyU z=KgHzYXh&ADI!f_pp92!b|~sTylh#%^Z6LN(%7Yk)Urk* z9=5l(L;IlwF~ZNJ*v9N{{zyP9AAgK0#q*87a(}4|DX>0&*2YArmEK8oZi+aGd7BcP zIB(qPOo?yIZite5Jo8%;#QADWA2IdUK>{|2(OUL~(Ha<_sIY%Y#Zxe9xVM<{Men7I z^5pj27*}DjOOet1Vi`+L=Fi$XGwhU2D<1ZDc21S%`XuEdVe_k&um1j{ob$LTR{xjMk+>2r^Z;!H1 zCwbFZ%5Qdr>}s-`V&2CwNEvfK9&O*Ac@BnBEaF_dLz!+-OXxS*i5znGVODynB zHfDb+#*FMCC8iFfukb_Xmv|n<3*86ROky<&O;3ro?@Z5DPwsvw-?;U7#=}6d_7pr4 z`Nh5@d03wbs*n48b}&X8+jnMO5HRx5$5e4+=?eo`?kQ3C<1yG8F#=K7=?`{vb;2cV zQrEWLTXLA({8D0e;KLHiR>hXgSq!Zuo}EJ^a8iP zlzyMBFA>sUtZZP>U9LY9vOGO9yScvo^$dt#no=7w@vLuk{+62JbCr}ym1e$Nv=H%) ziWytH8@mKvdTR|if5^ImO1;N}`OyMhYTuVWME2H8bvOv&H>@`mv8}s>K9g|ltu@8p z+mh`68^S}dAm@Y2AmJ~Z=azY~miaE=QH!G9@yR=oZ2*8y{C;RNUx)*IoOBkXw zPWE?Eo5me1OLYOV{JT0PMP)rjR5uXz$GFtaiO!Aez-!$h=k`5yFJ0h%lx0xF#S+^6 zCK?jvPWGup_PLkpHWSEcfZJ>{up!CpbHA?JtV6so)O|@QIU3qIuswEcFIdO?8tePr zRV>izBqmhepn(_bvd?zx)P(iy zK(6k7cPHW5;GPOun4iV3N`1<=>P)9~L+@QWVT#zpH|O?)c5f8#&*^^(&(;mQHr{<# zgMvGEx{q#qDf?WqZg=jX6?Of?nV2!+kbSVmyIB+pWxOnN(p~J@W?l#Z0mIo-odgrwQUbF3_8z^Ei{My%sw1&a7frEbd+Z&TQqjX44pzaI-FqX%ltjyI6Z$14%v;wdO^4xz=kYTEd;1 z*gO|>QF%gSUX6NrGaHVdS)ZPtKSQQm8p=w)^s@4j8{E09`YBn45>1x%-h~Zgm#jS; z(O@FAT;S?ND=|~2SEuSk>kR$PO$LiIV%7&mX>nU-%mt@`eS^nXNn?636o@hkFGy$t z4iIDlFqQL=)gOH?#6d2hqe1Gw>f6N5FXAsjb19vyc;o0t463p#Inx&sfTGj`(YSNX zdB|{hxqbnwX8Z6{W}!W^gWW@?mrJEcz1tkpaJcm^94Fi{%&CKSqX{@>R{ab)o&LRa zF;-U!2NQ$#C4v)s)LXunL$Et;B=cev`e0Rx9 zTe!BoR8x`SWno16#zreH4*hIPW5qKApF5FSB9qK}O*Q@aCk3GfGTa%!Dq8>+3xi}) zyQ>oP5M;J#)kwSTs`vb+yAKX`FTtOMP@A8KD2?7kQ{j-{uV`j}ZAlJu7g4I-DN} zUp~OTd4{Q{k$|DrR_pyF#*aU{?kF`DfMkd2%4XMXrN+`qijHSKMJp>>s9S(EPf96+-S!RHkA<3($$|N37Y~w zBw`~AOE=IM9J;hsr5Y>hu?g8JG-fo0!%Cx0mgyQ6Fk($TG@AJyRgXfc9xLFD+Io~{ zwU{f^VZNYZ^;$IgwFqO{8X)Sj@QrHlGBwApv4uv`ThZXxBFw6y1~j940U&SVX$hhj z;^96C{7@i347W(3O98VaQ_|wDhQ9OE5xQ6A#~+&ATetGl zFoHgS%Y9_(i`jj#%pt^|$mp-d$g&-tGRJg%es*l?M)wg;P~p@-skNSh4N#VtZ1{A5hBOLk)B zNRw)MK9!;4nnT2g$O(CcItVu!~o=8z4-={WT45 zTp$s!(qx1H-XM!k$9-+V;t3@_CDoL@6=V&CTCXvh=eaLiG@>Q6!TDkHPL@@Tr@OB^ z*G*>gSIDdXS$P(82vCkw>7xQ5x(@_|Kar_t-(VK5#WTXMPrOn0rSmtY#Hugvy`X(b zx}Zn1xcf3QY%pZ$1C^Sl?o9TV0QE$EuC8mwZPSWsTG+52ddSH=P6_HEbw@C{*&bT- zhP@NexWesZvO1S)0yh|u{oNXPY+wTIJck<<6?U35VnStODbySCZzT5BcqA%@)Ag*{ z<|by`&a7RgKO{$VKbjF0g$^i#l0J{mQzwQ=tC~Q(T z7T<*({*tb6<1Ta4%WO&t*W#!WXQ{l)`ewM>2<&S8xvp93AXon!>`;O9RCjOCYD^){ zOgLY?$2n!27ymm1S6*!2o31-~R>H~NjA0!?)&kTm_WTa01Y@~!<;QSTaZvQTOfhJs z{|p9t@@wU)Fd%2(+rH`2Lw)V^FBLWtF{lmp;$WQoNJ#@V^$!%jC1<&^l=Fl`BNti{ z;jLVTFg?#U4H!#dik4E>s}JaCJj=L!0{mQ^ev4KAxG; z?C+KB-pT3jI*O6CrSGTOW*GrV)4O&E6xRNMo~t%5q%ZU7tstc$Lw!40fc8M>Aj0S6)2XHTpD;)w`R|)MT52X|lJmP4(3;?`t?oZ*zCj9= zG24KNLXgMlpH^8J`cxBC|E-F-ghIcz9U7F^;UhFb1#%mm@|UWN{J)z*?=*#W&zDg8 z+1+Obq&O%ryCI&>|3XKLehyUmOidnVF6^E^GBTCwM3V3LDFb`QU3lO9KmYm9z3#ZT zA~E&RfnjXBOx<_cLF7k0O49qq*rgNl@zrjZHZ7{=`B1^LRWsh_`0w-lcbEU3=fAu4 zHq$s(zOMCm9A}My21~sml>4RD`zUEoxQ;0K2M$Od9ap9zJ`kb()tQmUWm|} zqq;>fT)2fU_^*bXJ9ND2VnOVk8kf00bv=`V>0I0OURR5|CiN6RhU3#AW=}5lnD2rK zglntsk}PvBwZ(TyiaD3sU|mYv6~kwZ8F3~^Lptvlew$&j_)1EE&QA%mVxGFNA+}2< z>78D`USCIVvp(s`$4a;oG37NTK9?S(-UjV4M>3qwH$y|(69zOEyD*Mu4Bj^ygZGwO zrp5-CY#YmE5~u%tLKcOcRS5_NkhuiW#M!IF{zuP8Cllb$NLOmE&l$L(N#*Mn3<2Z- z%=Lkfg&sbu0v`)Oe0l?)4d#Pu=_`Pv#T`CESVGi*C^U*Ga2{>%mU0R0J7KEZvfVk; zOiEkolsV1DWlNkgCuLl{wvaiExJ*e?=G2?d9{z0+r|U8!U`FDjt?-Y4$yqCoNjR`z z(lR{nAR{fTn~AV}?hAo-jUM8igK*S&&edNh#8Tv?;`W{&PFRJT1pBj6T~i-%U*>54 z!pCpF_=&aokJt3=Irh}AMxE>}&@ZT4%hau$uV1)9q3ctG%(x+S>bT`oYBpedde#7} z_>E5PaBjYHl0S|3O&4v{)hY&mc$_U!iD?%-+?J0gE<$pot>zvHkhskW?;lNfx#uJ* zVAh$a09t3F0&1O!64*KuBjGkLVQzsYqWNPcnUvwI!&0=n60*_i_W zME=w^=Az^-Bh}0qgR!K`#BdIaNZCFPrhU6?%Z=d5f?Jj=yT)>5XIidoW;`tS;xR$F z8r9l)ZMCa{^u>$=GY3ea(tejG=LgG^8_kUM7FQ^2ecUdw^Ur6{|1)(BC+K6iWN2C+ zOwiN93A!VHgHEkL)3&@THVjp0VtSsgnW0Q5hEqG}OFsTpFS?3O_ZcIWgq1ax(whlx zgoRCBd0P)Wv<3owg0;`6nROmf%eTO9c1AvXjC8CaXmGQwtRWH%Yzh2?^KbvNaRZc; zP$igkd_*y`j!!oIS;r@t9d_37$z_L~b$V$kWU526jwO@floL`%aID9>(c(c+3q*e! zBhD(BvY@i2BJg42wh}_oNje5I?7HhaRClu>(jvPYQ)$@Jf#(m&J~Po|5@v2G&f;Mu zYVn`x{%$fEl-KMNCR^sn`-SX=A+xgv{77TxWyV`&UhsR&j98mKmcsTE0XF4-i11cj z-I)cHh&{ne?gAyR()Ec*GBXQITY49VAd#D5nGfFuf=5h9N2ckfgo&6w>MmI)4G=F& z45QH^9O7ZC#8@8%p}P{wvNN@W7c2W;@iIlS2#DMqVaPcBgM6BzZjP{mLh4O%mT>jx ziU_Bo!_ zZ6jC7Xsz>AL|guj*~nGlw(cJk0wKf&M3bl;LWilPLMnR>0g>~e6uSdGrV(y%aUr$y zP2xNK#&ZmroXas`Zc$2wkr_6^m&`!{P4TJuhli)#S`9VkkkF*J6_~nZU}#+X;If}H5jLx6FuiaBee$`cHYT_q;a~o6*V`P`XlZ0FsO5*X{kF)N9?*Z zI%O6cu7oa)PMO8Dm(ZorDYKaJ61p@xWfs$2Vh;PNgt;_&8edb!d2>3+@ed})F207$ zR|j7^%~v;H5mkyw%XZ;L_Mjh&9IcI%22RkS_c5ejz^$L{+kjn8f2v2+uN(aL&-D)a z7KqSk8lQ_NR_lcTbR!_&9UXXnLf}egQUs(C{s$@-CguemRtU-e;=O{J`7mC zP(GvB`}mVX_TYoeDEoe5uHkcN_Zh$b6$g}~FW|qy!JVpG_3+NpPXoVUog0msTy=}S z&gnmsX|#HG^sZ=PLdEQDFb>cioU6Cv(9f{6meG`(iEwG55#gpQG&74WQ#_?K+I)Ek zYp>7hFL*WcLZO#vek5bIj}yc2S#xiSB6nnj|CNfz@=w`!|~#HaKw%`p`d@>q4D;C5{AvlT6hHP z_y=`1zO-16)&;VV<8#G{_V9d^WPp-Z0%(5&&*V48sX0jG%RE%j52TMExXrVeul^YT zgxo2+ZNAT0bL1;nKA0?WlLi{I+B`W}57<*TJ#JVavw^!`X>pzI z6<;Yk*w%hO=i|&54AD3e90xH0&0|Cdr(LYONq4r+)W7uvye63TWub*Hh#PKXS(r1X zFoQI@y9<5P%%}lLp$H~Dm{>iLkrh?1Da0{6+n zOTVI?`($7~6ReaLH-z(R4@zJd2qVib4TUB)S%wE1$NbB6#x+5LI$;fN*C|?%-|#gp zxG-V^o7tUNFDU9f$|9eERB#wK=)UfK3@HFHv=aH7l!;;$Czs=kJ&zmo&*NUtyi`24 zJotJpF&z?a-ySMX!cLF!U>mpkM#GGRsf)&~%L0Ix+P!qlcEbiXKo1*!AVN3S8rSRy zS#J(oZq5(GmVZSpSMh$)?hwo{5TqgZ5Z4X?L?Hv_nX@!-vH>Ok{wXM>aU5@@LWrL- z5*$c%_-B@1F=v(=(kJE3>1E}4rR0g)@4s}C5hvn)Sn=@o!lje)x^^d%+`lHj#-izh z;skvIP=ULn%{#Gwm(%|ZMm^ri(eN2`t78Vq8{IiE_e5Hh@cIo{0I`$%pt7>=iG}y! z5K9wb#^M*bp_A_yicyj*P5b1`4yA-=?4RlUT{-xolvWUIhD>t=7BFAR6bpwCW5)G( zGXE;_6;W?C@-3Ndg?*4eTOe3(k1mS`(oxi)Oz1&U8WUGNz3<*tY^;0th;>uHZ2Ta7 zqziw|$3`MCG`7|JguEl!C#^h;=_`casqX5IlsnKnu%~yAv+RiIZ>J}mYorew5y^E& z4b@0byOaGc9s;pvWJ1Aj-*%8?C>eat4t;RtB>#Z<#p0pap;lztf*I^dB*slrJ8M-X z6|Iy}Nh(Ui^?H>*Qr3$$R9`YWYbEdj6iR4mo9f)vmCEjEHY9)fL@#G#6&T6Q?w*0d zLEH{^xmcLUK2tOB(v<9THQfv5pNSlpv|+K|3#2EKGe#+@3ztiJM)zmOycYd_D}v#c)TD151e7DD#2iT9QX zD``;1XR5n65j0XfYl*Wp7XAgj%K>g1)p%zKcY+;Kyx8Fm7B4HFR7?~n#hs?Sb^OgQgmt9BcG=#R)CHPWNL7<(6yL{>B_mFMrzOD0TnQbm~W4(c42wk-_W}8!i{o#_^j{D z{i1vh41C76PDJ5>q50SeT+ui1s#Acb~QD5_~Fp9`EzHeBEoH@@PW!}F;PzjqQJPo&?2_mg=43h!Sziyk86;om!d zvCTPQ<8mY0So)%0`SbwFZ=>SB*K;F8`U4;5 zD(U0k>yu(EG732&oi!u~F}Fu0^&K_QXbWS`yEvMkJ>0)NJ-Pj*WpN8x_tE0Gqc?j8 zc+qv>;RLiaOfG&ne+su@W9}jDrAYB(5`>UrU_?`y{z5tdNGDs67ALgcTbz9KmVu|n z)z-Q#!>7b=t)Xx(q^@EiYA>L3Cza{ezXRa30#YUZ1o!LJzbjK6Mo}EZJ3S@e zHQYatE?p=X^u8EvfAO*@2)9Lp9E~)+lg*Q-05{n*)E*bto8w}$CSomW7})g28Sx98 zg?8@J;c$^j+e^&P7onzViLqn_w6GN*Gv|XXFmF4r3i9GSRDBx zc%v~luuYhW2G`2NAwaCn(LSZ?XdleH?0o{MWG5$9QU0%Dh_>Xf9PZzpKB4`UWzFtZ zI&oJq#fob4Y^BhRj<6A%XPX`>Y{LKOy~J@FulEk?f5OTAJ3b(my|&!Ho6F6NvYpE& zGZ@jSvwN2rX;DVnVeaF_tHPSukE4eeWzQ)pE4xf2JN+vW_g8738ABAb2p)u_Xw17P zcJksF<8cbB%0s>StG$EVL->eZ?Mj|81%kvF&{1p}#=qh|j`_FO1Mi9wO_lq#{?GbX z&+Nu7fNF?{YCpendKTcLgn~rN+Pn)bee#Ea=o16M(5DH-dG39{se(4ur%yEWsMXS= zBN;sP3?68jPmk&WMyzMxzDmjTTRv?U*|-b&vG$yzFGn+5CdY)JNUdx$){2Alr%jybl{~ z%UYD^9Eq8`Vd_>E?|aAT5awe>mCsSj-@R=JeKU~!g7*FEi5Og%)!}|V`fvP)D;Z`e z_S5-keaOflSA4VCFz9mXrhGJDE5ukaZic&{bcS5#n}5(Rv$zdc)@$*hrJr&Ms5##) zY)%ty%x z>cZg*OU~{7;-wd+FZ|*q-Jf5!@IpI(Oh=irYVNNfLhULNnrifJ7HinECjQX365BN( z-H_c;wAI|V?Rod5{KcJsz9GB!@XREI#U;MNEx>|w5_Y(+R~Q4PAu$BjEs$W_80%v! zACiF|(3K!k@@PDGr;xHo^HlvM=YM_~+M<`AyX^CuJL2bFb|J6W=a+r{i>T3Bc+p3X2pm9gTU8K9d?p0J4LJ7K<%Sd8kyy6uGndoX%hKn5Mt!|} zsqO2_F0_4p0a)?Dx2LP`VF_EcorwHDT&11$v{Q_?j^8_9)Pl7uamVMEpT3Z~PT!5A+JUwA8l2H)xw7mt}36^M-B9Zt8-bRvob~ zrrB8*$K6s>(%sZ1jdIgV>b8p$0(%ZshI~MENA9kSJ{xal)caB_e=6FxqPv+MHq>O^ zb+=x}d^y_pEOW}fx_xeq`=zLN(r&T&V(B={s7MSSx5hik`&86;cfjlh&CEA~Wny&g zx+j))?v4>T$l+7bUH2sL({8EUuLHl15q`b+^;Y=pzDFBpy!9$2$D461Z(bGNOjq*e zRpCuZ^5#|HO|J6hRp~v>dXF379kt%k5#BND9UI}Du-=Ig-bw47tn{YYstK=(ngB_8 z^Q!O$nDXXT;hn@gzCOaM?h(^}(zm6a>lo2<+(11Ol`slQ*dTQi>KbO^TlhGCg!sRa z`ZKFe!a-!-RrE!zOeGmf!U{_z2E`Q%CMPS=W9BwPVl=yzus6OR&Xp~+ihf!c%J9t_ z1J-P!Bs4T3J4(f_t?wxF3Jg891HW;J29p8n4srf_oCj6%&$!>`wQ?3T^;I!G zV3na>dIqZxSY-de%R4nT^<^o$9;a2A&mof@j^*##wg-jA4{}0_7|F#(S$4;zm*t~B z(ON24ks><)FDxIwi^JyV5AsWXAU;<;7v@*O`x5s>rrM3v4N@LvTqV zUc(&Y1*0lpY7Jx6{5!$P;aJ?P;QVVIe5(5Gs#QQ^u}=qHE}@tnRiUK9zAJymYuP;$ zv3oWI((b<3uO)eYt|aQ>Tyu;r|I1q>lapYnc0D0p?t99=<}vs8t;54l zK@C=Srqa65y^Qr}{_1ndgT<(G&F63m0^TjRD4DoW&0i6h@f$4ZVPF>ij(6Y2Ey!wQ z_okg|{t;(oNfhqo{(3r_wV*W2OmHABgAE7vl4;>$yM+9zzR%~oEIcQ_PvD0o8=GkD zKt307@m`l#*fspoCh<87QWC=VPxal%x3hNO!#epbNE1U@rdP{vh(DwVF|n52Hx3qA z%(>>qpslM+TkCI@O`&He(#|tug{OFv`E^RmuF+(!!cDE#t&-0vTj=4!H~A#uW?qHA zvEMqyEv&ZR-_eVX;1wxePDC9Oh8{h5h@VtEmydrf4>=u=|EJtz2F)A)OPEW=7JWUT zulMTfQGGS)>v4S@q_2nd71P&~e7PJ7{vNE5%tF0)eb}?nt2w0`kA``)R^H1Iq*PJY z=PzmV;;XZl#~ae00M{FEa11^kCIYc`dDDKBy^^30nv_cezrHKuQnHpl!bCmQW*A@H zce(L)`hUV6is36sI<&m67c2VK8vc`Bb1MJirNX{_wU2-dSPgJW6vBbm{I4PNxSlAQYoc`uC>zQ!BCCP`xu7xZs5(bO<{K&ld{L#))| zu!8C1X(^b#8iAPcUS>qAoUaWSb9>2M59RL5tV9@y9cR5{m3db1G*C=ancXz>$EQ>0 z4_}7eQ9IdU+HH9Fve=@~3DG#*n*e8xYZ+72Iz*F8p`kL)E~kGMc&NSMJi`ofUuhlo z;;H^4Z_q&8oL3p{vBR?y;Ky?g?PYEf}+uxKeB#F z6`J{w(wO^_MCppLm!2<(h1C=VF*sw*+QCjQwvuFruCl0@*-FyA|0FT4vw|$OMtNCm zVVJj4h7KbY3M7|=J`l}CW#OCX**2BRd%FMb(7UpFUVK#r2CkyD*#X(%Q+t=cTlYGW zBt_G7P-M+^7{UP=UFy*(K$FpDmJ-GVcm?3# zxR`;RIlLlTqCA=vU`uo_a$i*Cs~{{Fu!omMOE_q3AmCMjwC=0vqiOefUc{oVWXSzsU~sv;+cmsjfV1S_huf z$S~nteFq#X&8UJG#V)D9KE~a7?q<+!Kcmamxnej{e49u~79lUyH2{}^a$zyP$Roky zn@XumbSb)fK1t~Q5MAXYrOs@Y@YaoJDrdTiw;>Wi+@!nt%@7DD_bS>Ld?MlGw&N%~ z#9!+MS{z3-hY3RT5lwU};tiRrC>e?n-+#k$tv!Vk)V8q%`~dY??grCJ~IqBkhISHI55UCBt*{Qm{s-m+NX zGg?FJ@S;EPdg9sF8`B5&y>4c>@!8jp%yiHN_1R5rD9YRWFH|$U$C(gHYUD{x@CtXZ zgdwKaLAvh3yQoj!#&bo$_fB-KanuY!DEHS1CbpW#hM!_cFOA>vZ8Bc>UFF`nWxWnI zii>Q(zbZiMIR)tYcJZUm+I#z6zLn4QBF)7UjQii@77Z&NY1}`QTc?`E$;K_wvh_Oi z)2LB*kUh(^S@-#^v*=*%@2{92VuP@^%GAcpnhfG3(0P_SaZefc9w$eMRwN5k@BlNS zx0()soM!3}L~CT_RXmKP+di{e%uzR&waaUTkL@P9`U@lwDl1jy2q;YtfYf-e$p2`gyH6zkaKDV_uPZsbw; zJJ0_N80-ZXUZ!u$aYy~G{#U;%Jiw)L91>0mx8A{nKR*l>&|mN8Igw{3&&PSr}OiTK+qnn@>mU{DB)ac z+)hr5cuDExzu4woW2S0f+e37f*7%Uam~u}~WbV~E1^N|IYwtQGz&GVZ`~39-E46T4 zkYM2z%e0ULvrvfja}!XrMz918)ggWzPc-4O4KqQoR<4okP2Y-^NVF!h?9!1Hqo@yQ zDPVJUU)g`YKZNd?d|NkgHLt$3H{jZ)ZYb85>f45olarMJX11u&SQ>(g8A3L*lUQb^ zZmj28bi1*nVUUJv3J-w;SnBiFY_$N21=EUuiwwxS^k=; zr3G&Ok4nC!ZixF)?#AphiAx)Rovv@UK6^*!55^14Tk zHNpft>$Y6r_A5i?^oF|rA-(_t_bkzwnLi7?QBn+Z3F~}HFT9sxywf|dSRrLhr$+6y zT;1WxUuO_uUaG0}q1Ii<&odglsCF!XKB@~`CB#`M)ej@PUHgI%4X8`Xy{3AXFD&6V zf_iJrN+0G))ZJ@)T)IuT<7oB4A7nPFnNODAe8iZcdU<}+SlxW=n6b;dmloEmi?tzO z*t8gs#XTcJc5=UZIDNPqQ|}tD;?ZThU9;a~gte)2rk%TqP^n3+5OIv*n z^rT4S!X91H3j0qOWC&uoRjo*yIiT;SBJE{TJmZQ&yC8bpzyDzQ-6eTr;eQ)-Gj>y^ z{?dJM0FLER-dstKJ}&9e2b`~nHQ4_|`dIhesN1M3N(lqs&4Eo7Xdi3_ct_%d+IudF zYU`cKIG!d=#wmq4u5b?qvrW#=5)N$!;N9HCB0xJK!#jx-I$WUG7YnOwP69 zdAbjR8`}F$V!EQj- zLHdO-*ad=ZlFTDv3_lE{dj9qy(T)GGAB0^Bx7D|A9DJ2JEia~{<1@d zI{kmIj~8N#O66!W<3e>{%jMOId0i#iVnh$kO&HBR;SFGh4UU>p zPJjWbGAc$SjDb}IaYk=5Gs2?cB~>DqvWp_~yirvR^a2Y3P=C0e{7sS|x+yH_7e=|s zo||cgg-!9I)(zZAT(Y0s;AASwsr!k70FmmbHu?P)6;Z#QVixsi10HllQmA6cGc#BI z$CjjvrPo$kSb&9{4D9n5Db1{W)Yz^vVjw>2G~Zu}Hv=MpOgPwUslIc&Fqv7erfxgk z{@l2}-a??f@c^^?m6>ynd}deVuCg`hLYO&N9oE z3s6hcww{G*+~Zz90bi$c>j5yqvQNL1 z-CN`IKaUqMid(7U)kb}rPSqX?{DW)kr`vnh#S!+hPb5-Fk8C8g;u*x#HZteb}tOVwoL{^o3plJ(xKp8Tpi zbga0iepzDtH~DJaksUhOxu*UE3uCk{_`}Sa?pQRO0I|gDw2L9*GPf$xLYbM^QJjcW zZ7mdz5pK*7H3r0&C40DmY9J3V`{-boAh*AExaD9)HcDyS4Pr{`CxM0Zd|^-5suY<~q&NMIhw=xuH=7jYW|^b62S)-C*( z&OsfU`k&G_?0>fSpY*j+fK$@x33S><`$8)6x24p3`8$n45Jhn}hSsqYh3}Gckgl{d z!Tye6jh8xOg4b&RE$D7Fz~xNeZo|;JV74jMqO2evKN#F9>Hk=Yom_9l28YE%gdf|_k&@0~_x zxVG06h$28poY&RUw?~|Y%!zPJU$27+P1Du8ta4FI_gh=aQ@pz8FTRi=8^YY(RQTuP zOhpyS(2jdwHS3jWS96VLymzHeK!?5Q>$6wIkI10v1i#bmp>F-^?3eKy@12(L>d5!} zihRQco7xT7@jP?+0$&4$nA-t#Y=@ZDI3RYeJ`{3{AxpJ`JGD^&_5yXw+Z^Y2FaAP# zL4}iGp9jb#pp|yF;wFT6QQvoY&ldpEdXYb;b0g!gO*`evBqca|9`U$lE^<1ZXDLQ! z*~4uZ21ae!XPkj&Vs-aXZu;l}cAVHXU_5P55`KINhWhdOefw3e1n3O`MbH|-iG;;Pc;Kly3!{kA^QpLUGhG#k7;U`^^qeAkn%=71ZGB5rc;#fx@7 zHJD4?#Ak%J_9Br3haWsjc)5mea6~D|S1TG7?Ar8HX(c|I+3LNH9(N$$YkG3%VCS00 zm4YKch4Vh&fA{F^cP&6pdXYi&JV^xQ96RDKy2jd`in?>ZRBx=ZwFTGh<|4>MXl)wSk2s zF{stAlzsXO-fda|j4P2}*mTgSWjeXBWhHF(FEhHkD$$UMkFDG|8dpc@0O)h+OzlX~?JL4?i zPeI0?E=w|c0DhN%KM(i$uR?wM(#`!vpbEp3yoNC3j zyd?v(iZ?JV0n+cM@@B|uoR<9|aS=DI+&!u;=_w=XQGA!hk!~G;F9{c);H;FasI#>X z(vP!2K;C!xbi+|R!YFK)_1l=SejCpY)!h+E0+87Q;J6a)hW17xT;_;pw{-Y^MV7Ko zt_OM(Kqq}PHL|6JzzI@jjxWq0s%mKQudb|x5Z?d}m6Dx&Y>?5!%mRr|c*4>#Pg7HkC8 z^|dp5vO`mxYyO40uA_xUP1DsgSs||z6I)7~uKstqB9U6F!f81%$ti9Xxs~)&{a^em z^iySrjw@-W+EM6?0p+2oSa#$i)J^rv!U;Gz`-|UzOp+#^Qxo2l?lY@TJeVrOUP2G5 z2Wqkd+7F#?XZ&1hJC&^@LDaGF*a){@W<(fMPQL@30z$+P47Qot14kz)0k2oYO7 zRz@O33&N}_2~qkW0DN{i5i&ZrO3~lsa5E;S!r=$nNiUy)L&-M5`QaEF0R)TFtnm(J zbcjl7`V6Rab})MKZDuuf~p)CG2mzloX@6lnB;%}@qq`=?`q(Ce?C z@l}G*4i@g8LhWF7=X5rWtR$`c@<-D;?ZW1pg1|6eX2tf zKtSxB-0PO?js=ZS;oHT;vx7_u1!Yw?5&w#`VoVOhH{pBOX#7EdSFrO1I@?QMm2 zoSJU?IC{j6y(Snl)i}9-3dvX;0;~zQ#>b4H_nn;dTN#R};1WH1FD^@1x+;le6>u#6 zY&ks8hloYXn&pQgopCVo1@Ma{r&L0N08O17>lZCxMxturcKkzP91dofS^HU46n24c z!EEXdAtM}xh~>Tx2v+CJ+{$LY-^B@h9wBaxW}JrXV{-pO$Od$$758FQ3#vl1%AsS7u~+gM zV!mR389%McYRJw@HIK`$F?h$C+g?_n2jlr0ji39np-o1qL9_cH+^bE;%Hn;E)XOZI`$tp|ib>-U(}*X?u%j~y0=Pr&-dEU6Ln;=VuoFBPCAFDuq*4w#P`LdNUK*6%CMtM-w#a1WD3ALq(K+ z#9F8=Alxryb`<6jJ3Dlulbg*)*;?o$$^{C<_G&EJ{B6cz6|ny+-WKel*_G6Y9P9g5 z^elo7Wsb4gYx44UHj)WIG*X>{@bwkEE66#Ely0Lu(WjxorD;9szRq=&eOXGFU=U=N|BAtP4`-#qTt#*)^gB?dk@^diY9A!aqJ`_QuYkv2c zeo67{V3+rOLnL=mUQHSmGLk_}2Q_Jb)ydswsyF6B%cx$4+tcAsGgC@SDf4CZt80;j z23GVGy69Ig9%l5+vdRjy&_B*9%PMg;TH-UKh^6$>Ru08L7k#`;S#zCx?e$dG90D*H z*NRsWv}O1!U&rOo*IyI5m_0o@3vM%fFCp=?n%u_pyX}%-9KAVPy?LXV#&c|PC5y*& z$o#jHtbT$k+;2O%SyKq~*?65dDUz5`v*}1?kJ35=4Js9pqU16g{4sm=bTSB>M-FSO z#fr|G;`ximkza(U#59YDbbS!hmh}gUC^izR@e&zX$Pj)iL_=p(p!kxrHM$O3KB8{A z6r*HX#sH1)@DG&O0l_D7`lUrP|A}!yJ*@WUsZu=DzU_*$JX^1rvM7GBbw>%P_cHei zy-8j^9?UqPux;{3sFuZ%ziDFJL<;9X4uY-Let15)lu9J~CS@ZU5nbLCRM7&po(SH& zo8rK?L7$yBiB;5;zql5O?P(FVSQQ zqxPE(cDB(574}Jz{31(hF~t7f93+iooJ)G&*qu#6Yv&ugb~m8ZlyBRt5MQa$P4Wo z?_{N#h^b3#&=TWBlkPmkEy^Y2!ccJ>Lq~v;I@DPG3-UU7^<(_Q-!Lp8<3-*H*_|n& zsE9yl8ce}+KvT124>Lw2EBw|JAL)T(epMN7C|Q_}PsR8kv|=Ayfb}YtpH`RU13(8l zjlF-YNx!T2kK@vHy?-3<^oxglx5#C2{M`(q$S2xga&kBF0dM-ZdI=_WI7e@Rf%6^> z<)g}$L(yBca2u$zMCLzuk1iQQ_vIB~A~ji;PK4@Lm#v>@_M$WAtLlN7pCsTmDdr(P z%E5|+=pHR118cm>o%!C5T|QOl9^`)2OqQbr|`f+y_u zhJ)SSaNSQVl0J{GMbeE1Ns$n7)^1|?X;5@Q{`&?+7sxR6nY3sg&j=J9iv+6ot>h)g zm9BI}ohJ!6R(kFU{GU%_%^B*75EvdCg3`fMJEIR)%n8L)s>EcH@DDQ?!RMI~tkF{% z#hak}=eZNGKahJu3vI3%QqID{AdWJG&X=>&0a-G;Ax`BQ*uafTFT`W)O+@;r(HjUf zKWTd~weVr^XslvvBquk8IQcb(dmnD%o!c#g{iZ%A_hN{?H%XHgQ6@VIl1w~*0{@UB_%o7L zas-WRNf}4*hr}>aC9D7yxx^9tTbxFsMzy?)1zSY5G-|)1szyHmR}Hp0jN7*{t=nFZ0hDS=n># z)^jSD{8PYgypv_;YMUj_*l_ZlCX>v6kfS+x?L=c|IVYJ}(~_3nUZ5XRm;9YZx`QxT zOiC>3E-~Rb>EG}?=ZY^?U00q+E|u#_W7}Z~`Q**s%UZ&)-(&Jbpg=M~&7X7*;0A^0eHP15!O`VgW+i&V0qZ!L$T3tG}DKMi11kP0QYq@=Ui-4 zRd3g5Zrq>Ju4=qEKojudd~vhQ?#{X)@#8EP@``Zrv|ldd{{olC;6kQl3)`-UL)Ln5 zie(V5g0j1?%+iYh<9^s>Z!JgV70eaT*o^Ej)%)cC^M#F;=!`viDE3<`khACpX&HpL zIl0f0|JWp#MNUX&0?EGVmfQ~4q-PfHgesZEl8D&d0TDB+C=s!{M-Z{QEfE_+%bU~R zi=&i#iOlxMA7+P>dxZ=&$nrO983qB9`Jlc%hJqbvObBg)fIUL2zCF)CVUXNIJ+84N z^b6#kuAqJWhm%|3Cqx-*ifi2!j-dW$pX1W+3k7omJYvZhp7F5&(-y4!sBg@z*BC3u z@=YLwskH32l(i(&MOk8&0HyO-aB8QmrAK&N*t(-s^}Al={5b3@1lRUNo!p&xX7`NG z9GJc1EKPq-|99~*`a>E@XE!(DS6Iv6e$N{O;8C4*1^0^jf~E9^m|*<$IG3sD$4zctrf%CjZQ4?4!arv-m!Q zXf?X|Lr#*+;V7xKf9KThcVp!<#>1APVK^skt=e)jwZKrmD^Nu^Wk27imHmf zZ}~XF@KP4bqG7o586|#W>o)Qb_pRYB!J?IS#2~_#5&Nu$W2TZi_~roL6349YS)rWe zVxNyyq(RQ9q2i-C+M|2(PvdA;?axa2j<<^zHFzx*qZVS$XQixmvub6AerkULw>TENFr(h;>o;d;JLs3mf(K6aC$x zzkk=?5A=7l{=Th05qVPo$i8&B1eXcvx8GmqRa}YZb=JK~?vsj(i#^2)isxeu?Y!cr z-N9nIcsBo+6qCj7Vq@{};%UV$+@CJaDs~j(#p%UZu?_oaphmm`L9*8T}N3os8V(8Pn-_A$*_CS4) zVek3>MgDJRT`!`J?Yh^E~^SiFdMH1ee*_S(!7&; zYoUsYU*x}%rAw)h1aeMrX*-=VEY5HdSiDSmOMaNOSO=7ZgGo)7QkbRvb|Sz52uq=X zn!Zit8Zy$LW%_HZuE9nl)osX8;aPm%QZZWP+qR8v-`}Wx*B;84J;DcMpB$5Y$1SW& z3pKuDwL<>D&M^Pi0;RGwHKKY6vWbGLk;2#cSDxY~6*d!DmkJA4Ti@t=y0?Y%DjdO z=GV!^zRDc4Z9{Y2$^*?YGskR&B}AC96+b8UImHcD0}mC>vTchBYYQLui#bS+kNS?J z9Id`XC-8-o@8BRZQaIFiNT9Va$#<|pj}#<|r%JzDj-9>(7Jj7g8{eTJQ+UKWVprnG z?nT{FjihJI?&lV~XlW ztf`m@P=)x86m=+?(rRm$g$Q>^N(`;4kcD9 zl&*{vBw`^)n;h5qjuYj$+IJiwN5;?KK{>u{Gl=zSaQ&^HTZclV6Gge5Du?ELIZl>i znxBDAzYCuuO?GeX9k3eElBh4}Lj;}7=~;}5juUymlLIG!rOO?r%%!?Cmgv9t z@(JE5*+OOZXBuI$&;`PCf=PgDsl!#8OCjAF&A=2SCEzp0&0y@1YT~f1pu?&msXYM_w4Tz;~GCS{IJIAxiG<{DsEc z_}SFFVs9ZLRAp~r4jiu+%q-V*wfVMO(;tbjF|9LPq>aFeuc%M5_;W@W1gKJ?dxZ_$ z^7%8@;~~|fje3~M1@=eA>aB{!-JOu92WXg{YoX4w8ENIuO;!BL!{7O?gx5Rp_^*e@ zC&1B9@nBIm@?)M$!08Y1{wD9aJZZlBcnUlZ@;nTU`yu}7s|54ONqm2e=QBJVgrCJb zga1W5tN4B|e*eI;nkDcp_(@!RfBpP_i2E(#mB$%me7%)t7kTL1@vA(YJmN!tpLZ?q z6M4SDx1`cI1Ep45a$c`0O!~G? z$FDq1@cmW%6N<+Z_`Q|)tH4$9^)7$*m&X;v4Iae{zV#mI4#Gy}7x=%O?~!GUbeEU4 zf$4H&_}k?!hvR?dySzTXqQ0&4_3|?3_vQ5GxjbWqzvKTu12%*H zSbe8I|NqmUdl}39(D_d0go(U&@I1=*f3^?*#?Rw8-v9n4=;Hllah5JIsPZR`S?6v(^Tf4Ar@0lRJ&TV-33Cv$&_j~h)5Z*i_}Ld`2|HK~C6vVVT&apN9VAcqc303ade zB>Qb?4NGa??FJUYWs!q}w6sE--Kf0+7H;a=GLzh$*$Uf;aLTJC2{MGq0!YlSr0)yi zjB@ygut&|8Tb~-fegpB@n$ATjja1QO_e@{*p7BzGK%a;~0`K);KE-)aH;J_pS-w=@ z5D4j&`Emcf!ha`uZ{faiE%%LK-yl*;`vish-2;-r&rAyPDK;q|X?v-fQDb(f)}}_q zb@X^$_H?ejj@6@1ZSr%ZBqt>?Aa@&3iN^+3%}X5s?CYJi_fuLjf9=nyD_>31YLNY% z)cZ<}x}$ZMB#@*8syJ2Zmv2PwcO19sIhLorQI6_=Ml!?OC}9u#x(%Z^e{RpZ9|1P5{0yDyT%#L`Wh`eHfBp0DDrkU7_*bPy3tyuo-cG-i(iHyI zghfqQZSmynz6s`YeDO=FXTR<>6fX7C_wQ3BKVOmJw9(B$|IRpfAa}2m(+;)pVH1CX z)4xHk_ZinjQ^k^WR+08e@)>2AsH9FI%{MkY+0ja(t!J+658s4(&~VYPLeVaPNn_idRgE9-}5 z*d;+f&@bgk2*Q_iMZ66m7v9QVf zy^U1f|HK=S?UW$f{K`~|r5}8Vxy=x>IKxOc`TO>BoZCB*kyw+;QMU^)KiZk<^a(*% zh-Q!=->)t7^HC3XS(Dv8euJIc(c8n-DCO!ch`3wpwxB}IDo}gIC{VkvZm&_GX4QwH z;zh26btSE9nk`M9(?mzciI**IgN6&S9e~;&%_}24No?SeWc-5o2F80F}HkEI+<$L}Uv_?1DQ| zWaf%Sb5H(bHZdjE*1V~Nll_DfY(mvxqA7P`&0vSE!36({Ovl%lu(~it=_^Vs>r#BR zz{U?+Gr^>>d09Va?P)awPsdQE$Lhnmk;}9llT0KPLgE@*ShS|}tx8#6TfM*)R72Ib zz^fys8WM@HQV*_$tpDp0D$i|Lpq2D$4tG-=M+zK8aNK-Vx(Jl763a`{At{cHMLLdZ8!E z2;E<2pX(TSE?W0!?uixHUC10{?AEt#DBMo`z6T?W4EOh*5m@Zs!K@!clZWAN7o+Ge zHd-Sjyn_CWKx;&qhUOVh6I3Ql_8^isCMzpUwg77kMDS0gIueR)howJ8UBqrDKp|sQ z#EB<(`5Q@V$bZ~U2gCj9Oj$dM8!3)(yx+T1DIy}?t2kWCMhH; zD*a#Z{pXPIcS<;ekC*i^jgM#baXcTwwc>mD_^mz;<3oh3C~It5ArvR_QQ#xHr6xPX zvf*aFy&no39BXvsZ`W7YKiQ!JR~{1d&W_^y%I0U3&>~|Ri27}lfZu0|2j)#qwu{aj zd3d3fYLz~^&Ky?QgA4mTriuoZsnf_r%U-i9;oU5^)%NbJy+x>s9(vZ@(j^<7ZRF!W z7P>Fy2rBeLn=o4do+fkm?3~`V$mNNOj0T?N9&=?zl5k_8nkeO>D>&LjB*8W57-i+G zT}*w--Il$#rf-j6?eyz()_v92LLa|LSM*u1cA%E=fSQ{l;DM9Vr0f~+>r6U{%L21F z(LmiEO#9=-zyEARgZw_R<7HBK6WZwObox&spTg6W-n;iVPVQD*y?dWU-4-7Rgi_TO zjBoL3_Ow-FFNLtI`>J#Gd`^qJ?l`C|HOWm@PruiV+V*;{{s!+%>ffjOw;b?6A4ZxZ zyWLH}agrcag3=~Ii5O?GM=>h@z3v8-#*dK|r*w((e9GPC&Qr2*E2GUKt1lxbJ@XYu zWuqyAm5VE(+ndlnYODzO6wt|CB&b;v2T(JP)qy~^4f*Xe6%h8_Gl1Lgy92@zWBbp@ zYoh?v-d{KLGUz{bt&{tK(gwHLe`Z9pN(^II=+EcVTa^v8N*oA0pHJLw_u(#J2){Mt1^mXtV-Aj}v)n28#D_DGa?nQ=%{Cm%J#Z>DyzZ_?xc3 z_J(v=VU(a?Ji_%iYwJ<`>a#cnftAhXN&_rm9a*x6a$lsXDsMICWQ-*_Yhn^n zGS@wtRreAM-9e@a$&*#osC3oTSPWGYN?t@3Ctq`m6a$1+*w5VJ4kEf9ML^wh^{du& ztZXah9`%zQug%(gm7TP7hM3z#hX$*fV3lJ!JRB86JDuzYnOiy4KngBDx0$A(QSN|C z4|2Cew!lA6aHcW^t>MQPXSxq&Hz%^s?R2N>bVs6IoPB6((vW?yhW?U;hz^$dlFQZz z?j%UZ9vB}nkqd*-$q{f$;8M5_Ky>XU>H4%l-7>cYHh;2xFulS%J&LW{lJZT~uv|!F z3zr!xzQ>yrYi~&(kv}~aE`IqyCE3hadn|uyEb|8lSG>J7GeK{+X84S0-rN@OIvNzV zYfhpjeSkMdCrh?|{s9eF9|)2C+b}5X&!)_wSzp-BG^A8j8>w zG5&KKigczeu3~j>i%U-;vlVgoib!!%`zw53`UjZJ5@j^35eX&n^Wg;RM`XcdYe^c8;O$@uGi^gU_{R$DLe`w&$M6v=4T~YX)bGvwQq59*Wv74p+ldG>G$H717zV%9Zn4EfLWvul1Z%#1gXFZ{kIw# zcdF*IfQf2&(DhIPm39I^}wV~FiD?8 zu7h*@d?vfP!5rpuy2d+{m7n!mc4(sWRjAobHO`HlsY4keZA#92y8rIbJAci6^Z_)P z1K4q(e|-5D^E0anRzt2royBOgq?5w?x<+ej*A&BVoe2M79~T>>T-3*@8FLAOqqjV2 zhH>UWIC@V19wHQ8Fg4Kakoq<`&ZS-vXblk`Wt>SC*x)O%7VsfFl4X+G=g7gbt)Dww6{Oq zeWt-N%3?0B;3Nq$m3&JStd4n4nZDCCr>hE2kX1R$der@A-4m(I*XLPRQ-NW5qE*y_ z-lf9w*JS7(qb>bM2@+|(K1@1CN?8$6rd%{ zC{S45R+#~562)ZD9LlJwMwndB_gYR~8ci?Iy*1Y8ZNfos!srGZF`@y*Lj!Cz`oYR{ zeho&IEtzI+=L0Hm0ZXx-)$qHVYfjT_wIp@kd*-DMJ$?Nr=oh-b3&87UowIgeox~KT z>WF{6E|of`Y%3mv_lF(zDxL=#&#lGDoI%L=HD?eS1zMbWeP(MFy~&u$rXQXD8wi5G z|3VaW>RAvjs|#XZE7$7|wz=kcJEv?d9;+Ix!C`B#+IVj(FKiWFV-%Jeqc9!v0f$fr z*-h(3SX4>uQP6U#XMD&uVd`0q`vskztUsLug`e^T%3-WNI5G&gQ$oln=$0&DAlT40 zzq@BPDZ^;)Ao!3Z8=-m1e>drE?ix3COSGjF8`KkSf)m2eMIrbW*Qkclht^Ulr(i)1D5lUNfWRk&=3m0v<)O*x_s*R;b6#`i%$dgxj#DQ<>zdkm;)~fjT4PWXB5H8YRFN4l z516H4OlXnFz~dPlCYu}>8OC9f3Gq$3F7kMWaM6)5{~zv;;QKe%`SIWr zevju*aD5Ti0`T%QzC-w)Z#p#`^%4Hya`p!G`&J7rZ?F~~PD%Fnzf9foYb`XI41VGZ zMQGX-bl?5I2#oi|b59GeCv(?6+>H*Jc@;*_)1@Ul~nPc`BeXcP(Gl3sUe+qefSQv$=3;jOac=YqRw z{haV{Ft{q34k+04E&RQ|MTkScA7kojjleZuz@y;qw-N~TvVeb{x`=MsvC||zN=R~@ zAW@%(>p~yx^Hn%7eSeMwgT8&ZwGId8^EJ?;6TxVhptj_e5*a)Jm9S&ifX8+h2maZ` z#xc?6vA4u6^XOa2taEqW3n+pZViLrOxr^X9`P5?OGC2O|CFqJ8wIE-ojN-_qzriDS z!-o1fZN8qJ?Ib8WyBntO`nTHY z-;7(U{XGx*dGV~FF+Y+T)2%he8s7H@K&Jy&f_S>KHzXs*Ihv7KcSpOy%{|^HVGFc z^0#D1=xC*11?J}H_lNWI^V)p;q!&Uv`S}+_a$bI3J0E`1?$uufUe!oNlEl;lGnPicV+i;!F_nRo3hO!vOPg@?S~N}D5A(54p4rr zCHRTYqQcNrcKF;^R)focSD3l~)3n~v`~7o29DBXs$W8b?b`ncuQD9dYCSCR&%kHip zKyBC-#dM?jKLseQpG~G!bUPsdJO`WrR1V6L`+Bk z6M@oF87N&`2U?H)V04rrG0gJhYSox*EKQhZ^7w4^OHd z!aznuZVWGpO!-q^1cD{k+zJVZw-j6xC+T5A8T>0w-gHfZo{T>Nh9X3yIH@8r#gdCY z9gLzu3k}SDp+z5nR|{ah(HHHD%6EMM_Q$-YK+Hkl@J3(n z2w)LuG2&+kPrn7%6}Uc&`@g~U54ax0^?4lErLMLY}@8SAST*NE4i}K{VsBFHAVCK8tgu3!w zZaBOISoyC1!n1r=5cTA{pl;UsKCu@)Uqp0a_O69cX4tc$%wL7@i{4^L+lyceiU*E= zX6n?9v=pYadSYOLZkBfbMau}KT&hy&CRja@z5U$y3&}v;RQl0)QS~>{Ctmp(Rz|$G z=uw{UAaJD_|6X1IQ=I%rrgZ$f$@S>MN~|s`v%+6@BK3~C^@XXLsXqe-))Vmq&`au` zjbC2K!?Ewp{u40_lZmz0t>XiE%hZBC>N=~^qea@br^4ETJbeyq6gWU_~m zD^qk=?y5}mTE!|dhwQZ8YzGRcBJ|Qntl$)jGaY%0;2E`2_4sa=-yQS~N3jrVCnKbo2Tj5ipQ|z}rWs@M187z(Bx@~`-{th3 z{`pZvP9Y`x!fF3O-I<-y%QMj_!~Owmpqn})%E zApg%qi(Nl6!3E^~7D#g1PLM&<+c*mkwNJ_7+cX$P1s!kmo!pC)jv3vKL{QD>^#Wq4ow=HYZTVO@b*=TpQFyA1pU}e4b|P<=seC-W z+A6VahsR`5VOgh5;sA}!`kZVG>6>xdbMbTlCq(1SXWYLV*E`i*?c7NRVXl<}5!JxS zZL>bYo{9Cjy7!@%$utqDOrhvd(#I#BE3G~*x*E~DAmvh(lAfG+Ay_?`8TMoM}FW8InL zdjX{aoyiAuXHs`Eg_p(|pSm@Lsek4}6Ba#LcQW}RRfDaa@Lp)tSd#uP);i`R7ENb7 z>E^=8X669UC`vc`Cuwj>!|$fdilX}QAOAFX#~)BiUvT(XUvT>PPlB6q-Ei!u!QxfL z$=^cq_mKP)lAj7*{|!9(=1+qkITfrtzMYmr6;G$KO~32;M>H`Sn#V86u0B`&jqxe0 z)LU@;r@@;iev17AWvH!0c6;C1To(Ec)cbo_!vc&->n4MZXNW`CVuoe37(Frp09}-x z&J6jp;dA59q62?{yKitd{V(WTCo^x(`2PV)cM0M2ij+s zd@qhO0W#xL$zre+i(IIGp1!F1tJ8r+Cnlcu6%?ea&aEi=0v-8KpRU@|>K_x!h_TQW zqjPmMj65a+W{{Yq{1^NBZjvw7S&IctXS~VFvaRRFCz3$L+E6j#uX}#mWf)ZZ(-Pto z8N%RL7XOKH0VWh7548CbjuT*_j}6QieM1^+i~52aPe2YQg4Z8|9KhO}TZ);#%rYlu zv9h%UCktTVUi{sy!7rV->!qgwXl!E95faunpGK>b_~H17#uw|J4}N?zwR5?c8hPj= z+Kbp9uKNBY7Gt3^h2kdf`Z@B{2ghh&nDx_UDvyGS`46lg#)M>HT5kAAr?8~g&}I6G zT$BF0s9b&BBdM1%s}ThZ?)DJ4n`oVN_KtJouOut$eiC1tJ_#YdJY9y}wv%Bhfthg4 zEp;IlPy^EgHaye$bt}C(sTF75b5e8<&(DW zR~IJ=oj|6{-%woY<#4e#1uHxDaB+D0O|T9_rRl{|IVaOU2|jQUR)}AMHO*t^&ZXWw z-9gL8@iW;{_w)2i!IrN>iXmP@j+a_{8_`7;!kek)qfuRgJWW;`ic_} zBaYUQ+v?Nu^c6HCr5>_H3H%3bzU9%fJAt|7UiN3M!rIh|7ZINMFQX?em#-P8mv?^!HPOZ)ES$!h8-u$SqXNjO zJoEd+x4Uku^7y@;cpU)H_JhUvCcl*cPr~D+)o;RH(N0tUC#UErFcY16;=YN+O2p8}??emCmh1RJm!MHf~)oNQ0OFmcYu z`^jJo+Q9@%y=XT|JFeEO{|LT1#(&H-z0;&ZSzGV(u#oLQr4^{KpsC5sVBe7etQjn;3ht(uFx4qmRr1-VJPr6&zm3w}3| z*4&M}Mc^yB&~~2F-gd=X`My`&PA}xbGw^reuFnEn*MW-SE%TM|G}f;T>-y-V&xZzAgt}YfZl1g<+`XE0i7@{3!r{i%GoY)6kZqfKYG=C{=(B9@7O_q$u+ME!vRoPs=_*pEuv1djHr% zgX|+pOu1s%3EYxGs9XNVn??$!m*5>FmD7va+abrejQ9bsQuvYN7haB(c2yQ3Ke5G& zD50ieQKA@Sb@Sk|_~i2!H^Wz?w`A|JUelwzBo@<# zA}(H(UHHw3e=kV?tm1nW->!Rv04B=Pj|x}@JRiYZ?;kr}m|pL%dn68c$@ip*>WQZd zuq2q{@ujr2yu_M+0N+Y0@WSEup<0>Y`VB;ZaOBfJ#qt=QlmAEX=RHuO;;jE$BqhlR zYv2K_iip(}(-Z$y05ONMMNg)mBk*;vgB1&dyZ@O=J#uE^`GRcIl{CaJ&o+C<&iK>M z#fP))KP#+5u0*N#`|0BuD&GELVftj<B-{i z?`mGqFDzC6o+nt`{=MShWlc}M7`&|L$*~9hb>C0@unygSa#6*<*j*yX!|#JY{9X*$ z>n2k#5Mb0(p7ozVz2q}DWoUu$!s#HZ`5D${qdLYK=8?*eiC^~H+FzqWgEa_vFI1t8A3Vl&rosE zH0|0dB6d>YbZxqy_VvI;z)D=2dkATXqB`WMPnT-n8di@6D|oHy)Fzr@6Gfm1N_@8A zn)E;I`=2|}JHbF@=oFg5^hCu=*w#Go)xZAS=RSv>PGfY+Qs#C~`lX6jDSe94v+Zxi z3lcYO*znfi7|k?PoPm)VI7W|vPss*6xaO}u_qj{9zr}kD8?YMT(16(`!QBgy85ERc z{o{mm)?c4i1`$|f+lM^a#e2Yxl5A01*1v}eP5iqr>t9E*!c~}F%#H#T<`xQ0mU^GV zmbM*2PbR~s>DgrXjQBcBUzuiXy*r(0K9dfg$uyr$htFn*PER)Tv&m+Wvzg0fx1C07 z{YRi!m8r!Rs_FMp^~=|#vBwkL6^LW6n5*{w91i$&nDYYTbUEz~Yb^vW@6$S)9Y(#U zVISX|M)i_bjBKAz{Qw*53RV9(_RvDM)Wki)7}9(J(j?fb5R?fIO#7+E5A<#lm~cNkC&^(c=_EJ+}VS#C2-aYr!QZ00^WR4 z-5rIglht3HB71@%GU*lbfxC-#9vWl2pd1gACQslr6)_^Fv6HX5#W84bV38Vwg=G<=C14f`%+ zBup%FmoLfeH{;>ojEDdG#>4jhq8-Mu8n&k5XJ}6)6R-Q^c^Me0{1H^xIxoZb6*v|j z=JPV%gD$dk`&&=FS~sDN%NP>Fo5Z%P|4XF#%FeMl!EqU1hDGszK0Ek%8X&weM`ip) zT6)Q_rFp^t!oG_A1|=_z#TrSW>;Sc;?2 zo*P*58JbLcW#Wa>>Q@F{p__qY^uPMWvE%Ru&*GIn+n+)YSDL-Wbh4*ZC&?y}0@$et0MTy^ww^Fz4d*#GDMB(!hy!`I1A15bCYx z#=n+)OWoJe1zg5mz)RB$rd}d8zqaTnKo%#6kvGDVb-~?F(gO;gRMGbQM{%cmFwrwq z&}e4-(d1j}PQ>2=WA{?}B<2D_$;+l_0rVoi5hv;fA6SD!l21MR@`N{i9C3h+MIQox zQiIuzg^fs~l;YIY)nCO#Q>iDo`!Vz-sw(~tKF}FhaCPUUo>W}}CJJAiqQw$M4&pPd zE4dcQ><<`m6H0$S(y31ahZhFNDFhGKrVHIwDG*iNRTzi16{gn|!#Tv1!(|BR(($9{ z)#|x-pQPWO$!6|}b(h8m(-qYdk#?k)(QU|{^7?|2&fHXRfnC-1kxATqQRRnin_xY5zYjxaPVa6 zCpayF8p%)5NU+sE{cvWJKYRVT@z-Dq7ABX}{a3sS`tjr|ucW_80>>F77YTO`{wvf$ zNNloM1cpBkAd9}4xhP$9Z+Z%2@bMp~-ZS<8BGG8Am_HVeg1bM4C*z1C`;!an&alVy z3I~c8);*bgO7D4EbQ1S8u&+r!n7L?d`Mod_H7JUd#n9p^1fnsPK(su#``@UYJaAKC z`unGzfB8W#^)ShcGpmbe^p;({0AID~7f`MoO(K+@3_eg_h?wiUGi!@59L4MV{uJer za0Qm0>-bW7;?xv9PX1u(EYHj$rRQc-cG9434jb$ueM&vB+GE>Z@>= zHk2ZB5hSx1W*heVV%+%mrpuA1ljH?pHJJ)T8pc13vBPw+mP~M*79) zpUkA5NXMVZq@GO2pPUTygUPVS7Un{k)W4?V|2oDSQ-H~Z6T3hQ1-YO9iId76U>Ezc+pXSY9=X*nqppHPW)*yxe^CW3?% zFyW3?O&wLgjMzdStU+4OArVRPoV0UKr3{jrsU?wyJ78zN@Uun#^v6_jZj3#vu6d zdtt)f~Y`(S7g(#|$` zC!T#zHtF@A`ng(jajIgX;#)Mo;-e5WAG=?Kt(K@c`R-S~5C4-V-7=WPRu*^ShrWXC zew+$Mv3xp%VDYEYBZW9QY-*CGz*`F8ccvfto$daKpZn5}{?6NB-~R=3yqM!3`%@r} z9(4S>_=e#lYQ)$GLp;pYRRIM*Rh^b&C0F8NVkTb^_lftSJAubZv#g~RXW-VpI)02t zn!)fXn*AD6vtRW9U4+OD%4hwbp>6;qp=5~|MdHWQO~{)*dFl+N_rWqxFnlH(rX{4y zIX5OG=oABbpN<-?tYKibu+H@MyrkicF^Y>*pQWm1K>KN`g(mGJ+Vt*`d}z~18fV@S z7mE(_Z~#Zji>ck^He@D|XE8Xvm^h6E!d0r%B(7(+%cHlrL1fnYah~2~V~?E0c*C#q zO+TBtI9M)3RfU>rGS`!W)MAqSV@1KsFg)H>w!H2q$>MDMY{l1Jp|Fql+W>$`*5Gd1 zd8z5gP4zJnNw#P&AeBu#=M%q*;Uw&)O&>tAG#fsPIhSXB^|&d|u0De~n<-M{u`^U} zNt_llz%Tk_VI8K25)EE@kyL56X^+2dGI1rmjN zc>$&}I5Xy9i2AorO@WO_35`8{1{sR8C3gXMQFi$!a7R;CCE2FCisf*K=I1`?$NbzU zOW>OAq4~Kzm;}X$swnjg@)iLfI&B6gAnk&JPG|Gdn%puMIzuL%!Lg45RU55CCaoku z8@*F+7Cu)o-YGz|B2opK%F-97(UQ@4*A`(Z(wmi|L1hO;-avGkr4vP(NPJ3~-<7~yFuY6UOJ*6MccB1W2RHP_Tj3!c=ZT~%g-Qx*=`l;!)hys5HWABo&|2UJyv5Yw0 z`HyMoGxF>yw$Db>{I&mXG>^M!v~w3VkGp7I`oYwH)&T&NwLbZ-iWiJY?@ap@o^;VW zX^#8Z zN12F^;^U?dn0v|uGgxx@c=F=()KnX31dixLr+Pe5TX7OX&$fDTkZLwr$X)2)Ry>!y zsp2FUCziFLI}z`*;6Ac2{bG7*`ok3`gpB$0x?uPvUd&qpITR-=)hb9n7{{>+64Jn- zrW5J4{&Y*>6m>BW`OO6r(=e0wQt!@Yqvmkkx01gF3tOIDcedg=GNMiI^k#4Kj-8_z zOj+V>;Pt}k-zJ8pY4b`c7*{-vGaqDm0SQkIbT;%R1@87il-?V?S2HM~LP5b}#ZvQjKKY#t^cYj0gulM}@Vn@87-ijBLXU531 ziHX&c^u;)+S$V_Gz%+-RCtF0I(H550FfN{K2@$->mNM~GF1~8TSB?0p7hgPFo@{9q zcTM7}LwvQ1uj|FvdisL*LMsbtKpL_<2HJc}Kd=-0AZ7(+! zzA2P!uQKRuS)qN^ZUpCzgxA zIK!KsR<}0nfZz2%Fyuh6%2KC=n1X8so&n&wb?n$_-u4Lblw=B#2&`9T+5@earoGg1 z$>A(=Hrm|Vbddw|cL84g>1@$Ocx0h1op}T(tl+IBkAgzyjT@i)92#bQ7!D6S=iT&_4#jBUFwK(dnXOPqw) zdLgX#0If+V&v>%S@pj3J;09mRPLf*%*Vm8T#PzCC0twODSb!2qlJ-KNN%|Q=Rp(Bj z6?{My34WPwTH4`!_ri1T_da^p4-O;O*z2M6kfi5>nGF9p{;iuKRuz?hOduAmJga@z*l{kiLC<#b8inc(>Is193{KKXfk|6XU= zCWuB%l@g`nS&er5W1vbPqG{qRL4KPpaO!6XzK`x?*e)5wmq zLq5R=jx*;~I23sw@drIP`?%Dbq~Ti#s{}IjRU}JkD$`#-ce3tGYNyCk1Oh{fsrcQ2 z>e?$#j32w>?Kp2WEJ(!hn?zzq70SH@nL2S6Gf{w__383yM7_$I#7ZGb5x*?Km#40x zRB0-)3dSwBK<1y3(L!eWOQJPC;)1B+kIh2OW}mb{l7?rs0|}g>9eQ7{C%kUm+I3flnxg}QvEEQ}Bs4M_8xHm1?&{F{5|?-ueDH%IPo-x; z=)I%y=$4^qXk@r2=II$3P9#IAf#KwpOCrgT=f;~t*MvUmS>UPK;aTjt{X-sxhr^#1aWW_gvz6@8H02EL44or=@*;du1ZoTUoQT%Co*>V? z2S<9ga*j0{QDSH`m5iz9$TP4FhmLQHB?tv%APkc6XpdQ=GtDI%l7?c5ehJsJE!G3t zJ<&nb9mTKZo!4G{wY-a!CkAedf#1Uwp$`myAQaot6N~jGLPOCV14F5yP$D%tIucKU z)0EHC9R)MN%DBP^RVAWBql2-?P&BbMLM(_6^ny<&GmvT9Kx{h!ibUfeV2R>D0vw5r z@Y6^k=;8;vFs$^Q6AYD>Q=?__azG`_P3ERPTLSYnW+Eer-w z&5p=mbf=*OGEZ+jx;-))jYm;$ES_+J0Jg(D1A~#+4kCr0k_ySf-NaIn+OWDwr6TX( zK+ixj0?s5+uLa#I-ixNw6N_vCVWU>!P-+m00H#?uSftX4^pGPO8x(IiF_7HJdDd*) z6tPN0aFo5^YBULEbVJKDH5Q~kDDzGss#vcC!gxan(7mKkWfHMa;KUGG&j1h`7Ql%3 z>Sf&^PBtzJ{aQ28vnDo>?2pAm(NJG}WH|Y|5Oj!}dvq9zH$o2*qp=<7#5B$fe43 z#Nt#y)i#@49q@JO=2#|1z7f_hI@!N31J5f8XY!dOV6+@YoU@zb+e_2 zY#TxQ)V9FjICXuRHmd+EPm)y;6+rGq%# zXVC?1izH+QG}gY69L0%l*%FUI&M^<$P){^2x?$1Khro_VawO6p8-(fsf-;g;4bq79 za1X51*3#3^cGxJih7iD}sMi(*Iiw4etCulELuk|+LZ>4`1H>yx$JXq!FJ1T-O8M_$4xw{BojC^1przf{B=m90-!FByyt zZ-F}oM+8m}5~>GBwm?56@4)vvalH!{4ZyF!Md|Ox_j_=Ka4o_`Y462%8Lr>L z^*&th$MpeRt8lH%^NnQdL%eglh*r0Y3pNb*#zzKvL*+}CEUBuhSrUTx4o4o{di=_o zWmneL^;Cr5Nue8nZ_0zW+RCcRt3u`d$>eC_>JNS}Dgab&85!9!7)y+#;ytlS3|c;z z92ptx>5mQ!e^8X~Ub?hzNpDT8yRY}krQLnYYOd^Ea#e44Pqezbd&!d8x}{fDRn;!5 zzN%tgum=aX4TY}kxw7uczSvdKt76qxc31UvM{A-zS1pZJRY#-CYOn0QD!R10y1J(q zpe^#++c&NbF)fL0!xh8}s0)9*x2^MdcNKcyRpj^Y0Ye9o%E1$Sk5G<=Kw(3ms3B0i zB5f3LSOa38++ds~s-fb>?*w+Fw~{hi*m zfno*+pnifu`gIT0gAeH>eN_G4+dA4AyNhXSpXXf)$5z~s?$BpDgiY;1X%0N? zz57j{@Q)RY1KDSQz|-D>%YA_okYUvRH0WK9qN7wEA9`h)e=&X-G*>B-YZ?MozGhqb zDrBYXv{ZmT_4LmwdpC26s!S69h+sS>+@HoppFaV?{x1Bm$}sMGeH!KpLW1n5$MvOdK&^=1vh$~fVu>nqzR`AHzrPVghPC!B|G%F8<+o1 z6V8f2hvH>tL!e{05*mdcn;HU}fmv&ygA(LVyOwlRdRmN!>Ss8x88!t*tBM*tKGWr> z^B%KK=I8zenh6IMKtUJy)>eAL1m+NK4=-p%(#I-2iAvAf%HpN~z9bC|2;L7mqNxmV1zz!kKaeYpre3t4A=ezo9sZk z==K1f*tMofB)1`%WKV*i?-c;BN&rwy_ieQUbm8YNdk)sA1AwP>Ef4I1-zl&cbpg(; z%P!(Ab}lr#aDmC5Q3+h&3b3oehi34@4Qz+K=G87W=jI4IB=phqp_wg^CdftkZnxJ= zy3ydMdBf~kMrO~_nVZF_gls@Hwk~4zwdO)`qT6m~lnc!cdAPNQJlHlEO{Osy6(Y#Y zGKY$MADb23NNzTE#E%zSTWcqoi%m8-Co*(iUZj7_RRJ> zN8TIkPo?A)2@=wrNSGO?nV(8lscIcK5{mY=ERa@O^bv7Oaw1)WUrb}17imzB550ET z;oFC_dtBBK2o+rB7$b1`DhdeDhk_sWv4OMv^NxWQkC8@Y`8I-KmDgjW+l?_2jqUc! z{PdghuLu;=z>|hko77l}#$G36KKktjx61+djLiSrGQR=$W)p6Rf*<%SrGGB?4j6E2 zkflTBZ@1-N5eTU<53v@ja;)Je@=>`xvfQSb%K2Jt1!>%e#a8@z694^W7ywx~V$4I; zTEkze*tgHw!19JbeRH6yKd?L;sBZ`~ zH3V9l0__+#BXLat`DC8fK-JBG4F{8+0>^#*Dh1GNo-lu}Ms&=~6JKKh>Q>&stZ5H~u2($jv18!z+zU{_9?}rS%r*_mK^It3TkKr^WKgzWr>O(vnmCxzSA`QjL%b`4M>Qc(f)^AGJf-X20#W zV+c6`$1+@_CHRNW2k9U9V%Xgt)9&6Y^IawLiP)p&`&NVRq^~Dreri_qp|pRMX%wHQ z52d{*(C65E~yetyHEd{il43WtxglQd+%BTBjo|gna!ntr@?i+{qYnY!FQ) zM1Au;GS5$S9&~eVy5ajbJAXy&u1c2wdoaP@l+zbD+tQEiFocWbakUTyn1=C< zAOk`rypY65N(RX!7eE{jQ)sPV4t8)wvWOr^l3MABnIfq4*d)SQM0}IE1(EV*B^5Lt z@)(E2AfG4s`6`R)BL1+$Na*LPWp-y>K912SI&NZMtrl<_hbuiCtu#RoIx6Q;rvhdx z?7NS#XcR0SGH+OkceDk#+=YmQSw1r$s@D+h$^efblTD`ND8QZ!n<=_&0zJXtUCpMl zw41rP?d%9!`Xrbln;H+_c1bpf79bUv*_E{Ekd2*d8F!m93%n#Sj<=GgOU$lg9?wyW zd;*m>0u+Y>OeJB}Hxv2@Gc(}}jH;|$G!3^K8}FRtvRPA&VxZEac?X#ZJ=G%N2)!ZW z_Q2@v%-$ALkQ_5)Sv6pquqhyHb`wt%uRAmF^q2*_%6-^97x_O z56wFooq){>iW*GqP%R7S!)V!5fweS!8EjxozeVipDH7db!0|oNFS%GS@ ztWSP4xGb!a6s)a(>gHM`r3ga7Xxlm#TV{^wD@xJUoSC)Y(GA-;Av#hwhN6rUjIB3g&P_6afUpifdD{B zi)F@yUp>dnHc{B*%9cWS60-aE#b!c-O@o1k4YC_iYy63XM<*wm}Q%d`~yJK*|D@$hU1 zxo*b5$hZ{_CfsBBSajE|LgCj?|4!o%6sPK_ix0yMpzdG#4BS8rc-(|+-8jq@6cN6# zY(zi2Fdpy_OUg_#lo!1l48jQ zwQ)&@kdS;T23R(qS?DS_C-V#QMEM(qi%wi4{eoptJfYh>4m<>5^W>-qIr(zf1Rz3V zNeOWimaBJmwc#EW!CMomNPGnX+T}oI;dBdK-&KoP#KHG-NWwEtUsfCrkyaH~uc46X zs1Z-bJ+jg|t5#Wd4Hg#qI}p*a$|JS{@(XnEVRr#|Q&4c*rB2r0iDG`lG4@GVd^fv8&!U0~*?tfu#&LGFj(_p+rBD+3!)fl6hwpdrdKv~H02 z1aHS=8@CdjdFJXXJqGcFz|5R-0OJscu8Q%pvxYkak%ORfk9{w&)=5T%l!JRZ{nViY z4#8D=eE*M~ct-~A{WOAZPX)e;(?0GD@|LLdFn8~Tx@ze#2lt^}ishUN6f-9`nQW{` zHDQpg7PVqo7N8#lj}AfphgmD~f@(09k=p9j*s+bj57-F><5fNa|7MwF$cWTQhE+5V z975-~+r7X|*Wvrjj8drdz(ZOgsiqaL3RQPra4<%*NGy-t>*Yp}+cqdVlAGE;p9*(~ z%$*P*QKc$mZJDb8xubN+%yK2>H$tvh=LqOpuK5bNs)%fCtEANI8q?&^m|N`hE0Ww9 zJ}*KE@O|FZIapv3D7a_W+g~5RGm3FOEMfaGUp>j!{%6GMmsb-DuDw)qMV^LN@3ow?gSr9^U28?WP9EP03+L&z=Xi zyKyyYv}>5E&~yWS!I`z)=8E(!btb|opvLQF%6VvM_mz0&$DV|k0J$Vh5||POx^AM@ zne3kG@YyOojs%B0BKpB~K$|=#>Vc?-#X>OloJNFgCaNq~Sr{EtS^7k8N%)zrDKB0V zXq(9nZyfIT3`*jJDRsx0yhY%tyfpSg?Z`L=3T!^Lk7lT(Nf_iohD?#4i}~Cwm-HhQ zC^==QVKWB$cAZeEHd(tV8?336Uai$Zgk78?fx1#5AJZ>HM=gf%pz#7zsJjuB?A{gy z$hrA0-FDW|-M!elrE5kLa#w2NxI+7*&cQLZc-a9vWMT+%c5~q<>$uGa%Hq14OPa3` z(@H}e(_A4=AxE2vUJi>XEx@})nh;aCZyEmKbLJw%0q(>~2Q#LSyHDz&oQ+#uD2#nd z&qz2uw*byz2OMmT@auTO{a8nI*w2xfqyBK<7_P&9ChaJmh+6~&#I(0aT8kV$jvI)3 ztPS<^C_>*dfAuX#p!DsqQ`CTW2gzDwAq?1J>RXOz5UNLT9rZT>F{+hkwU78CvLGd~ zfzkz;?F|7@w9zQa5OqE$#XMLRm0@2FSH|%=T>>L&9^Z)+s+!w@s0sUdn0u7WL5HLM z>m(Ql<9JA{GYc*#`gm-jA2O0h{4E9Kvf^xc6|NHamEZ&K>p7fB;7|>~II{nj+b&bk!kOHhP)>?#wk)xU7J#$~(YSdZZ@0 z@KF_U=#K1$b)|FDWkV5MnjnXIHAqL592v56$;UHGnztNRunU(hkcL_5Vb4V;I4YrT z>WF`>)a<6fL(r`g(DKL7I!DpTr8)ADIhnhGk7fNsh@H9+D^?o!)JKq_h++=JDwd@-i1w-0& z%P2Vr)wh)%!_v4Y2Y2{7yF=d`#5kI?cQgDDbhNn;CUrWITvRZMA&gMN0_H1FIrPCu>mNaHh`#kwCh?FcTd z+2jJ<52dtsVB2yLc4&sc_NJkzP0?FBRQn2M3LFJ5mW&@rb#Qj|OKa%)Y<9 zZSWL~W}8FDDm^Y_a~`___|DCjJAxZZZ^>YZ_Syhr)c|AF2xHYGja4icxU?MPVJOSt zf);o4dG&I(mMp^Xnm0UMrf>5&IzBed+WJx(^8KEmKv`r?%W;2XH=rb2i488f;+MQI zEw%LEa(USZUappgU-6QovvxZu8ArUNx*0jy-P+PvWksV<`JzH_9Vn&*N4-n~1Q*6P zc1ZcT8QM$vT%b!xt7m{jJQNHG8?99mM3|CKOxV+SU1wCd@-9Hp(kUY`r%^J8@TG!| z7R-IMZozS(vkIPks%}TcQ)O;^+Gb^b>WmuA0L)l>3 zW$lwzkx(KtWE(9|g70y`=JgKqC#hBBxj3NQBz5I%yzO20kY*rN#af^XIPAH@eEK+G zk~gNy@<_>lz%qZmje;`X`6Ea8$oRjxvS+LE5X@ z?^ZjPd=5v82T~dh2iM?Vv`XDqeL86qHALCWsf$rnIcN|Sw@dYOJaj1H%+whTi6qUQ zmc}_n71Cn6YlL`3x|`A_}4%pM08koeNEC&R~A$%fHE6KRm59|0$eYAf8|J! z?@!&S6Q;uqIDoKlHNJ|m4yigA%YqU1RS8GhKoXxy5_VA!c3cbz%Wrl-Qq0OCNk@fR zk{S}b0P;z_Ri#|2_i>M+WofiOmp)=4LrzCrMXY1ccsiObhby$LBV0*FT3=)b=j4NbYnOXZ)Xev+3 zS}C2F9Ox=P>ze3HNf#7D99GJqk!V*m0HYT%MEE*1j9hlExQF;8`vYW_fg#8-0$BYRX`EN z7B@H8(MJpZtOx=P?8xOYtvFnB71J^GkU4!n?7lq!G<&kCmqzY9$)@`X(TAmSo5^B$ zV`swr0O!dqt&15i5Ow7?FhFoajRD&+lU7o>5OY^S*-Dfvi%Eq!*64zSL9ofmd^znD zxa49^xQ)@bQQ8{|61>jKGFMH`liMv>nlvR=9)SxRyjJ!W=u6b_ z(sU_hb5{k~Q2$~J8e?s;DAI*A^+2=UY?W+5?5#bIQQ>55q+~7{7MhgH4vs8{Sq+=o zT*2oB;*q|NNkDI5{g~XgCd~zgiDlIEPZdPvN_E-|d zSO$gGn?_akJZ2J0%U*amx4Gn{*Y}i;=$T;Q=&C@UnG9ucOJ>6CqIYlGaG)pX8o$5WL1;nspFP=ZjH5r z2uF)#brwCPnw6oogwNiLfB0;owS=8`1A~1nVTWD<*olMR3f`8pmas#d?f6(kz&W0K z23VDbK^r9t4m;0gqNjj({}3Y9?I|Uri>oXYWio@uk+*G0~UPRi(4b}pRnb3 zp6z(hzzYYQA#XjdQCapm{ML2x8D|b!eGk}a6Z?7TjJ^9Mj71X03VkLh(^D&-_u{#~ z+?0z0M?5Eb{5=FnoWrSc()6zmlr{wxf`-;W@fytvJ`eSPtg8~T^Vizzs#klHn;+Pp7{QNk9iFTmN$u0T-*7+i4S>27jSzH{2IW2Qo>(}-&)Td_U|^sBq1A> zEAFQP;@wMgEl2J1kgV@&v0G`#uds8UZQhG0wn@TxA=ge=c(jqCgy;;-#f{v0<9x;| zPWI&nU*4ix`&!NrX1U`uU-TxOWD%&8BXLtsVr!rz90+Zgt%{X_vamW~7PYtAZ`ayx zOB%_J*d32ML38^p_=nFy8}BWh6XfCy>vEVMFbdTS8NYjs-**_lx90i1)=*yIUy%Nu zlsMcv6AmA<7hR5WgX zb&PO0i6_Tx1>L~&vISeNIfCaAmoCWDCkMRE4!k&SEbvkUISTszn%Hmvr_9(X8nAOG zX}{$`t*(71Jw5Eb37p`dm7Np5dQk-(Re;xHU?ZF05QP%-_DYrN0)W8_(b&qP85{z{ z!;t9xfO-VqNAZ1(`R@W}Xht-7(CSjlT(RT@2^UbFIi8n^7mD45mVcvUFfT6gh~2JC z9JV-sJ+|T6<28@f^hdN};FJOc4^KMo4F&;1yN)7K+I8Mf&zeyM-Zh!7ItM zzKca_hrLle67RQikvnT=o77Ik9Btak6EH4?irXZ9`b>}g-fel>&x|!xVq7X(m)U0K zRj=6NGFL1awBSixG&Ew*yeecV&b7Yt;>x^g;AouI3!ZJ$w`^d9GO6w1?I3s+(QY@n zvMW#)j#pe9fMVKJ81L6(l|2OIK8))SPE?iPw9WK!tr`icOzGtzucrk5PG_7tQIF>j z5l3?LrTToVHa_46XER}AG53CSl9F?;y0J5Pt?}D;o7}Uj3a&REni-pAdNY8pGk&X` z@05OHp7iUD^qBGc2GmUlWzp_ndh4Zc1UIzDook`st|gl=gXVU>@iL zdT7TuZT2VAppHpuHLC8#Z$g! zV~Gc3IUcVXvBaY;>2SY1Psnt63_YJo|Ex?aA_VZM$8}bwJw*u?KCWZ1FF7f~u$1A} zr>L-gUozF->5|qj(-v@UQFfP0zP&DK2VByQxTHNM)8wmd7{8}wnxdQVJMEIMaGO9Z zXyCU{rcoLCl;WzAY3ltJcl&nn`%EcMyL<-kmp_!&CDRIxw4_Vg9+$NHT+$9Z(kPDc zkW5=cby#xL@w;s*I)G3qq? zipsj+X1>RQ^6#BTe!}gT%y07i37KZ%_N+{MJK=#3l|3udBt#}7N=HDt`nM|Yi zIIFZ;nMUt=rcW8JcA56OlmJ?dSW;BI+k^5YWj=}SQS*z{dRmrQG+1UrqJ0;ORUChp*Rp>ITQuPn1D zx6B5GAHlxoJYXN218lVXW>flYUh}*YYzEJ0B?`X$FebO{C=18 zF62KV(Ie2L~HH0cq5RldqnJO9lv1*FJR(+X`ih3Q&hLT zUPt`Nx6KZU!%sY?@uY;&YlGqFYkeI?S1V#D^~hhciwb!>e@g#muK(_Q^>30e=39R) zs@x~ba`$Z2@5H?;2X`ua@&d{h-A)91JnX*at@mcvdRx!4Y(47REz3Sfm0R_?`XR1! zV#`tNgoLrh7WZNpR=g1}C?f}Jt=BFzp2sS@gDOYNbB6NLLA%sh{yvmDB#+; z{c^a3_l_OLTjTfpd=C(A2Yhhz@shMdc$MLPaSGHyBpJ6ZIYg4900ti7e1$_k1i-io z3`=>1y?_Xx9Ir@|l_;q4R+MRRK0O4?_WL;WF=Gy1-=si_LXIS=9AOV1ulp9T=+*#D zJmKX}hrlg?e}u3#D;{x@ zuEKFEx8)oF&PvM!Bo25oYpHfcu#}F1Eo(;%;FnT6!rsJQN9_u?^Prtq=xEv%BzM|r z@t3F^AzU=UBe;$NnPW`5WQA&3h8mOJikKX?J8EGFvaEvQ63DO6LEt+-7xnT>1_rnR+qA4l2d z$_g+NVH$`^n^&T8qtIf~6w(D=_$A1oTWM019*Grt2O;;ojnK#QDcVBtayPr_S}n}N zN&^VkMaY>dNY&@YlYMq{rFJOnSw;taHyABLsVA05g8fIK^!vr3YFa06B+1%KVZ#9{ zHAz>M5-*9zt&k%%I|ba#CIzKrOFYKzxxe^#;sWpMA)Lw@`$C=I*m7N>Dz)5Z)Ndy zQj=T34DwKj%iIEmrm1$OByHXQAqnDuugx%NohT}`US)HKnrbBJDGK-hCzIsk-( z!BpKKpE4!XjdDpPy$Pt3K~i!g8)_=4IId6^+x&*|9mjZd+m#Yb@W{4HXc4Ah3wbo; z@{y0H=)vyU)r5>_hCt;H;w8koMsBimre8I9oSnh!=@HeDV}^|+AVYNCihDf*U)5X54pj+dqbN+e ziuL3{vROARPwM zKhglrK-U_j<8whZ&PEk4)zHI~lxVKh0jp}+jS+5(#rtM{3nWh024n5^P4-FTR1k%R zLrb?XA8v(w_f{6K1Tf{os9wqNe@VoWAIf2oOoj&%}UF0M{LVl zds+1R%#!n_rCpZ45L!-4T39Zlv(nCIrzb`KH}@062@g% z$KcfeV#GjG*Yw+8spWi)CGZFdrH&EHoJ}QJg7xd4H>00&3 zHJy8NV&cTVW3t}wkzW3*iDyHg1X`!~7Y;NbtXpuuLk^Z+9*{VkZyS3?mcJ0ayhp-d zT27xoEu)_yMxMXDI4sMbFD><``?Q2{zVi*m*n@GOgz+dQp8Z8wabW2N%eG6&wk^=x z5a=p6P(TjOU{hceul>e50`bmJ@uI=5Mv6G~wgmbc0)yBQ)fzxF1_>*S1oSY?1V(4s zV4uN24I;`$Ip}?tfv#>c`udi=MqOS#6cqvm^k&^RsDzoGwB2tRHF!}aHKFxfNq0&#p}#0F?j@!*J6nPe2mK;@M~*nfJ0<5LP7FlgN02(;t&i3#d1ZM87d*i` zJFRzBb``wOtJozp2rme=RjH)i<@>Aw!+htw#LXnqP&L6A;AZkQ48_`7>4_0>ZqWcI| zm1*Q|p(Jq&CyZWr2=5U&j$jR%&czcw`j$ro0yXT}W;PI20yDLmTG5IFR(U|7D=~1T zI>nA^hC;VIn$ejZPlY3U1Z-35wGVs6YlDw^*GT4J9t~jy0JM`TNTbvlNMlDfA8AyU z7K$6Bv2aBSiJp~A-?D+yw;amRw~nXcG{hrV+-H!+D?X26;hxZxoxIW$19_&7aw=Se z9I>C9H7du>LOLEE$chqFQmmzGrAc6XQnUM8osNE<{jGy&Klex&H|MS!)q9WI@Wx+i z_+5D8FD)#j*VkSzf76>}KVtmeg*O8?824?~@7-u{_Gcr2+laJAD-XSuR-~CQTIQ5b zz@|46x5zb~^tR#^b1HieaN7&^--)tw!Ra1|n)2K0G+)LGaP%E1hs+40o4B~b3S z@IVUaDZ30BlmiW;EY-`C{yMYq)TJU5OX35E4@65TEr)(u=@}ALwi{LY`Y7$RZ>^MuLd797$1Ns0TTzHa*l37Qc#kgW2wJ%1 zchKvogdJIpzT;^@Cwfm}V4Fb=13V3!1YRU!;wyEtB9#^v-jbE_vg8Crui_dyxD}1OuE`6o1+pJhtM@4Y_sOdf3a!G zu2UQmb)b14p{dE{K&mj&itJVNW_J0`Zk^GEKbS(MjB!D@O_`Yv%Ejwu6pNM0FQ-8?I6ZwO%TIvW5$#RGqWvgp_f$^&$uk z2+a=zQ+TZwrc?$mXp{!Q*>|ubVt1g#TR`k-x*eECikEi?Yhv;TK0Nb-N1Ng?IU0QA zslHu!e(&kZrtW*n!oN}Z~ zgR3m=kk-yrA?ZaaGvs1DrGc<@a#F}Ml#)iAV*_@+Z~)MrB;EyOPrDA9@&nyIl#j#u zWLHz3d9>RqZj>UIDyUg*l5gk=H5svnRV$hcJJ`k7Hd!f?d(S(ROMq{7lZ>h2JRLmG z-)i)>xYx>o2Q7FuDf%`>IO$t%9%Niv9eO77%^>3$S>d!fF03F#gnpY&j4vY)oS|ZA zb5#zPzVkv+g9xq@vNN6BMu9PrW;f2tyqGNznW_0IKB$ICL03J%K;#5HiQR77g{sOK z!yVF8hjV(pGtiH5i#&B$7(BAYzOM+*Dv-RMQ)mK#ltxxP)p?1k6Np#!e_o8`C$UM< ze;AW+_PGpeo~niCsf41pwyE7c1g~i&Z}(~9?LHXFHwBuS0uG+(D7gSSV zGiFb)Nr~k^IN&!)s%eF>gDEG0J7CP(wOX5;azcgmyvd`zks-3dq0G%pB&)H;k}chw za$+?Ak7z7JS1_ftb4twX*BlnI+(C1WPv^+enzLO+XQ_1*)aJw@I|Q84F9?1Cc1bvYCgY-aqu(n6JPfY<_*%vP!~B06|KGv?8;tZe z{w@BCQX;=dS#3Nup^5a31{||Sv#fw-{>M|=H?#0>1rLG}cVmxTNX_qwJwd+L?d=q2 zNgToMvPaaQcn9nw(ig0_&i}ln2WiQ{U+eD$awQO>K%M z_M|sqlcGS4$AtP;Eb-O%j>nE$w(>eNW+=f@Fc8oMRcMtBoC2dD_{9)%SqeE=TqnCv z*kL*pGqjiq;|anJHYXD6oZVVDXoBON@;MBepE#ar{xI59eii;LQc#>WVd|2C|3aOj|A`wA{`oHB{5gU~mHTZsIL%{er7Dcjk?Ya_&}`TiC)wJzQhZ`}Vg zv5@A^01k~xKA)!P{8Z&WkcBw|Xi7G4ZeMg3Sp zAm;cTx7?z2T_SL=3ybrbX_15lPpp%*CGjAycQt1cNOBNQ;-!`%VEqN~Qnm!{T-at@ zy3hoHx~NLb+jFDSs2k5kEpVj;3=26XM^c*OyL7R~CRxV=JBZhqlMsR+mR&#j8-Wdh6>vr`$k71#h{yEuH>(3mgFonFp>O5?AawO{ zsG6TPsoHI(W$VJ+&-(t10Bl;tCbu1j#(tCTsh`COvZC9CZNe=* z(F^6`CAujKFIoaby^@7DtE%k7avD&F?~ox02oSo>ZOZEOAYs%@UA|`z)OXKOp~HWf z>uXy2EBr(pq%577l?FDe1DnXXOgpO5#P1oni{0!>fA#r&KzQ6xW zPJ0?v_PdSND2;L`Xh%a}7eXeOP9EiEYuts>Sw0(rKZ z)%3*3>8#C(4c{ljyg*P^#zhqH9M1#u9b5C(ZbQY&1xbi8Ue}j}&hc8~j?0~P)9H)2 zt~Fi`5KUhZaL#vq>TX&7eAjf6U$t1mAl3Ev=g?yLEG>KngzxvAZ6btnt+)7`IU~N8zfA}PFeJBTSeV+=nuL^Wv7>`B2zJq*TiWNPvj!!|S zLje*#D+N&sIyhIKv(g@@zcJ9%!Vw8%>jqvZvMe(~WxB$rMJgZGLQzr_j1si(&sa4bEoeF(ttIbXT#kmb); zPl=Y0gwaLoZOe0L>C$Z%E_YYKALSUTF0ppe|1eSF@m!S4S0_LI!@&>iTafD?C5-3M z{vEP$!bs$UanBoo$H_MUkCI1-8y?U3w*PvR-Sh^)xbFgCkd8D-7=Hn|_}g=I#3`GP zxXGplaPEX~Ch5FuaeZ3@ywzs1A@5XK9gd@Q^I`b1JvjD%TKzUsR>u4^o4; zmG8a)#)d^abn}Zi7UA#b1I|32za#vQndKX34~vHh#68%%Vg!65J<1d*_N0SaX zR=eLP;k=dLEHvRb>G@&~J)X)$e5s-E$#`@i znP}??hbgfxIygAe6HSi9DJ2}vt!GJ%s;4D39E(#{RpGYW+|^6grjny6AhxY>04S}} zI4#>2>!EsXanySY)!VVE$5XkbrzaBI(Gwd@MnL#rOoP{iT`33~0cEl15K)#(Sa|97 z_&_p7KnL7l)JPb8GXiO<4$n+rYi!572wYzqal>X#6b&ZAuB6Ph@GZJ#OM#ZO2uW{}w!`4HFh_csDIE6|H(nq@{grV?%o+vL;f! zWJ#wfrOtSC8(MoTZY$Hdttv8%a=NWmpO1>qvys``$9xM{88o}#KPSDmVQ}6+Oibp_ zL9?_A3Uic$3B|xca-nZvFxH*w%VX?JRfzOZ*AVG}RgX|J9vDU|)=fW0NV7n`5VV#K z40WeqLC^z4mQf!w7&ENGJTY08h$X>+aEH4=pA(<1O2lGYNBa80JAhH`z(^v3ZXm{~ zy#w*EVIk*<9D^7gNuWcG)b!y;TisB1A_>k%lHm)0Ta(y1++#EoLot?G-8(wL{Hjrx z=pWfW6dm4qVPKZ+NNkBEhcAfxb*bUrSiEm=WcvkCv^13;#GJICZnQhvv$ZceFzDW) z&XKcV3A`MzB#(v@sF>~lhWYDAQ=UdX$J*!G%;yMhmWDn@DCg7E z=L33vjeU-g-+<=+#%^O>dP4IqT~TN8DD`5>yr5k&F%VfQknt%5$?ig{3gZSor*xoGX=+)WU;@rwqS8p3g3?$d@9O@n!gbQrB_sW%*Pdt^{ z7k;B5D;~`eZY^WH0^@{abU3+Tm9nRC?$>*qRO30WeRCodHFA`*DC%>eHy2=j_NSC6tXN55SyOVso0RF*sZ=0?oa) zfM{+MdX5g7ZjP4Mg-$=xA5HX&$Z#8+uj;F0%C_iW3PbIkqcKj-34Oacg*iSU!kB=$ z1hu4wN8%W&#(E<|(NV557H?aBRRrN%8sHNWbQ=!0cUQyDqf*t*Qg92SgSt>H-$#-o z_JT_zZ2$@wHGKoaz2X@Wwp0>^7&gb-+c>a^N|*t|BfT*y*RhS<%yp|e9nNfZbsHS3 zc#3;jyBEsQN84kYt;%^^T}Q6>kcTv9Y9nE&4*uMl7=~m$BcnUf0-}QhTZUtd$_!Ma1rR!J_;xb7o7x8$-!%qx8card;V~xBG_Is3 z#Vpd3Tc{jq`Bagg+Ep<}>K*RY8;T$*hD4*IqmU!%f*f-7B$Bmm4F7euX-i{&ON`9PUN()cg(Ch>6Uef7jQS5(6ZLD|yP`$TNV*kEms90)@fViK zHjbXem^d){FW6%f?)i3L$`+y?D7$HFmdt3-=xH8a}Df z8W-RyLJ&2Bu>{N*bt-Gt*KpqkyCmH>k;+~n6U-gF?vhbT`EwRO2o!N+!0FIg4E_b8 zO^u%%(1`R}3IBDBqPxh%GnjWqA3Yt5v~7Jem9x2{?%2b#(;j=rDr+dcw6l}^6XA(h z*G1U>{=e+K4SW>U)jxh`cM}#^vI|BGn(9)wHPnc^Awah9)CH1|XaWJkODi=55+oQ% zOm+c%s0}Vr#&O%U)z(^TX&)bJ?Hhe+seQ8vB0;JW)QYvXrL`(?eTgqcP%;1Sxifcm zW-=QRz}Ei$oeyMY?|kpM=bn4+x%Zy?GAb0^zvkK&wCz)CAgNRVOhuA0<;EHHi-GKE`DVt=WKUJ4bW&OIQmTL^u($TV68Kw@9f`-V{HX7`v z+LI@l4lkbtA)UWPSV35OW&NDS+SXR`HHmy`ZO5=FPeJ31N%*K~krlN<18EPN?J3h% zVU1$69;?*ER90zA(>nglC%tC1wA5Z>lM>RV$*F181E38jp^qOB8^bHY(A3&htI%hf zv!=FTeMM6(cNC^AJo5`UWYDJz)==g}s%C`Q%Vl|Ia&ej8g@S7u>gu8MD^WWPi#;#1 zzzP7Xt6x75XvJZfQfWhdW8J*kbzFt?4$#0(x2-D_j-TeHrpB6-`qpBAZx)?JB11zJfL6*(4U*`Pfm1+H?K~}NxVC<< zvL$3?E!@|e<}_iI?I4M#kPDkO4vL%(npg*2-@2p0t;f;q8uF|=h3 z8|sIWKmip(IZCQwRYPSJ*+a7$Sj?`c>7o zpdLYtgRw9;*uq9pL+c`}M64aOwigP}e5`a|Wm*M3kesSygX9KDs_HceW_m*_7xy5L zPyx7tD%YJ52=*6a{mKxa1)#~vY2BS`%CSaoQ+=J04Re7POo4?PZj@Lv)?n8UR6xU` zw}EoSgc4>jjGS07p=k}RrHxIf1?#UYZd!+CWias6hE`hGj#c6(#G=6FH`l`HJP5sT zL#x(P90Y_?EnkPu${-NXSrl8@Or4qZh6kW(EFX`x3`Qx$i#^s#z19;o1`vi`wMb6} zNjo$h9i%9P+nQ<=F!T%st5d&It+KU9GNZ3TVa$?4xJ8KC1S!Qst?4UxX`8?{7l^IA5H3-dnYHT(}diWSZsyB%Of+W@8Jc zRB2MHyh?pfehlMGR&DK2=CWE_sP?C33>u*HVXPK##Ol!RN zyeHax7*+vlGh*{FFe$H6-G)HpUrGcPl`axxSpJ!L)F(};K&n1i>qp7rMi9r$7o1fq zP1BvCsMXQS0NU2-bJB$DYS+mUOIP_$mfpa+dD4^yR^5{(rAy3Evrm@T;1xeD)d7`{ zJd%ddGuRs6U$m|sUgNqs+Dg-swT3Q7+N9OtX2@UzhL&W( zFnkHB#jLKVy{0J^t-`tpbYe&zH0(EeY*wDcc>jaqLkzujy@XhXuq0jh15w^^t#lE$x~eS z@nID8saKZ|W3Em|#TZJv0|gtbcEF5dks1)EbJ3@Q7KTw_{)z3*AT|f3 zXSV__G;O#Y$4~+GCu6Xv`P~Oj$)qC~nqIyh-PeYcQyG&*#<6S4*^I{8*wss|6Cn$@ z(r}1IniV|gztuFYu0gli?C8i&7pPX8cxt~HmHMewZ0gdhO|qhwFtKDiK(Wj%bf;UQ#ka7Wxm?3l%IUN zQlKrqK27b)zgDQHp$YldX5e(R7HdzCg|$Y-2KIydioJ9p8b$Nrj4~%aPF)ybH zSF3^8n}O9LILpSkQYSQJesikbYAsp27Va(X{YW`dPsaK2&tOV;Ld-czcT`WP5RGTp4!WbA2}n`pCvz97B}J zG{bU`AxLFtRHp=0jpVa#+LT#oY(3uyH3u^(hE3+7soG{)T}6k#(CZYF8=e-y?amhy z@eSUmUfBlJwc$BqhrK55L&g0tC9j#3a=uWkz7Crque}ya0|%O2L+3jrcC}KqH*J|4 znkt8iFngsgSe(^zWo#W*O_D!J|dr@sx-rw(bsug)e^~ey zMXXQX4XE&#`D}sXT{9Ep2Pmo*>zR0SHNAQc0qW~C$oyt3piIf*bW;`_4^2PN*a-dL z){a|*^>tiFhEcr3OjN50v!YGw8deQ%ga+1*wL?`e(&woySfPxKwkJ5G=L6g>W8URMo3;7260z)nZ{?w`6huB?zX?1KX?Dnjrf6_A zf5Y1{HM|l-Lqv<%f_tQJsd!+7xXacWmXA zElsiJ50TLRX`BsDVxdB;;6xSWOQ^5{$h@I`Xi}e2Fo$<|4ce-%wKRxdSQ)N=g>%h? zlSX?@I}*6|rYwzaUcus!rnXn9Be1mdYiPEx1p?MUn?azh=_hm@>5)>-Bfhmz9*!k-qtab8)tz`5f}8OFU9a`}n-LXg=vE8Y~GO zT>XYK@2;Ovvf$(!&Dp25(WGKKxnrjenC;F<`x8oZyHHaGM(O>Tx};b<~MNbng%0={R@K|v7yf#&!=wFDXmuxpH>6*ZzKLww^9E# zSsmOAr9TRrPIAF9f>=z2NUnKXSx-jQ}0@_O*LABPa0sWXnB?8$UJoQ zp{HSe8oOk^Y4O%@359~3(rUi-Y3QWLr)e~-C(o2EB@9k^rhymUt4?F$ z@h*)?6vV1R;y_Z`glwj)ty4)ud+<)>snZ{%TYvb!a+glzbA#S z63}SZy!~#NG^Va@#37irOcX%x@imDW`aW0fDlB-cX~k;mdK{xwZvTBN)vd1OTd-bT zL#Hd2py!I+W`#9&YYIYei#OxAeVpQ1gY||;GhG5G{7_hIOXdyD!(*3KG5w%BkTAcge(K5&O^#pFIk(n~n~!w08%>)F}nJfInPJP7Z}&o6^c}XqCaRJMx5w8=Y!WAM6grfrT?f34Ev) z2c4>nwP|s~w3T7PN>t?2G|9>hMe)+f*xf$4rsm2`n`&@GcWVa2_>NOfbe9Dw%Y7yvLug1%z{TPe85f{Pl zChZ;FeA@FhxEpah@LSL(h`@cT&1$PLzI}I5T^q#ih+RkI_fK9se&1wo3Bvwqc$1Swr zBIh%9gJ2GKk#3g-*8^NKF9j61xsVs7E9Cd<3dV|3Fec=;U&9IhSS4fU+vMYQ3obYh z#1JMfk?zMp*qGno0>;V(2zP! zQ*Cff7F-o@5TSmFeEiUY+Ya0^9hJ)On-&~f#Msj|xF8C`D8EC%O|-#PT5!H<#wOX| zZnEGaz&UNo_n-w=wHUf%gF9!0nZFfF7<=9(-KYguwUn{A4ek*O?htT)w@KIIHmBS3 zX_NZtdbP-cI|STaHtBxdg6sGUV_z1P1$a@uf41O)pJgm;LvP|pGk?v%eaZ&6+Jf5w z+?_VKA6jr#S1`8LhQHS>xXu-fU2H=yILgdlA8^xca7`9muvU#Hph7MWSa1>GpyK)^ za4s}7RGd&RepLZ?j`mD9fvd6Ln$zHZVZn6(XD~xLy>~6R?Z62hjOotynEBh01}9r^ zooR6UEw~=wN^SCc#Dep$Wb92FT4fF)=HVbY?8eFFZcL+E` z@#^K4i9R8P3sLl?!F|SpW7kNwcH{dNoG%UT9ShE%2Dji$Gk?J}xO*(PNE+N*7F<;t zT*-KIx+~J)zG}fW12@xPP(``*TW~v2*`6~Lh`>!of7w_b+pm*YiH#mqT5x^9RodVh zEx5?%CAQZFcc%sCYm?YZHn>+TIJQNy?O#ouV9rMnxH=npD=oO~z!loyuD9S00XNx3 ze!sNfd~u2O*x**4ZRYRLR*8K^RA!_v%Ht&qE^?#9R@>0q1e;?lw;dP=HQM0zXgHV; ze)(^b*ge`a-Oyd)|DUkX>jCb+ZS<<{Bj$9gz96w)13i(C&z@_>MZPGpcANYz!#K>C zkDf2t=l6#eT;wbEdT_*oYX;6vugd-AbXVL0dN%UA(}L@`Rbta@aBo;}Jzup?ckV=U zx}9H>SiTLtehaSeHi<2p}e8Mi$RZkGku2izxZ%B}QcW_rPI z+Ur398Wmz&*n9t-5<`*bm(UkK`V2-~=eHzwo?nOQ_2VWDCs;c4TZtVu&=c+85evPZ zE{VM+B7v+(cS)Wl-QB1k26_VbXA7=*kHoIF!4*w1)9dS&*soIA(9^xug4?lIVt*Hj z8TdQ<6DmEy`YnHuSet>K$nUo`oG#~QBzC(^yZ;XhuJbPv8!3nw(mm@!b3S^|co_Q| zg4HP&Twfa8d<)KpK_i+d{Sx$I7F-ZGbiMUU;O?~GBEUVPqf+JT%{S-6|GdQQoq!5@ z(=E7Q8r%vCE&?2ebowRe$rfBy8hSe{xD{z|Pg!uyX>jjbaBXRD7hGhPO9yc1^6Qt# z#{vs(J8&Kym6G#+TW~wl(EDEtt`j(P`SnYr`-BD81DtqAVDT(XHs|9IaG%ntrErB7 zoc{%hjkdwnTW~?(sErhtNcW2tTqF(dehaQD4esw2+=?`~aTlBO+nfe>i3QgN+&qy9 z+(kZCS#UkTg=}zNu;6?zN(@cBehGU2XTb%5v(uNSEVxJ-+%XHT3OGAI$VY=_xpbt# zRa$U8z}e|Rn+10$4Szqi;QD|w3|DnIzhJ@n&}fN1841y+Npci~Z)^vHz=?N8+;j^r z0vx(#`X%D5vfx$#hc2sr3EYhqTpMtxg8C(JKd|6-09UM|Qu)|#!LeTSBW!SQS#S~H z3T$u_5NMQ38*o!>aK#o}CvbN9*KEP{05{i$-VZG}|4a7$&Vv?Q6>xU+GQhMkAKTN= zn`XiFq`}o%a4c!hU&4Y5rosKnf?JUW_l5=60UUz#OX$lv7+e|i+mi-YY{B_nmRPq= zEu~kVv)~Q^r#nA@7wNW5HK%*1PhwxPq4%r>*Y>*oxbb7t%=G$z`?d|e77K3s8}{^e zS#Z8LB^I@z=Yg>^%C930Zm9+5drM+1HuUbY;5yRa-m&0(|41{QDKhiNj!5iEVpzLG zd3@7?YknL3dmG%?u$f-RQHlMR4erwxT+cCyVJNC!BHgVP+=_SMhcg&9fg1(mMA1b* z`~Ex!+oV%Vso0k_oako;Dj!ky3<2LzS zeuTW-VOUJW-+lWlOCL$9+GMCC#M zpR&-405{fVJafSubGj>LIM~NUA!@X6V@(!Z$A3B4M0%lJLJ#h@;5vb;6Cm6L?s*F? z_$i02A1MQkBZ)!iOEYly+0d)8;DVPp*q?0VcORT{MtZ(k_T?KZHRIT9`|>S9BW0ww zeU5#)Unn!<+Dh!xonLOoHJ93_I}T0?W4gXFhpnF`YQeE`2is@pu!-^*ahXa_6#XOB z4iy{~CFk&oR!b+Cv5 zC+NLyq38RVgLw@&L2va!OS(H9?6)HZmPdGzIUk39<6u343BX0VS=DBGJ31ZgwG=sB zF0B^ab}SJ2m4Tk%&$-x4Z^dp0+hLQB$rhY%kHglV_!kQ<((Pd5ohb%Ix*uC&Nq3)v z`EB&7Q^N_?+a7nA)&U5)e0HgsUh|U<_UPDw>Hb5*33`zi9Hw~8K4Zp3-mtfScU*491>dx{e+|pcxSqEh?AIx= z==?om!FBw@!MFT zwC(5IZNWtxPTT&5V}+UCA*a)}U07|w^|+k2^A(vZ&Gf3=_WWh7GUFm6owoB8Idx`S z&uDx8uC?GgJx*JD@Fxpy#~3H0HE7}zdRkU*N!RPN?f-SJw&2Fv=lB1vG~+tQ*_X$+ z)|hcCvYl*&P5bto1=l&j$ue#7k>6mZ*K>}Oy=tRZ8!fobkJ!`evfz5ov!|D})|_tV zMEi2P+=AQjQG494EV%9G+v6r&Wlpyv;AD5(A^ZGc>Duez#e0+b!t|)BnE~+z)^&G^8tVf3e^WrNND9GM7j8bf>O!L{`u% z&~QR70pJYHIWJqn&$r;FTIdP+U1dqP3^=2lMY=azaMfvWKeD8|0yvQt@g<(0vCyjn z?r8#Omq_$@zy7e(G_DnL`GE!ZByhPl^sZ?& z)9V9nrVZ|6Q57fTm;XtpUIqjg>CV+~L5)TbxRIjp5k`;nze>YtFczL6D61hN$_fo9 zXFzFfoAX}?!!_eSl$M!Pp_IIc?Ft^frmqTuoM z!|(O?_ag&qAcnI$^h+s1*7&>je)(vu4~P}uX9YzBl4K-eR^zwN244X@=i7phq`?;f z&*fpk2g7@!SqK}a6aKUj{>)kVu6Y*HH}|FKab$4L)KM@S--|8xj>rdm$%mtCyC zUpkLA5L9IR#Kjg|#@HRwNIc!;IQxDVd%*ELRT^N%vYYXAvvb@XE_SC=bD$#JLz^Q4 zp7|_@N~qSieEBhBjnk`Io?IQsj&FuK$IeNVMo>iAiRyrV!GfxVT=? z%|TW3HSD^z_rT?HS66RNsH>rieoU>tdu|hjj1eL9!yD?7qXCz)A-DaAoE?a^Ca&vm ze>-|c_;vZwma(D7<-Knok$Y|qMMM@N}ugjfroj*EJWm!2Z{<2%{UCY+8!#&6Q`;kn% z+XX=Ed2p7~{)%@iR*5l^q|#g*>TEya-HK($tl^=d>p@~kfBPHWtvkR6N`Jri`g^HD zKcVTsLHU{9uOmRY=4gArck4njbMrm%zrMfa*bxMK+ao;0r;Jo0g-XPwM0|>Cn-a-` z^l~ARTrLuyE|M*u_o(sQ6mPDNqCl^e@_BWvNeWdV0KaWP; zNzcTd@X=T%DR=BQq0Z35DE?cz0zS;0#*s+nj~=kyIcZ#yO9?=BfdMIw;S@)z4ubtJ)OLpDi9Z<{y;^iU%@%*qqyt# zl3UAVTRKrAsY{ZLic<^$qu-(0Jb72wOF5xksx?#%AVS875V^bSHE*a}S?_9pC3d9IfWfCl+^)Ww8AJ*Wg2YOCzVoH z_-OQeP?;1y+;Rbw=^rq50Ec^GA2Gr^!t>m*-}PPuMV$C_xF_02$)F$MK|Yktu;lM@ zX~=t!XobS$Qa2tva;dAEPf9>a#mXE{r2UmQz1Mw>WV714zH_xVx$6z@a{T{H=bK*N zWxnV~5&S0vKZD?Byh|U)n0c66ZmLhT^ zCzW-sL`i@9;b>O)wHA*mQ2AieF|k`2t+;-HTAGQ5H!C?cF~_Yea?9i8R`i2@p=9FC z`7j4yroA`ngCw(5NhUKx4=1xG?(I6{a608+{~XUxBqSb@gWJknnpW*{p${S#s;#uK zwI(U0F0H*awziZF$RzRr_21)1rRdm1S$}(1s&9tUXmW*L-7uCKOhLN$D?oeW35o*= zX7L<*Z|Nj$OuAw3skhAD@cQC(N3qQJtoAP1ivro}UD}BPfsC)1>*Ip96>%HXfkn@W zA9b{xTju@E-Yu^m0-<=<#QUk#o;Z|*%+%b5_jqUbgh!9!(2ku283` z_Mv}J$+}%zC|)GIC-%Bh>2816yOoA}iO;%~1unJsF**E3OTOGgjY2Y@l(6m+iec)o zcbD)nK<`5cpZE?ia&Ct*q5Y5Etv^KwMC#@#x4#XG3#-uAk_F@8(wZ4O!7@yc|B(E= zg+FwRdZI59RDMl~vG~jznEXt1hK`b-QpUAEj-KmP?ip*{upeXPjd!_aH{z+k6sjj|!NMx8Y$$O0nYwKBMW~y&o0P;@f3MiG#|cWvW+c^P zR@S;u`FJWAe?$Xr?^ZWTmsfIXDm)FH!{`}lEkiFgySzX25BVUahh}&G#J?yG-s$je zy_?uT@725Y4m=qJOfAFS*aRf+375KKlan)zZ_)lz!*iI3YfVN34GDEXp5`48v@Wq< zi~J;KBR{B4E>O$HSRj`g&8me9G|BSeGqAj)2~+Ap*$Aoohz7)B?`=V2o5y-{I0FSu5TV-&S zE=qKi;tF)Tr~}KOHS(X8^DrtotNm4~d*cx+TNiHtgI?H@WX{Asx+{eNq%@jpmF&4* zenUA=p3u#wdiyW+$e$y%amyvHJtb~QJ{;f8YY18z;xDEozk+WU(TV*{Ei^~q0a zzv}Z^8?LRdiTc-1@?Wt20zVz;Q(xEWUst=SVO?yUzctp}+|&}Suk#a*Es9#s#6f`R z930cRKV-J)5_ju!>YSUioYN+$)O)V%01`7-P z_}(ViZCdYdnNm1yN>O;#B>$>Ld|A^^CjsHGB7f23;N-iEWs*$A$rvnq;tjJa85Wt9zrut zpb`8RX>qrZo(|U+zbH>NF=w-6W|lKRX<}I(zh={4(3q3uBMvF)@~qt1TDsX_V-{xv zulRWzYqWS=!S%FLe1F!!>oSnOO~cocd~`hLRo6YWY#c|kiYv{^w@B#4<amt=@|CM_CK;@FbF_vZ!j($Q zdXSPSQT?Q}sT&$_UOspr-gGYTQAKlVQ*b<=cFGY>*D6Y-qBD%-jGw=-5HxcIC?&d^}TzNS9-+*rT<%IF&P zm^t$&P^^uy^@GnJSV;_ih$|h)A6?VZv=N83THAEn(=!LQ{l!7sBQ8(3M$u8R^)2Ww z)Wp^|;H*ql_tvKSxYB9XXB0pG2o>~|j-Xys+qwpy2VdVBO`VfThJZc+#ow*RajL|j zs;qkLgJI#PTWXb2J(|(dOA|F!dui&inctntnU3b3p!KLs90@rHS1CJZ+Z7x@Y?yfC zDVPJ*O`NCr&pHHcG+GgALb#g@citxRmPP$T?Jiw3?{36J@SFN=;__(^jkps|Yo1sg zFqrbuFG24*gc#}V0M2eL`aumR=HmCF1257dqST+K|9{7SBfUciq<)dOL>yYLW5oF( z0N(G>fC4uWag8`1JdJgN814c$&w^_M&L~5HTW`U20%x~3;8_c9MHXYTZPN8XUPk_Q z0LS|!mV97oiV1fJINl$z;O?{Fs=zq!TUc<5QGk?gffl|ViczdR(~aKI|2hqa?C|UV zfFm6e7h&kyV!=HKkdPU@7r1X)a8CedwCwNdZhog;u5smymJxieGlI?yY> z5q>>Zk(f`hoyvT7>=W|qaLmpcAEhh&zPJ5HV3GVYGh*)OMct*m6x1n@?owV2Fx3_~B1y52 zDzn^}C4rw^dc!+5GZ|IA&H0Npr&w;X0bbqsJAJLIu_7h@&gj-Lau4g-mRZ{Vcr28h zm00VGKi>yW*}L! z*;%oCDxTMq1tx0nMZUtzXYrCj$_KOI;p5)+o!}7V<)6`%9lf|)b%kqA^6nB-0ezeb zs6-S{2}@p!0@n&@sa{BpS|K%Pg_Ok$sf3lFlnRow6W99UFH$Kj<)!o#j|Xp^R!SxA z_K*jx#Wjrymt-88Wp*EX(jIzYgpMzI$t6J8pF0@h;rpY4112rsYo> zg>0gdnjOK^IRXNhY|cZ@jhN^iCdZH zN{-f|zztL*i$|2gOew=jXmaC&~ylfvbdW2+;)jpn87X zRVBwP1*zf@Oub52P_r!Rg^Gi7>{}I(mj_{nw;R#{7N+ z+u>O7;t1C1T=4t|*5g|6+z56kW5HiXu!l3pJ~4tllZn0JboGDZOlfq}W#4d0zm%}; zTJJAf*NfqIE_WWjEV|1srih*Ii$Fh_mo3=LMp`b zHyxfHhx9$ia!h18-RR^boalMp?##H?DSgX{{*36uAdRu?J^Xr4^6qpp#qm4A;{++I zBJWx$iq7}-Qig0;Xxjgci=>a0yMH1{t3UQLNm8V_j6E*7|B91$q>&8A%VoSNNrxpv zDwvxdI9Hsqj9Fw=ON&z0tJHO*G$2JsE2a6eSTq?Y(a}tDsVh;c&xgnN6xq%l+RTNM zPGYI*TZx%&b)quS;*ks8iKx3MzRNFHyNlG|_%1hoxQ-ONISX@bSeWaIce`b6nP4h? zAJp+dViWmAy)d>cP&r?`Q=fW|?{*8Mh94-OM5zu>B_Za}?dYqyD|YMA45?V<4|Y^I z1Yn3UFd>z_53KwWrA4BI)27YkNlTT@Ya8_PEEMH=tw)}THG6}X=LuD6&~nwpkzO8r zt;3O0KiA$ok++m;XU6xW7Fnd0L|DrQlfQ;IgV7sQO$574Q%n6f^wDJuqy7*~WFEqE zlubEGbAI^!)(m-5zWlztH-0F`yOpMtfe6HpNwG72MO~Zt(VSn>-MjS-(8ZdfBT>G( z_(;Sr#l|Hf{z%drdIjqgAC6^XQO_b;>i3UH56OqSj-H3L8!yL?IieS+l#WR%rFQCg z5g$jo+_ACpG0a8hTzF|VOna}qD>)W#a^!tVx#z-5v97Y~o%5WS89xK7I60L~4dF-S z-%se_q&C;edq*CQejF6?j_h({+88;DZ}PC{r;hCMMYDK}_I{4V^z(9{9;8(iIj}mj z-O^rpwnuL99eL1)fz#}4`kf>HPJSslibv$pKry?UOH^LwlB?WWW5h%3%9C0lES8`Z zGWly6{s!rP)sp@NzWDB3xi3!YfYywzP^YnU2L84gUtqmt9=q;3j9&uChd*>A)qBI* zkJ%pOQeSv)>$FK-=sM?3dON)TI)}W!y+3*;`cg}))DAKt2GN5CS~@Nrg$$C~nnJ~a zCU0SXRUY2PkM>6=Y(s|~XYQf2ke2lRjA$Tl^X*AT=m_OQU0uR6qWvM|ax1fPlm+?W zT~Mr9`SPy&NqLUU3c91?m8*T>rx3irhw1rpPx$p#Ck91Vq-01dW{m~q7{>i}i~mwI88QTE=7}e-dkZ|8*N}3qYBjqg-?kr)-C@4?W!u|z?S|MbWl#=v;*lv})%3rRr34(qU_D4Sfnn7i$N12;*;ZnCU zpL$;I@ZRVITJM;co3AwGCzb|#Um+bl(p!iUet;L#+#ovTAHz?=DRZf7m#v^}q_IMi zAB?SKVvOaJF>>_otYjD%#74{e4!m^#D3D8zQs(-VrGfaN_sismCjEW`mOHx;3-a=* zQRSDAvE)Z7nim;!?J1_C>^rwPl3B|9ygjf$@?6qwzKD1d6pHw540t9z>fJdCv5>AO zHbQ=?^gwSiQ<)!7Hs&EO((CfZY#AB-2bR>3*TF5liYK?ckrsS=oM2XN%BS#B1m}cb zO*95_yt5B0>zJH(#Nm#fdt@#QT4rJ{44PA!n+Fbj(k^+fTVCpsn`l9>JG>9ZpfEZP zG`BgtJNu{-Z<7b?`wOzx_2D36Wx}&<`)^p1 zW$kL%)t@-gJwK52FmSNe|@SNe9Bms3^U0>Ov$upOp7adWo0oq}Rd+z1P!( z$&uo~8MK%<7|TdBOQ_4u?)wcTe-5pa4tIHH@4cTF`!Oo^E?@kweQK(rOtJq731MX> z>5iL>icks)kCO_BzAOb$g7O}D6IYh_UPn?q+?yj91RcCyI(HGi!H~# zckjKUHjb4Z=AvqUSl;K|dKIt`MsC7&E98vjx)C9)MD~V6VMljy2k+N(yE^DS@{@xg zH$8)mV)E{0o4vb`TqOB9(9Bcah2Ho?l^^o!dR4zJgax1B^kg~t)c_5s9$qkz~&@eTN3j; z;p5Ruv`&?>_&s^advHaUyaiu$>05~nZ*`ZvNBQY4IjY{?qFZ9!TjAGY2Pik3rd%Lj z>XK)>LF(hi{#hdS){&C8XwXpdo)BI5ZTTOu7tlk~hnix+H{5!;L_O5mdk5{VNSO|y zcqnzb8!dhg=&=i`gY6a0yui@GoRi7$M`VX1nI_@D?CF;gZB~vMTE513) zhwVeJAu**Qs|>yWQG#hDGv4_Yp(PARE3$G>BzX!;%*<38Gf@PY73kl^E~9npaK=Uq z`BTS7ylQA$0cb>!k+%|_Ot9;V@69k) zS47fBxSA6S(us|t9zq50A*g)-pWK~1JGJCK>5#jPQAN2a*iTC9Y>^(uB*qQ`ahm+5 zyhqh!O(LWQCOd%q^2^2^=w+9OZc#C9Wtv1at~yW+(p9il6-c~n(jMhf?DLrPx_92b zN!{4!iv3*IeFRJGX&F4vcs@1>2O;F_@KJC3t4Iy2?!Q2jJU79iE;JYS9AX4_Ki%WU zMz{Lpy=*T^EC&TWL4G@VVd83E{DnSQ%L_#(vJes?#UGQXw}#|tcisdlAMegxoB^$c zCM+36Sl1jWN*zBxmhLN&AYr-H&JW1@`)T*rH7bT$ZoiNho~uBjV$$CB&g;&C%`Z{2 zNEQQGtO_FD830vxM?91RJVxX^%-+DysrHm8M19f=J})+%LbZB~&XXNlW#)GP>dYj6 zqZaEP8%BkEOjUXj+$GtT+Udsvb?)?uZ+62jRN>}hv2r-NGW^lmJb|s9v9LfX#qJz} zlkMm~K(+8(@hXvx#>@>>m$<;QReKxXosFRp(3}+ilT3=AChoNUir>OuP*=fRVKu<# zRjPgPku{+KG?|jvrJ5NTBa3EHGb26;m7_S*!nvh}s%&d9Q3O80rCw0Ev5{0m{p8V8 zMcQ#~|ztks4sQKP`f{LitKl9!f4CRz!4BpFvN4k7541?U>cIv)%&sN(` zK5yMUo41<1I0u#~W$@MHhxcRPT$V5ISJq_PLFHqUdgI6XyzvJSC4OuauPQe_0>Zq$ zIpm%QrunvhmB013oP%l`A4Sy3kKY`a~TS4(*x%_Bp$xu+EOH-M- z=;rtSaH#0Dg#J7w{k!;chY}SZVTtS<&8_0~6;EYeU&T}(cFzU9V=IEb_#S`w&DaYw zu)D(B{uG+!gjEQZG?c(DWy!E8hQD(r4Rc4@7y_1X)5=)W<1 zs5oPsf5r2Fm2-pcx=5|P;T26|*!awY{eyqk*qmr%nk>&f*s z-|E_T$L+M?_%g zeI=bz(`4VAti5=A1pj-aG6Xs1QJCTPP4s)WG#j{LgqLWzE7agwmgp(4k?7}B!TTSdW-Kt!q-%haDjTIw$$?gGG7cjH*0Zb5@8!&7V&*bFsH>?fns58VK7nlC4x)h=Shu@R`i_5 z!{CqrXGNHnBT&5`_kKUdr&kxYv!!1NLf~J4gD;fomDg|Yi3DSf*KBnr% zRR-CU9_4Bsr*nudE(#0UgcWOHS}}0kGMlhQOIQT-+O)9acuwg&FFUJz4-JqWqL6%c zYc%ZSLpmqqQ-^0)8UE;X%VJOPiu%RbSO`NG*`X9RC8xpm3sz}y*Fk4eaqaTstdMLn zM0Oym<>w6aEnLe6(6Q|0bN+e&oro%zXEk2zG4oc=VS%Neo$UT?=YBL)ILBX6o+OEaFs&dmNK*SbDb9q*wgAqoWb`v7A|Vu zFgw=JSf{Qz4^4}%tSi;Fd-H)`$->JFdwL3t1H1B7^RT%Q+n?9ew$wyhY8#@h<*Q1t zH8Nz}B#4j_Y~+d7Z;DQ?`3&E^7_y{V5L~B@EI-hcFXNj!ElGz8udI*GYHX~mZ*8r; zvc8q}x24~yncBG*Rt3?d4sr3fzIGkS!%iGlX%vSHyXdMn1Z&n~1D!$0r;WCO=9Cn_ zX*n%1F*fYT#=U_yxf(tPCr!l2i6I-OBv&I%8^%r>Z3Dkkjg@U>Z1s@!tH7XNr-Pm` z@3!=yQfc`snc9Gt_1uosOrxVN8tV=AAXTMO*&USJwAT745-X`%)sV6(c2wYcO3M@~ zs$m~9nW*Wl_4QXZtzKQS3Ga#;np&|-wzZyz)-|-0tUc{%H8-`wRMr%(#zT2{-OAQz zZ4?K7l$P(Co26xDTG_sG;Lg0yZ)L}BQtGND-7%U(_Kp8*m`WlU)|WW z@su(-H8vCy!&9Je^UB&)SFNsXXe>E_Vh$>Q2(CFsg1hYW>UU8Sj#=Tk*144bnNzF4gL1}6e<1bsH0kqc(mfj;`HaEd59s_2 zrLz-mj$!{iRgIEWDc!nEH`uhr-q_AztNprlP3y}mR)$JS(ww$ncUnOjD5_B^Rja># zkb@bFEDg2YomSi2T))1qWUVR5X*D(L>#hn-Q)fZSVe&&KB}gesKTx0h5&$wJDtr2|-9Qym1ai>B99U51?5Hn5OgGtR2ONl-OSu_)3^mjKZZH>url zH2SHN8bm77)KnG~)!-koqc`y-NIWGhT`#Td+V<^B&>2}DZMi0$<+Ehjp2pPGji@5V z_AFImp;V`6c&*VC$bv{}r%&J)Ka8TTHd;HmrM?m27>rdLk6$>I9;`U1Aw_wP!ET%q z6FX1saarE_6Kt|D>NHYL|#oY@yc&zg2?(;V$Ui zX2Gq1Ux?4EXjp+0`}XvF02i>KN9TDEI|Ap!;$-qCic8S5p0yDH?h^upyTIXdcP4tx z!14JL4J&X*Ew~-P@p%&qt^#s3@)v|3>w24X@3G)If#dTd7J5f5I68xb&x=@aWhfY9 zy3N4RZ*hrye9eMu15TTA;8214lLglS9G^GQ2nt*|A{)~^gl&=J{}Y$M-Dko1u?-Sg z(=UNLV!;K|;Qk8=U`#gx++8}gRQbj&xIW;xuU*56bpL3<1-)4FZbR=})CXg_&A{<_ z5DUEx7F;KAd@jU-`;7&+0u0gIhPVWO*{EN}bbUCxW1;}zE^r|Wj?MzP*ap{Z!8HSC zCzl^va65n#a}PvTq&o`r)yQ8@8eE+P*9V-a%SL+Nx8NAg7O}&CA&|HDI1n&D*+_~DEfCdz}_cdIB7GCOStXdGmop_@EV^II;E^N;oerEf9v@0#R z-Dz;oT5vA|7h$OjW|UtAsQ<=v^C#NlHflIgq>aGgxFP)_8g$)a!F>)mAq#pha62rx z1aJ_QehJ*e7XI!44pm>jL_S`$;O+trs-a&3hn29V{O(AD`-BDeYv2S8A}XFMG+aOE}Y^w zUMD=eXllV!`u>#Pf8w)?p2j!H=~C@R9(#qoERyGU>{U8U51-kxi&({4&0H+b&cO=v zY^;CvDYw(h_=9daN8aR0YzlTqxD>l1oS?Sc8r#qa)*Z=KZ#<9P5ma9agjHZ{Pb3eI z0X4)=H|%Hbj_~Hbo1aLE*Tw4VhA@Lryb%c(o9d?kw*2lNxen+t*wo2xVj^o`K@gm|4F2_ z>Q4#%N!FfLZ`r<^9^db7dqjV^SATj^f9lbnp4Fe8)}Q{aKONGaMCo<69oEC%(x3YD zr}y-yqxuu=8mFtfO;qvjHjf@gr?snZv-KyR{**fV{mHLCQ6=bQ$&BF5dzi{T+-cEp@)^}Ph1D^zPqhT4_l_kSfPh4*PqttPj&iJBY&ba zqIy`f{Bt?!Pr-gKH*FTV&ZVq()8@G7Y8+ngR<7{L zf9UFUC$hij-T5XSUvN1Kuxs3(xSYPq<)TODW!c`H1nPRu<;?wJauhB1R$5%~U9Rw( z(XsJ8KKbb*((-hMp(xA(B287DZ=XIb1LHL;K1Zm)t_J{t`38I|ySQU3Fm7y4n_yIycOL$riF zv5@vky6DmQnQZx)u9rq_d5$BVb2xLqmK>)oi|02SR2T2kUyZK*hg31F`D$!2}qC=rq#_7@Df%Imc1ieB| zkNys%m#5OJRDP6?C+zH;A~;p=*wU%(4Na_jk7TKRiqM6fq0cEdP;_kfJ1Rdw(NnU_ zRmqkrKk}<&^EI+3phxjkdK523&!^MN9u_@{r_!T%DS9rQo_kpID4t4>;-%M|by0>+kK(EHC|-)*A^cM5Q738W^eCQ6kK(21J&9i` zy{GXsbb1s|rAP5n^r*9^(tBiB^eCQ6kK*a{ZlDGh+L|Tb@B>r$ZF)F0zB*pFMx|?% z(oMX&mu}YImNu#(%_1aGx=fk3++?gui&adSz$m3fYRF6xk|@nr=FtXD-NYR!&E`if z(Y{~4^-i=};7z-1?6KH0Dem#qNle1tn$IR^#MuPc>#Ob$#HPm_d{!$T^wqtAdz2fu z;YUQ~x74SRvgm7WrEcP*yVOI&weHev^%pt-^eb1r<*2tj^%hWXe!AiOIvk!PA2pa1 z@6N?+n{QV9m@DdvB+uPhyppYt#~y2c7+ZRS*9GIpoS#4E zmuT_Wqf^+k~R< zU_&&{;grQjOq>X#u%w4lY|Tt~w#k*7<-+^1dDEw~lg7?ye-?jR&&1YWE(AG92cz*< z$?;nrBK785GAT#-YMCN2`l=C!LnCwpiv6hd${3R93~bV;uhpuDu82}e6HPDmmvM%P zI@dR?o9{T7{s-#W6t>ts(jHu12Juy+ym zuEW=s$rR^%h;w5`=#ETwf5uik0W zvj@+6B;O$iTwFgkgx>@FJ+3jo%3wb;;a@=b3$8KW8NuFk{Xre8b3SiE_)V@cdotPA zOyPw2gJaCCF7|@s4?2Ax`#HjY?(ku*q1&-UlhOSMyWg>Jx0BuET%qMZ9p8UMdVh3{ zc{PI_Hu3ik!ryU?Nn}Er#(chx@Yh{qwq~;TP55;Ae-6(1=Q75;pUL_%v;hpy=l9?} z{9fjm$H%jsnR~cWspYf{^tZXjd?SP1YN9{f^7{(te8n~P)=YMn>l+67l774=jeQ@- zF*=Ol9l&%r#(vqwzHJJ>3E?+6#wJ|s8;&~+bne9SosO~JcCjCu!qxH^iweHi6#hl% z-xr-@pUGg`oqyNq_)uyvK@Q(dPIl0-Oe?>e5q7h~_o##2p_i$K+eSE1&aWUZuSmWh zIoNSYgdIfOgAU(qPWGaX>jkb?^4;rT$8_9rgdLZB_y}V{$GwQSFFJgfXL?%;8&wrT zH*|}1p;nJ3v6~R@CMoCM4E7!AT|9r&ISyxu|JZpWo_D&&wrAjbe{Fcig>ue*NcxVH z%wRj5w>VxwmC5)9ULpJ=UjW-ULR0d6*~#LLN^JOXcsiWyS;x=7gBtgvsNwkVqGKr{ z{-5)*KV-1u&TDXhjLQe5ydeX8skkw$7=Ab(j!LP%l7fi7kKKpY_et}693YR$LxknB zdl7c8RQW^XPr`)QK8NpNCws<0W&-a&${JGx??fs#r8Pq8@FnjW0{OHmYs`#>SBN9@(|%P$m(~_@5*40xm31Q9$!G*7o^Jf z9PFo#^_+*Z8TLAVKG5c3|05B%k2)&t}|*AB>A*zcbs?$4#lhaGIIZqpAS z?0{7HoC7sV;F1VSN|nbQuw)`^2YA`xn7`M_`W>xYUOtpA#$S&4-*B?WwXm~kQn?}U z5^6Y?;m;kFk2%>^U500~X6#=IY;mz$aQG`@k2xyw3Gr_j-h*~)9(JyML)wS;&pRsL zb3y@9W$;&o{#B}c+W~D6GNHQgu2lIYC+fWj8z{Sv;M?W&{qmx_GuV^T5j^j6&X+UT z*InPmv#KvX)(M;0nNiu5$r72L=K0LKTXOegVwMkSvj27EKAy?`?y9^mll>$kihxWn zUf!39@5Nv) z0396R!}9}f-*-IhUH6%Hd)SVVXKwefhej^B$HQ(PJ@XC^dusHTDfi(0a@L0)THolg zf1bde^_=nA1ooQeCh5oowmqxil?hDoPQddYz4M-#z`o~u5s^B^o%Q+zc4*vLPoB-* z9yjm$bJ(FX&wT1^_U@TqkRCsq{p_rTf1AK=%=sR;BKkRO4fZhlzT{w=&SxlJA4K(i z2_=hnW7qs^C<@7PO82#Do@4H#UXQ_`c{w_CrR{AmIt7KjVnLd^Il1?{^ZD4GJ?`etMAaP^H z`6^+o#D~w0FJ3D6x|s2>gD$psJ|?jx-|vy8gvYqU_k@dm#ev7aIed?}U@P7s>Y!ss z+b-<U9v{d4FlNH5r0JT{I!@AUxk6`yC{IQE3kvj@*(J-hHc*7LwP_Ls5L;B!9C+9^$FccRcjjI}ue zaVL6}w`;N)-?|XL|0rG5?_k>;ga2Zy&iDt|z2s#?~i-q=X=V@{_OacPBUHjN7&OS+oxTg z{~g6%a%F#g6uUjc^W9PG?u=i8H#NStyy#XF)R*l5D$m^1yqb~{H4*(eQZv8PKujbn4-TEE;Sj(0eG|-n4 zm3QkG@md||?vHot-^_SS4SF4X~UpjC;0oS za2WAS{)R`zK~wM%Ye)6xitx1zg;?0%?8kBC+9$qKELq0i5Cg{X*#hX1>F_EWn!u&b z(np>&fA{jk^nCf22dVi)IY!}sY1YefS>or^n}r7Qqr7lrYfv}~kV`Nb%W#s8r@RllP`Ob<*|-AoJyouI{;NiO%(mK&0-uc@X9l)a2hQh$ zCI8L&6t7hC-yr&s{5OIUr-Fi~lh~S-Esub!8C!brmpfj9#HCzBju-waIXWP-(i^ZC(8Ml3s*0dFt>#o??oQya(}& zVn0tz7$nc+mB>n37ZN`@*6u7=WEGtGHD?)e<5A{i&zP5kV;CjOwaN3c(FBzGkktTQ z>P>($&#x>A$UR+$GQwT4!bEAVynpVd<-f&2P@ms&3`bmDveDP|x6F8#KmON4;eFmY z`{ez+HPSMJ_&9f0F2%`nxj3)=rHlut^?%}pk%b+)*}#d-FgU4m)>3jHanogUw(W-| zKafHH6MH5OD?e)gA^$MtEoI*#x^2sY^1IK#%fy!DkQWMt&MD2oA<}3ya`0Iqzxs6^ z=ziXkg^L$J9doKg1C|Tj@hfG%8D$=C`_DiG=5=kps-kET-hpy$##y98@mCWI!|#|x z10J1!swZHMI7bE+ka{gxObtzr{Cn~Fq!h#1(YbOc9`U)7i-thKoZ*O1iM)rjJiT3% z=T7?U6q3tcAetW^bwwaXzj7l@W6iiR2Y6*+ze<=wf6J``bI6>zgXXhg_G7d z&i^Ut+X*O$f>ZVNKl&!L|0MP8?0>z!5ep}+Z=C;A(zg>(_>aEXTicV=H-AdsqP+LU zTO}Nj&D&GnwZkAHZ|Op`5k7qO5hrYG-$cQrqSmHfSmvR#jPC}iP=9JdmKrM}4@=L9 zQge(hU4R-o-xB=E6~jTzc6b!m{nS>WnMMz|I6O8s2KTb?0+)9yIlJZxifHetqnU;( z_?>B{T;>CdIIcas-+S|F^h_WtL)%Zsp-0eV=PODh@|JDjIW<@9mFF6UJ(Qne4|~w{ z(?0iDA+#5t{iE;Q=-m^V#vPWhs3(&xzlv39Vcs>!9<*(5MAxRBx9{zC?K^*k_Pt$e z-&3R56SnWxned>P2|tIVilGkgF31mwo)(UaCI^T*$cfM(hdV${Z_AEC!e#G|3J&Uz z8cP4~0?;15eWb+z!ZAg2{?_i6k62b6Pil8-yxQGDZ%y?eiLpbm{hU8vYKY!e%_e2; z=1EUusbu(}R;-3hPN%`=K2%@Nq^=ETqq~JiI^3VuSn^U)&ck{Ed<5ihD-Fy%30GX6 zyE*xgT=;$4MFe_0-rurae;_hyKHPdp{d+&8p!K&5mHfkGk1Du5dh~SKBMd#tOg1TH ze%x5=FL&#!`aL9{!4~&-V{t!+sD76S;pw{)!T{<0e$@a~>jvqAF+gN^!~o;}Zw5%! z_nDUQY?VHqErQ5%&P4GfzQo6~H2i}P1_gsUpGVFQeLP#Vpb8Gk>Of$jC@*Rwx zuz7dl+nv+^_ozk9+Y%~vkjRs}@Yj!Kl$Il9ry6HGiR86JtKb8*kdJsUhI1>f9n|cr zt#Y;2D*JdXpcNPNbtt!>MI&*M38YT#ePI z+4tW3Sv1s17g9!BX=tvYPF48UolLFtEcqthSbv3bOPfu6_~1*bu8?d`rmp0wbz`}u zuH+yGd7>Q?86J>XHKW#ILSv1=F}?&NkF_+{0n<=C7si=dsHy?YHFy81!*OeKy;NtE zlmeV_tj%ydmln#K7OqVf&GknSwMt#MM&IIFEI%ZscYJu`)>f`n8CI_08z0pXZ~NCE zWF@v7a|e;c=awfuDHTKeP>PS@c{Y!y_4D%Eu~(D+)Z2~@IR2w!6X1x}dB+YUGZL}o z^4sxCSge#vJX;ra#5bBs691_@`81K-?3PC;mCF>&7DO{-Jd6O>RsFH$B36IN3NW5) z@)#76$6%(#V~|#0V8Y~pA5!}@9y}(#XZ25s_UosV1*(=y7cPOvN8{DfkNy%c)Q?6% zx;Z)AQ4M%+S9cdJsagy=GtDGWU$q`I#^LyWP}q%65TT0lj`Q$H8N1A_r_^PpbWcl{ z`GoSoM2#pgAyTS$AMP%4BEq}K@)eJ^ohzj}ce?uWcJ&Qk;2}S) z-iD&JG_(znz)(8y*n4~u9eDC)mN2E#HL0up;p--bFp6~d7v3*4&WGt>^(`N0ZvHE& zE2Tu`m1whCgldei@g+L7gk;sMIbDCO>(vKYk3fqohCl2xtU*9|o0hB(zFytSRe|O^y@vJb zLz?RptKK;UbWo@*2r66NLk4DSVHmhr7n$={SY+OH6c98kJ~THjIkj-z2VLglQ{!Bx zD#Mdso}iV_;QixlszKU#5aNR;#SbMz2hk7zR9-@DPcg~8U?K9EyJRUC&okAcJhhKZ z-QypCl=17o$P_0ph@t~Z{ndQ(PvtJ9&YrP4<|)*=?x0?9RraKP@ps&@GnKJ3@EI_8 zsmfhgXur(6^*JO_D(F&qr>BhyUu>qYH@S~_Z(e~W7j)FI9C!j~$=b%W_MU`4<^=OCXCb2>;P{`&LsQat4vppE=jDB3e0Ciopb=(&SKOQAoJ#`~ma@!D4(#up+R$UOAJd+Azv5 zLN#4brFSe)Cu!<9ht}03_+C(0mK<0X?ka$D9;Ps;uEN0ZyJ#`F>irAI6z1zh30HEBQf&)NbqosN4SHOjmBWwh< ziM&XLDlT3_xD&whK{x?SKKry|TKIDYIsr^R`>GT8?5lL2{plQAqo8c-2b?{6Uyb|A zUPT=dPA0XTphnJI39#stSAtwVUzMjDHA^LU2x%HC0Tn2bAK=n~>gSUCDo=D%ZS|i# zWBKUplK#ie$HVgQ0(b0eJgf*W@OZb5!9d(p<9PKj=0|O=QIsNLL;b!{NY$3pV^Am`@;R@JjE($eh5QoJr)x_C*|!1fI- zXCp>s#@18#)z#LMCTUAhU3eoy0+IWK(Sr!(V<4TkbODHHesvpmi80lm?(^PU3oAi} zp*IT|&}WMOwXWxXd9_jdW7ho&r#?SSJ3xkCJN`32Y}Y>?(Ed*(BcQJTG)y&7WwzP~ zTC0*8(3mPR&6QK_@_wNYM%FT@5e`sK&YXgI2C`8I8fK!;<`dtQ=3v z6rZxmHR)hizeBky`@*YyUB?}jIMw7LV|SwiU*1jBqf?-`?wwKmJy&9#6n)v)L7<7X zY{8VF`eOp#2OE`|T=QEe*Gv;@Falr+p9c@`_1>HVLjdCuv|4@G24yIgpX4)q-R72` zL{x_|(U(EQu|yQI;-76VSG}r>6f7@Qy-(U&2_V*BZ9AY0UY1E+@nadAFXGFkJE$=! z+(G>^?uz*T*n1cFD9bBg&4+HRt8t8Vm!Pk_)mM$f zhqQCg;cGmZixXtFcTnn>ID{JIwj(nX2X(|G!Q`2|ohI4zt=6{F+Ggg<5g=-6`U`E| z6CKGuffE?NgXt=q1R>d{FUN_Nm=;DJ_!;qeiD?li24}<MhStec$ zPaA+~zg83dudq7Lr+S#^3At(Z)*LcMn4Q4BWn`HG`~2+T56p<)sxQ9=fjvNgv&}B4 z{4M!u|Ld@|V>vLd#B7|SXU1X{;%>gr4h6x&h(AK2tk?`?w{f@<_QYUji|9@7&5ece z-9hKo#^Ld)k=YK-Y|*e~Z@cJ$>0ZzDz)q4Ij`#9vm#nrXvzUR4w9&LF6Q?2L>x$U^Pm%o2w>_S_1TXZug&F2q9* zK7HkS*I9hs@u7GwM;i~}%-EGIWt982+yBda?K=z2ci%7$$BVS@AexrjkK$PDm+WGP z^CKIcSNh7!=9gDlq`bdpdF}QXIi2;FSLG{@ktBTWyShkuZ7gpd-oyAv?-4z718$M! z`8`NzNhxB{&hsG2{nBpM7g!vir@M9g`a90ozWejrcWIIKt-&j~|AimBaSTF`dkd|x zuOG&>HQBxpd}w$N@8)$QfNnp(o!9%k=bz>Em-)O$^h)w;#+|~xUv?^e@AH>ZQlyml zsg&}s{!*U8MPXaUpGqkU{H3IelycRnl=4x3DOVRMg;uqb;>7EC$%SqX7ll2#`cz8! z3zkCPCOz|aIJG`vUp&GK%=Gr?30xMIe+0gk@^7%>Zt%P)TU7>dhgm%d2G26Zl!D%M^)m#-RWpnPOwD)~Te>E7B zAaw<0amD@BWGIsH*}m5KEF!)&~JBtFq?2DIuf}*Shl|y0iE*x;FFZ# zUsJ-z;g9=+?cK_lb{*Y=R3kX{$dmBTj0NzUg5k2QbgEUR$dNq5FGu|H5JB zMATHhL6sf|u=|X&6h!yUP$%0vF=zCZE-G73VCawbw3iuuBT{2IrvF&zKB}`AXyo*m<9tWlS^&vy+!xpUz-k+MkLNven;##28>z9GR^=KRaWA^`a9G!pX z-skLl58>$l^Wm=*ME$=05P|j^M`Cc5tPgkA{v7Z}yD^qF>d9h?&+iScPMOhZLO-qn z8V-fGGZf3*(j-0kUOiHu_)1&DoIwRhi zINOZGQ(v6OqIZkKtd3Pc^s|9RUMWXuTzM=Mt9uQSdDEubtt-vlcKabKu#EZkJI}k9MI|YWtZ3&srF{A`+(M z5~h`TFtxX#(LVk%VG2u_=!WGx0)Y-rC0QkZnCjwKMdUpDF--EkSR4!xHrDXFm7?kC))nV0PLrl0XC#DT;|0a8H(r=BT=yBSn)Eej+S)4s<%-S5fodp3 zX9x6#&46=I&s2a;FbHKJwLtc1QVmF?%+ZCz>;>Gmy&u}9N$-bNuFwYaeBj8UI4m)7 z)Z#pdK7f?F7+7kU(3CK(az?gG=@nBrS~qMx$Jf zwBwW{>vH`bV>2Zd$x`t{caCCygaC7xLkY7G%*6W2FJUBc4|~plIIVhS89+mwiyI8c z%+dv>UdV$f{X?9+g>0p039^l%C3Hrn5%j6b%*ve_S$8kKvKPvbQ}U5D#@&mLMq~G< zZ55-zbWj@|pcIv(ospvr1_(@$^bGO=aH_ITao8|uwbR>XkA~Cm#S}dqKX+yEd%729S7~%1FI&cN%_4AsXLi%$$FoBd^Aw z@6IrSXC7{dcTc#-2w-UtO+j%-=!^t%@ZRapA|woJ;b1|Ts=S~~W89!j#O^#qi2)&E z=-~j-6ZeC1-|=!AQQSCMGeFN|4gbW?rnk+UMk8r~(#AuSfqtxhRRyi6zr)d=9DbX> zzEil;dIDS-he0B$IRAwx^H&2<=0uy)eszRFJ6x7(`_s+%BM$v0B8U~^H_*$u^EFxT ze9z%kXmQNYEdj}T)+^StAIzyivLE`_huh|#?@aK6u%9EMcMv}v#;Gw8QnEQH7KP4q zONhJwKa5E`Hee5WjBG)L$5eaJ^QNiO;68FMvNKH$;68Gil2g>L#(f5Cb{B{}x5$e< z7d1A~nBL~VT$<7c1fP>>T0o~C+P*{rk$MsUzK@@S-%SBLKA|H=te}V8o<1ij4fmP7GYke zE@P{h41VS{P{wwc*MQZOBV(UjbozBNFQ5OPTv*8cpM$O|C>-1C4_hB}r;m)@L%ODT;OI@bk*qeQ*DzF$X6#s=D-G-If=+5`~Iz8ydlx!~Dr+@Pq zqfgf#Wc=~2SM;ubz!6hHEwYg658=@eXt6RoI);d6NDrfL!oAF8rFgNHZh4X{OW!%c2qtC#gvKNzWz`hhGk!Q z8#+}p3nFRxteH|b=cpZgyZ89V@OXdq}Hn4yUUdR@Q`!H0noQTT5TqSpmi2vlzYIHO`Ceq&}?96grcMwv6G zgV981L7AyC0st-0C8fu8H}?aeOT>EsL5q16L3&V9s9E>@35$OaNRMbrytw#XYt9X5 zjpl1E03e&pz&uhIi_St3@ituAOK9jZYn%!Tym>X~lr(*1n}X-iys$;SK*#8eL<(YX z5qMJ1f$?iWy$u+mWZpV<-N*3J({y^$8*}DO9ik>~hQ4opEo2rm7c107?gWkFn|sHHIF${Te#7FiMqn) z7Qcx`#;7_P5U4Q*0Okd198?8^ZW6Z!Q^Np=>8k8WXCfe zFPfW9d%Tc=+dn=WGXHgEPlrn5>g+~>0T1saGaGQ@Z$6ejO*0v8*g{=|M=l;^PfLe{3m(p{HNr@;6DT4 z{YQQTH1>x?^h>vPey*xKcR%PiT=J=ee9Qnd4VPJuFNs%u88` z#bO9kLD{tFTuRMooyQ5vS<%MC{VP$9w-&EtO0gN!* zkf7?8t2QsBpgBt$KPGjl=z*dnD_v%=kc}uGnv$*AyGvA%E^D;t$;t==V0#e;PYum? z)Jx&Ky&2ib^RNtteg{38GaYZ2JMYCX>CONaHhhxZOkGHC9P>ux9!Z7g_qWo$$W>LS zSgeU|z3bZmLG?kYYy*$YM(#3GtF`ept1}0e+<^kZ*-!!vF2gJPq?X6~QBRo|Gmx#k z(bUT4_p5jVaeqxsP#a7t*T#p+sW^CkF_Z3vp>2TrB`S`IU0y_NK4=nKWv0;Ecl^_L zzVn^Li~4;s9|=9T@Hm;ejc}<`!}DxdY(g6%W=Rs+=#WQmaXdWB2YAL#C_`JdN@W7*3m_Yk2HPa~PKOYf*N#nWAr5Vb04q>+NlhsY9hY zl&eFHI!H5AZ!>iEe6v;^8q^`F4mYYpBM)FH0KUdk*;%xlF%bNMcB?s$Zq~OV)PIsI z_XwSYr`Z{4f6{(s_TI2Kj9j#I2jc)lgqKPr!ocoK$FdefcB{Av`Dh;lV5nlP;T>~g zaKgk8P%CIm3~ERbGm(6!h9&t*xs~qe@Xn<3a(x63E5}R!@D@_9zKR=IQSaPrC?mTB zr`l{~CW&)TSq-wwpU!~TQG8U%q8rv~ApN=7NuOji;g~pIOwphX>}?8NheA$UFoPga zg`#g28(H{t1*wYd3rC}ps5RT+0NDkf3@3haSGmzmoF>%RZ8Zw2afDul^ZIIjz3?NV zyCi4B(tV;%hBhFJB(mMWm|#w%7$4;BtpB1VCNgV_qKB`Vp88A_$v}UzrE7Oy)r( zdAdkY$U3dEVtP{yC-|;4L_SNJ9p$i!PQ<_`&3ToHW2ujtjYoSMsp<%1zjBo0?<7@4 zyrTb>?Z!L4 z2JbUy8zxiLl7)-V3fT!K3px^>=ji^OmATMke%|loLRVr|k$mX-ee7rU3t{mR;2f#g zdDoYXO*DUMqLLY?!V24w6zmJCcsWVAsI){w4M3P%iWJ@6B#Xtw_Hh=;8L6Pi%OvGQ zNI8>1IZU+fN*2}_MxuYjeGqke4Y3H#^2h)twT7+@pu=SP4h%vax+B{RM?57;ty+Ow z^+F!ZB*g+cw7HZF-c(}0iHD0Jt+g~vXrZ)*#BGq)&V{UoDK#&@uvky14NB;elzk0O zN31IbkbYFsG5bRDABp$?HfsUVxPXW3hl=b!nNK*jn^#WyT__P$jb88bMqT_culHqKwZz<23-VUmWjh^mI-%%2l-B_g zm>MR`Z#N!&as*ZmL#Ks|BO?|LGoB4uwPr_+`Blikp8T8GgbHcWw4?*uqOc>`hFa&B zIOodPVFS)S6xWw{04&Tk@H9c!Eabt*Yy_qZYW}2r1Ig+1iCJ+BKpPH?!3m8akXvx! zIY4m9sT{IKZgWY{igX;2(4n{+i&0#)L&zZzGQ1~!glwmhQ`!B%rbB+J^VubUdO?r4 zkow143PhQm=R{T{WETc!UxXTL$=_WT6j1Si!R0#7-^hp~cYs$FC-GwQInso3 zK1W$CHX@-7<&p=_kQ0KOj?Sj<>TCP z+&4Cq1IO~FYEE;n1RyPe#Ce^+&h12RjdQ`)e9|0blR+Z+|Unzku%o`sK4h zVW#qSs-aB=t1>nO#XupI`*=^AeL|g)OfQuvmzfvf*u=^I^TXkwVJA1$S1+n zwc;4+hAvBbm%+=(+fFe*FiY(7v|%X1r-J$(iOZV+i%fn|On&%=7|S+!YBEQpP2E&% z2E4|b0k_|E0jR-l`ZU+A8k$ExKXwF9KdTE%l@_Xn*XuM5FmNS3AD84br=Y}@{Ruw@ zPOva%*c=U5vH5TT@X0UK!Q+VHK_m~Srgr3~(TeSf&k*m3Wo}f)Fwnk=Od_;4v*pKj<#z|6JgG&FJL+vth-+W6#|5~yOF^-3 z0Is#zxF(;3Q`fNmK`?DFJablYwxIR9j%S03TfaK4ae(~u^X$$I@Iz*R`6!001+37w z=B8g+&1yO*ud@es3b1MgJQ1@?7^gyCei6I`pZX#m>W_Y)8waUBL~w+&QOqRqJc1-Z zN`=n8;)P7VzKZi*_dbNlux{~m2|P1C7?HZd_@Fd>zS+iL64qz)pQ|_!Ps%1tu&zft z%go3F3`oJi6y0wQ8QK=MF7v)Yo6WXR_U0VQT(t3N)x1|1K7!KCbLta^+h2nVFe7+0 zpxe~eCxy(itn^W0Q-KUJc&0jW2g#@&4Lfc2joPVn^{a;``2#Fp?bEobT#*H@Hbcq6 zILkC62`1Y%#yQ!0}zRFzl7OY`JU=sKgW5FKlaRDxXhQU`KV9wIPuhv z?)rr!cfk>L7aXc_a;h)RUw!KhQAyo>kdVSri{W?%;wVs|fhC--x(R*BbI-wbo^M;> zDzOOjI=9FQ(VZWW@36+42SH9sjvJ-q*nTyK)LW}WIIv1HBYS=dlcOtE4aTgBPm1nm zgGpl!f0~r1AAnWCT_3g#K3>b7UX39Lq^JSX++pkirPXF-m;z?GzEzCIjXDfFB5!$dN@!6AD3xIeJ2+ZMHMb)(`AN|oU+@!GTxv;=gst=0NpfR{4Zs2tKKZhe zV3L-9!6zXsW9}-D!QioH6($8dA@~QXg318JxoMgB>tBzB zXguV{zGasbx_#@^LM4dWdUt;3rZDguq@Y}lorPJxpzDpfpKJSM_`#VlqdrvXCPH*7I;b2(f|l#WdiJ!xd}* zx!mFMf!yI_@&t=J6Ew`{4h?9%59v&2rS<#4E#Pb*l)daDP(m$0&@3D9uz(d;N=eS4 zeiVM?`x_t}Kk#dYiQU;Q52;4d~-4)XRNj}A@cmW zrchGEA^@1@&NMF355DaEeUKcB$pf5Q^YkYLBHG~N15~L~Hl1J37k*de@Zrb zgH))LE&Ei!Y}V308~7~!Ge~&9_cUX(DtRbAUIXomdA7yD7#7r*ucOq{Ub|pbMYFKu z{U4qmnCS%^%QFfOd=vKOy3=_%ImpWcCaQtHRuRlnwz;{8skxSjei=74_Y>D4ubg* zmarfW)D+c8P!7lMo$v~Q)P8CPu@j@g>8iXxG&Eo@ifO-oKUCf)MGKqT4`x4I;I2&= zX?w11KS?bHe$Wvq4?pM%De*&GW#a}8DQd+|5k>I2w2;WL<(LfQ7S|Q(z)uo>c^;~l z#hn4ikRFPT2D}hW*t0)qv?(qhFuu>3=yxziwQ8u~8h-}NU0FoOI*TnF|L3l^J{;GG z-@)-oUt%TP5%N>d@5}n@!x=fnl8cYuY3NV6#}{sOZiWlbg)@N~PJ1Z^3au%KcLo;) zbFvD&SLK)m-SPdSeInl^sK&E$H%Hgew<1FcY{!i0=*xrTK-Dde!f}2-;*{o&V1`__PMV;_3#l(-fj8gYMuUh0$_gD-vRn)# zSccv3;ySzpJ9JzoA)GURs#jA?`o-H38P3ieOpQV)1}~yIzEex{oItIt%1yI!@>Civ z%3e10Opp@Nu=2{7mX1wD7 zjX89b^Z#?X;Qv?np6@R)DLxnYE`26kxw6(QkuIr3chE!nGv?$DGxB|L2zv^KnbVmf zZ-*KA2GYo7@5mX)hUoWABd#4Ugmg@L*F4-Q zFyjvH)`k5+P*t4~N}~SRc|H?`p&V>)cQ5ZBe4>%m?jHC=4}o7*S^K5Pqo#K)1ss2j zHp^su7a;H3_`AbM`IhNl8nQYV`=J9Kw@dCo$YXfV-rs{4;UxEZAGSKw-ll(5D&TN5 zaX)~g zK%c8cqBjNawXX7{_5R}}D1xCO=1RxrX$j@4|g9QVx3P6`I=^pwlM|R3k;|>u}3VjBC~^jz$p4ARdnSFb8;wq zH&MHNk#QJk{R-Nn(E9Mj=~DCF$oPAS))mK>{7H3xX2*KsD>k6C2Q#mLu*-4!b?h2g z>r#k*-vf996k?XeL28=b^*6Y7vR3LDUb&eob3}V?db?YzIKK3+8C(AEa0eB=;#9OS z2>vqEyr-a&`|+A2!wgQG(ovmE{KQnMRleUz0UL#6^sqT;yz;77rrtxO&% zVTRONnHR6porYQ&*~z;UjREXimb_Y30B{4!UhYj)IIs}FgGtLO#dFs8&`R}Jod3=t z*Yxq;dpk_+K@&Onrsa$yL(sI@`hDL(0dmY3pTIbLv7UJnOdnJoF*_pTJ2-4cKRD~( z;;!vFt#?u27;K%7eH>l)0;M_;@jj5$jr;LoR+D>l~EIdg*jyo};j%2K0L{nubq%;a<*-mc`JqX7UDf}n?t?roSo z4l^$yW{q;ZKZN9Dy?WCNTo)0zqt7DIi^Q5Yn|31*?ug)&45 zS$4#gg$DZgN$*R$N1&?#Eca5^V>D_9;Q=t@p5IE;qO@POhA3a!cl2q6{z$)qf0-RK zfP&bWEZ%AXBG1QW1ML_=gd|;S z9~|=8*CkCl%2D1TDy+5S;N+Wr@=r?6dWcRR#w#` zo`CPX);;G=wd}MKaGA^oP+S?VAlvylJVI;M&AXgJF-Yo*o0i5>Fw5^ zKF}3ki2^V-l8rN6!RNsumi;Kc47US%W~#bcp|0w2CBXs0RuDl33}!-5i7Cv7;>++N znk|L3Z2KJX{#wo!#=Q_^Mq(yqM2CnqAL}V@-<=;(Ox69YHyOSFulM2~zez5o0^-gf zBmncK*=8wrU=J5K!6k~q;uVF2Tl?GR6cp1xaV~%?Yc7>riN&O@sw9vGJGrAAIaVN{ zIDZa8P<#pvwc+<1WESHv;Ws&u*&_C)_gHZs0FA>Jq()}bh#jD1wxqWk*9X#HwnhT{ zVlU6Xa9aJEhaK!rw}!D>!%y6!=BVuT^D)3s;#ECx2R&j4v#{|z_hb2Pe>eURI%zgn zvA^3-+~4to_xFl3?Jslm=8xlP_qU4u?RtWAJ`)_nm*>W!NLzmPS)A7wjlrC&Cd)&vx3o6WVH zG9QK1Ll}OS&6wB$O2-cE$7IIxcZ}mh+wW#8vv>W2aeNq`ExP^3Ogf@JddMMn+*~+A zWeghQ!zG?N$j6dAAND*2ne{=o7m5LWE9f4%RQjhPCJ9pi@Nb0Hsy9r zc1Z8~M_x^>gq)q(0)hypt~PHBT9xKh_DT|NswuMtL7f)sT|qz$sbD7%2!Dd_atE=f zs@?)&`A$2YK@v_I8b~GHI@9$q0V9iuP1fhYExPcLTvj6f6&NrX*(MyxIQHPEV9ZQa z>uzE3-(vB5R6{efz&!v_B}Li-o~#*-&exNj$bf~$M3u=qbS7321F>TRORBLRu0q{q z`2zyZVsl~P%y&@uY|^Hte-0t43?GCOefJ`FuH-!Zsjk{K(W@k$K0J(p^8xSTiNhR+ zdn>0_^kx^Vtn%tOLHST$r2wC$sf#6ZPK{v^QiIjOL}80%Ei4~KH`h(E+zwzy@0)VK z+uNS(1$(F>lPuzabK+nRVF;rq3HE?EvR;(2a;F7kMuov1pq-N_0N8Y({n6BPoZV^O zJqO#QzmmOuj#X-d2oc7bF@IeFeuPkr;uz+yRu6ihhrSB%BZO~hmh%^<6+OeHnN^+G zOvvb6`*B6kO=B?K#ZDYuXoqtz;z{=IIpP>UOW$$=UR{AV^LbZCkvV7pw_X`vh7U1D z{q=L@=#`)eaiki5!5KV!GCv?A7S9iuE8~BQ*ZaR#>H1j3WJ;lEn@4y(E?Qg&iQb13 zvUg6gt}s7a&-@T&a?{QnxnRbOSq~B7c14#o6tDX{UdZ(y>F)<0_yljv<&C}aMrww7 z@mk)W!}~9)`>pE!$9eyAyuTjz)jehlTX!?>eaF4`G2Z(u?>+3^yN35>^WJ^#JuYI` z&EmZ~aE~xk#KcMagcxNHo})6L{LeonkLIl}!1wAP%&8oG<|r~Bu>ENEraz~82Q{{j z$=>uZ&KJf3sHtFnXa-~&Ycg=O76BNjdHn|TA~!(~V>Kg;^O4*2%y2XuZA7vg$O3qw zvl>b9q#8x<`U_Nn?CCj*!A@}{P8gTmGq_uQ(5(5su_SaMnEPE}^IBZ-c!!44j}4c_ zEE-`x@lSX);Amtb>x_Fs7h;B~!bgnOK>hDcVdL&liSb&0O$ln!*KBBY>H!uaWbpBl z6l4;uZI+7Ff<9dXH8Rx3M$aDO_^3q{KV~93%vB4aRSsKk;GQg0 zw!`6iGxE6}Mi3%56T=r{cko&;r#fOcPB=N*BKIOCa+B9J&mGLdn@`Vv>&k!`;)L{^ zZ!dv54pXg9Ux#l!hKcpNjMntHKU&jbm{(>X3t%Kp-7btKD)HN;%;|O=v%fXj`dg*l zM_4-jLCg^W>vG<|UCT~+$2dGx|Fdr6_?Xm{nLSItXpJ)GN5;<&cOM&q%Nf;sa-V?o zlU?%8(_jpN@0S?;L(#}N3qJvAC1i!2F(TEjmgEP~F{CeNYB}?Xf5Rt%lGpm*A`Sj0 zekA$vOJ?Pq3t=plUH12Q2WMrNXCdffz#7!XkZK0%Y|Z@{ZgGAbky>E%m8P#XCx)Rp z%l)Uk?NqTWGDzM1W{O8phoG2sT#)BMx+;4fJ;>YM+8~K!G7F2^6&p~Su z${PxuS&lr*`vgNXUlW_0c?#_>&$cj-O%-|<$7MuN)mCXvpOX3|CkAoJ z!D`B(NBZ))kdEvKG@Eqe99*Gtgl>tf11RL`wJ>B83`z509V=y`M}2t`U;OxsC|iGY zpKiQM%Z#+vU@~ZrDJEa9)jxO^_;sfm8yI z`6Pz_DE@1FZ(t&yA?3RWR-DQ-Iolt0jOE50KmiyC0S3Toh%S|( zP#uX#Xg)ibHH2D51$Y-gxO8C4x&Imv-+B1I6#x5h&3|4y|AqH{iRb)N@^L*4%$k2S@51!D4a-6OzFl|+WSHnq|Gaub z?%#2hr+z=tG6#d!pqv4y1v`D^rl-8D@C^PZ_doIM{f@8a$3b2(G{IY2T#NLl!yhjp zlpu0|iix2?Xw6*bL~E(qqL!}+cOoO5Xp7p15--IcJ7Zw5LqN8u0^MEmc@csYeiZtL zFMwp|i=V;RUbaFYXB;2WehF-4sY@}?oC=I17pE^rYJ&08!Uz|H8OXYTZ0APW43!Z} zna4^+D2`(1iLKBHOxMJV70(;Twe)lt6YCxarJZFi4H|XvAqz)Z*F#FgS^KqS-CA>L z$mo3s7R5#7Gr1&Kz<-B}c(&yhy(>A)_Dpq#6UR7*6-T*rlo|@L&zr1>&nmz1T3>$S zZfForl;2o4{u*x}$1(J4Q8LfO*7S(#gSo%JT~y^P{&6L*Zswy6k1GnZyrq}nwr zzae8TKFJp`9ZbV?fG}ktW8*uhuu8ITN9Pcea0NeVzXSk@Pk?Z1utFJuX89j#D8cadr}>PpaS?`K2B@t^8`Lw{ z|6jL!L7%+4cIz><%dzt{T#)H>8)_cyy-Y*$8lkn_~bg-O1SBix-M^ESkc9w$7k1?$)NQywbtX!do8O8 z9gCyTKrR55V>1lfkxRa^*&2r>7F0r#nxBxpa3)xgVVR!29@B$yJc;D=QgJjd5ZM1I zsP_hTxR;i)`2j_k*40X-g6*65V%evPy^lA%55S?p7iPohVS{vffSUu|GZx1e$g?}e zkK)VF4_qiMJ+28Ylq+Fc3yxTEoH9k!yaYFiMx1IRk3ho&Kc=8{uJ7(8xNlXfdF@6x zM_~OsWYJit%VtY+>;n9D#h0-Np0J+W#1T?i<+?kCRzNouO^3-mmq7SH6}b)^FTQ}qVP zWFFce!>Z~H2TC@AVMj2Zgq@D_#OW+OJ7!?HiI}IM)v)i)K)~>~Q>EtJL1q7|?l;TU znqLoPze=ylcDUTYOY0xd6uGR&jFTQ`emOG!%Ut&-uqs=8aqa@(o7+V5>tO^J=My~} zzyr)kNY@s0_1o23#7`(H-0k4(Rm9mZqF_A}BmUJ##>+HPM&A&9g;2ZN6ev+w59F&tLz)9g)*$|%uo(d1gLeF1JhKmW*J5Zj;|@*&4{u%QN;Z?M$$oG-@JD%4 z^q=8QPS$1i&`6Ns$9v>201c*tNd&baj<#%@TLi@)s*ywb$}a)YmB2EIVB>sP06lD8 z@CXgiK3D+lwu1Ljaf@B?q{52vY&H$nJ1{SyVRLfylu@kQ4mUjn%ah}9X;r?b$LZ4Q zxKzWXRk~BV%TwFo8HGj@z53KXaU6cFbK)_~%@a8{4>mUf_+?O&OzlP!!sPjv0%OH{ z)mtE}&L;Js5Sn<3B06Z9nKf#?K}fcWW3HALq!z(Nc*-BDXLs zYHjr4I6y-7m!~$4h#aVnc{Gc%KW#mfaFdSakIl&_p&3qx(AV8betx21LLcjmo-mqL zo_I;@(^u{#TlFR@oA+S=Jic`u)_ES^3Uk%x<6A{x31CG5tTr-?eqi!!4v3A!lBW&E zG?px=enmO?U_Qgz<)w7Yy55id;O~=QT$>Y5HW{0=#7ilti~hbz9B&SPl+Mfc#!%?9wW*3=TZDuR*D~w$T4t(5_U6i zA{?e?slM_lkFo&=_#*w-u<7nvP>GWyJCC@|s2cOrG$8Dry(5QB(}| z1srq0V%*Cu!;e$;_ju#q@I$(jEE(&hYw4XwvH#ysOp0Xa_M1|T&m5`vYs8`uw3ieh)X*^{ zZ(W|BIOGWiK5%`x#aAPFU-TeD@QM{EpkBxWJSp*d5G>vGwiS!YOda=4(S`TKR3s24 z%a53?4HH_KD{iDeTN)o}!uBpk;dplizjN2;1EP^J-h(v^0cM>z!oIK%_)z_wEdLv8 zD)U!;`n`;@@00{io&}DzMGN|M%BkRFhl<%Vpi6>g&}Yj)A1d*-O_nE0r*jyuoxbIv zS;O)jTM+!N)KAMnCKzO%FwFg78GJv=W~-bE%~*jd_xY$F;>Z#P#|YTWT8bqKtIB@f z%d!DQ8isSokY&Qpcv$3ZU*=9I{UDM+V) zd95kJbihsFEHq~RCgP(wh8XFrViQ{83xh~wm5j+Whh=y*&j#Y+Yf-a=uUS|(27&Kj zLri7}T;`eV5hh9kP5w#z4e#c;vwarru(d>2IvngawAvFXGXf)#H-uC&Kv7oX7WDYT}VHnet z%Es>4-}3x*fUDfkefsehdz(Tu$$cpJ3O%dKs4%*JFfq=G@s9;^FLsNIROP46Kd4ze z{qeA~$pGgS1sCHd*qbzf$B=X%bNP%+16jyp8p&g1@XUN3b1IfeXN%6@nH=)cuKH=& z+r|i^vdTXw*~W49a4B<^Psgm)l)u2wj#{ z48QX1>|Wwj$k3p=!3mU$;Nw=L39p#9YP<-gA~!>lcjE!se_!VdXweqDy|MO9?-`I zITZn1PD3&WJI+Ew=72(K9!C`az3|U+sRa+*7jf>N>`oV3(8dVBWuX+hB z&fBqUYL5~8K>x6VD}enB2twLpa`;N6X~1i~`O3snWtU-7XiVcf-<NvKG0WW#w2<o&(D|Lq@T~Zy+Q04ycu=WhTqv7*f?g0?ZO1z)w_!Uyx=v<&# zEQu=v8x4ObM{zlkF*~EAU+n7MH`1(GuaL|vd)WMP4c?BJ>4pjE7C0n;?`G?%b`Ob* zjm8Gr8e~dEtKQg@1gEE#mMd0Qk_H&7%nZvnv&5V1w0>BG7svZw|kSEPuQC;9ug_&<7vEZ(=JbB9@M2m#@H;gR0J_d}FA58=t=&G_}?G znl0ULfTEb96x(To8jevMvFSV*G9Q#Rev8FtCzgoivYv0T6nzaCau8PBq1rb*AGHB1 zVyVF?mChA|X>m?IAFx)ZDXg3Gfxc#2_il8cv-?eW9fe8ouIFL_9VvWzkOC;?G#<=k z4LOYzx@@fLX{s%87+cLL>Us)tg`c9D=R@hQ!k_;U^IviOhIv2H*jy!13q1Q_o`{X( zA120On)t==sc<@IIPxSe0~K4xKg@wIInsHAahkw}lO7wEB^@=CQo@8{Q<=qpfqxb(nnBFhp>GaK-0JiQjb0XXe&RgvKZgu8}p<}sdq zQ~o~vU7RCRc^8Ab052n=4^C5#z=@+;K{y_~(irziyo!J$8wjkQVBW=i=;-KC0;5Jm zQDZo(-H+24B#SaRgD91V_wxRdKE94ulj1Qp17{6pG%;ICe;j-ynfn{u!>&A>>Ro@w z=4~_?)yiF}VK;_Tb1sADa?TVonV(}cHnS|a*=%^~D4H`NOFs_Sb8I7%e8^hel(lFO z{RksM^U7AuVl(Jd_EUf-(F@@z+W!AT&<=xK%dn_$Tf*I33e@mPx-*n*V+a`ATq^Mi zdq!X`ZH7-~GfdWT$E$e#(3 z)#-~TCbqU86dAs1JWXc{40*3?1JB)Q*vB8;)?)sP`umE7wjGiqO7lC%$N$*hQMo3E z{Q?q<+1g>Qkmwb9fUYUZ)p9`8qpwBAf6b111gnLNdW0hb{5+t{7%L=7u9ba$K^&o% z$BRp^hV$|{)dy9dC)9jDeQ{IbMf7)t?C)Bqzsn@9qrZN0hAsbub`ube{A*A7oT{MS zoL}N>P0*YZY+Yyc6t)!5mD>3UwoIPjrPIPAbCBjYvUE0}s< zilpCUO{*J)o~{L)>B<4RD$#xDrLo=E!KbYUz=zS_fhKY7exQSR5up+~YncyTZ+sVR zrJ1?5jV>2uPFqz7I(AR~4di#&-=Rc(ck5!vTqWWBu!Qs0)NF7(6?|y<+bG01qNV4U z2@Ee>$6}793SMTjylrxX0@x?sp0MiM_|**qzshneZ|5GswYiFe11X`4n~Sd1@5QHybr@W?Vq!w(1ca0fAOGT4V41&VcvIukk!! zU75Y#ei3?ezb^TH_E_A{9(y0Ulrcc9%);a!;F*Uzbl1KAZ}ABJ5z?2?XUxMB+20MR zPh{824*4L24oQD!c?%tK+BwVBp7+9s2tc_1A^zH5vNNeF)qAt8!>qdx#4rq={6La^ zGx8+d4X3sCU*isvkZq%WoMqw9uP^&TXYWwl0^T=(eI?yBK>4!uKjOPw%B2>W5>)0Y zi5%T}*X`i)h$5(G=HkQ-|F?Vw&dn;Ii1>g=0)(8TR@l!1Pq;UzB@b7kPJh0QYINfl ztjvQ(Za=R-FyWgh>Cx-Wu|uzpJ!Up_n5!gE=p5}*mmO^Y-Z_{zUvSCfFa`wNEezV4 z-1e*kX6zR*V4Zgju_Pso-=MOpO6$o{OIL&$N4m!sXso z++vAdU$YW;SqZ#cD})7ioTVM-18+U7z+8xt>U&fg%1T_tS=f}guZTlztJs{@6^^iJ zxu0<$){qk5A=7}i3^sEEUsv6a*YdPy@W0Uh5pYkMOFIzk%jgJ=*VTFub5SkuA%dQk z!J#U)@O;M;hWptxZiSG47%*Ii#0Qv2%38Uaa)FLdljaIyu(_I4+{ngr^4zpo$Z6*T z8MUpYe+>uM9dtrp?oz`^(v&pTd9N1GN&;qRdHX0ts34l2LmsQ!7d7O*w@Zb zgv{&2bMR9&>;BDLHt7aP8pVza5*@Vzu_^lH`%j!QT;d^cPU+Pw&50KY zUpLbr{s8XE`uS;48@D% z(+zT`3S2sLXX7nALgc2_|1AmcDH2}dNa}w{cUP-k?(e;vAD+)RPa8C=!6sz;fMSl( zyC+qF_%B0jVKmVF`jDYbVQvsHp)0>5lx^gW+C@9`N1s{v&nU=5xB@M)EByvWFlK&} zQ^$C@yr3-cF-S%9PMIjbnPoel^|a4oC#JJ4H`rduw(L5|nh(j3Qgeb0fbZJZuyv<& z(LJt5%supoNz)_dHi${=#+T9XBWyVO5BEby4u(USl*+vNE1dclj#4k$T1Yl#uY#zI zL213^l$hFOy$pXF>GXus!5KO6QG%ZCi`i_qeYN#33K8sI;zQ>ThI%M1kx*s-aRy0ciiwiUj*eG#Uy_ubby`-@9pCbqd zzIqN+kOeQ9vu?%B*@?{yN4l?_4<1ZUzQR|(#a2u_)z>lI%x1$-G#bo5yA|O9#V?wj zZJtB6gY8*eA>cW@pXYhbBba31)HypJ9an>gQCyyldgicn9Ov4{ThHcoqb4sK`HQQN zIt0}L_`sXW7SJ(^{P815>*j9vVDti{V_og6>SL!2P zqs3+h8B6y$PTFQuFj18{&*;J41pb+$F;^vm*{=oDzog5u=+QG#+J3quDwuaxW|LK@ z0YEapE1QNeNr0946dMorj!D@cPYjnuVKWkMV+7{)+D1ZtO&g&)DDWf|cpOuq1kb^y za7lV3>_pAh2-)5x(ds=Y2%&%FpT0(45o|P$Au4T>i{|P*08=@^hnHppEGs6(V-j5Y z8l3UV=B_R2&6z#m_wgk)#<8JGFI>kltH{Z9yo@R-$Itv@usM&5j$a48ZWSq;%l`viGavjZJJ_AsvZTgYxY{Ma z#svke>xkBr{{a{I&o6$(PZZRq6dmEwr~=fm00$oD*~gT9yi*>#;>&o%A6{8(A3Jz7 zn_K0m!RG8Tl;#<{-^@ypW#>b>*IF62J}baF^sm$Wixp zZHlghzE_<-I$UEaIfOC>0|y-ZbNNGaFi{Ks(ChFAUGayz$sc+|Z~Cu*jNfM88f(qT zb%d3^>Uz}fz@I_tuqg?{TZy+g%vJWWhE#=RM{RGtq_19lg%|2W>Y#W)z2X7&ibd8d z7FqXrwkzI+*Q)pA(ffEw@9L3F^5p|bUOgw(Z_Mmja@|QOen5Feh@RCr{DBlf)k#AE zbFPIeo`RL+(RI!zO%CYfAnPl)kX*BU=$@H5irv``|M^dd>Tg ztC^m~ugEtXJ4psB6_^9L0b64BHF+F>^paOz-s=htUokUbSw_Su<0`j|f#3UIb-yo@ z-^Whnd;hD>_l*n8$#=@udo?SN45;6JRekvehD9ZH$g%=&~po&Z1c5rd7jhRbhg>N=&# z#9@w*0MS}Uzml(Cq~{R!1-kl`V0L~Gi_?3wfd0*H9 z@GvHTIBTM`Bf)!e!jvEcHK`z(qFLu*EsA+BhU z*~=)jgD*1{-XJg9kyo4-v39sAB1itya+kVYc+`xn6=%b(U%#9)p0DU@!2EC``Eirz zN&icJ8&&%z<-xQd)<}bSV+%o{uVN%q2yilb6hs|ZG9olSVh$-|Z*h#-$M{Wn6>~}X zY0o7!j{$cZ+)Y;cn$atQ%|^c~KXQjtgFTrl#m|+aLHY4qe%mDF$9~9;{jThI zco5mqUy?Il-0CY`-Lw0Nni=TXFW{HsnpEh=fXHqDJ=N%vI*y7b*(0H^$R_WzKOX!XUqT+SP+Zn2y&0r-O$ zQLgyl$zCKVL!sAL4Bcxa?$O<4B|@kMHycg4Go?IHB#1^6a7OR?OUMN#BdZ0BP4wcO2fACp zOC0aCk13jAaGkdx>s4~Fe8snH>yp9n?Yk>^#2?;Wq0Xd62zrxwqArfw$`pfZ%JWDu z?R}tKanc7H`A=wo!~#bPqPExTYleuP?Ry_9(I4tY2r1Yc85w9LUPfc*$ciB**~hs& za$D|FJU7)Y{w7Qx%n}jdGv#mXtxL*z6A$J3WZP~8{yNxQqBm?rG7`+76-V^@?mM|up*yAceURpZr4 zKUi>G1FI2LHx<3fbLFF?t_~Nf!x(iKrw*5>!{t1{(o2P2BwhlDoC~D*Y>Ha;x!C2e zB5Xj!kn6c71o5E$hU>Y5fb&E6nCO67?e$z#LWxsw)c#hj=MG{$cif$Y4-}n+2b8C9 z(vD{0Rig$1KmZJjtmUx3R5i<8$mRYOHsjoVS+8hnjJR#)`e`oPf z>8ltSVcwFellImw4dhqYP4^atyt9|sYooN-sIP&HkVj|<afwt z8VfMH?qxE_%8%>;bE+VpLE&7o7YH;Rwm`GkDa~DVJ%X3h6~2AH_UOxQV6H8=l(#M9 za?$qUVR{iO%#N=mCV*7fHb1vjgwOh`7hK8eG-rvdA z7ljK7DAfV6vk*7Y0hn8|TxtyTuQ0*#;FVJWN{gApNk-17pe+BTSCHJmrrP)$EAJC0 zZ68&?h!WUDDO}N}Yv%GAd@^{RWWDCWz+Sg0`KfX@q2c6z;hss_q#30>D7q_h6d(`i z#(um5&Wz|o6|V~36k9-3M$KL-^5t}aDbIZaR+==hKULfftazZc3(F104wi) zOJ;b(t6<#{^%NVx>v%Dqg_&;;Fr<7*6f`PxDG3CJQ}JxYZds}>AivS(fV?sXQ)2-l zw^r-i-bS`009Y8CH1Sn!N_vm+tn&G(-h$9}XkYF&bP_n{egzufxot6WR?3PnJ_CVW z0^62kioPVPR6j-V6L=0E*C3uNEa~wpwAA7qXdiUXTv?Nr-ogC7ohpmq7g~%}bD1M~ z`}G4x;qpIE9{2n&BN&2Oea*!OpDDpcmRmIQuAnuvX}e{7poyO%K-^31Q?j2vDqhCL zd*TpV?@TbaU-!-2_Rop;yZ1z^-@pBRUfjNczt#I;@isOdMJUNdFVjc!Xm-ZOw2A}b zHNc)e5jDu)h$wT1honX$^mF63Z_T`dcun}YdW!=L9Q8FbMwNadGCEybpV*u}V12>&jHke8WE`WM$wArIy)Rn5@AiIP*!a+A^yK4%_%DSK5G`k% z4laOk4MO-XzBv&P|0it7Q|9x68|ntA+~>Kk?MrIY!4ByPFq! zh7NrCnkhlC8A#JzA~pg^+Cmc$DJ{Jq+ZLQiXyQ&deHApF@Ed}R`zlbG_%a&!qNkfA zzT_72rtgnHCcb`-cn`XhyaXXiUj+`R#f-4%RKRzbe8Rjoa}bz>Kzy)_8}1etzWim-|)W-UQFi zrA{u-8|gZjpUcx6Er!FA7!>wSV_MR-t@b$W|MHYBs{?NyR_91=S*=4IBU=5U4fKm@lpy-kwe=KckRjNJ(dH}nWx z?8(H_m*oB&H}mSZA0go~o@9=gjasTK(I@ADLt-0i0lRtG4cEMS>^59)MPF*fGe}=n z_XrqA4L-%4N+5ETv~ghGi|Ji&pjY~u&j-b8+xKE3r=~hJ0y7u!Jv*7v`)b8Le8=^C zO!Vq&lEKGHkPK;R2!VLPF#ZPL)uMZQj*nA6&voMY>TGi`iNZniwQ3r? z3fwFjNKLV4L3{oSrrYWh&tv|(Hm~>C?tT(ogtNF2UXxGEQI)ZYNq9v-{;`bx$Ssd8h8_{#-Dk_%T%H{OTBSq4#p z_S3H?Uxop&*%*!);LE-}KDFjhP%Y#h_M@WPoT-Uji4>f9Knxd*|Cb-^5S{O?~Y4 zLp#QuTe?-8Te3;)?%s`J4ddsRfaoH0>YM^l6PQ$G)t~|FOgV_J5~LQRj6nd>G?ay{ z5lT3j_@;H*bVptfSxYd`lKZkg2-*C7zx&uF-Fq%Xip$;IeMq|rhi5H=#=^&+i$;I3^VRwcNG(+F_`T^%sPU4UvQE-_%@V@-$ zs3I)6yc$mm5tSr5>@T`EfN`qm>wbOc(0Z+68$h}0TySHc9+!(;TRs)Tj{@y>Q{!Ut zd40n6mkzzO^KFdu`Qm(3Q;E*Otc8+y?k?RX zhKozYOB@)pEIuBe;Xx(xKKE*();gQjWg9g%0~O(owFE%LX4#FMZ?SX62eHL>qFC+F zcA!dFl*Pqs!onAY@#M{`%?ak1aWnAF7=6vBH33ke{t<}VB!;4Z(9S(@9UcdIFWrRY zuF>SeKb4o43 z?QhKNSaOYPXLdjazXen{+GOI4{#K-|<=f4Cotw*cE&eaFDQQk=IQ8%Ow*Py~6wnqn z2wV0;1?o<%d&g}nhM+0#pIM-5Q!ke}FN4_?^naj#gfkyG$2=v7;%E8xWAe3X^LDL* z`Gg~I=+8Em*jqUN4?v8a6i{1i1w4KXw)CmaBM==f0Z~U6owxmPqFcOx^#)|quPE7c z;avrCshlutvZ3{mP_%!^F8CM8eBn|BNeHw$CK2D z3;?Xp6}F8+hm#`uFlXGI;~&TWojG{|Y$~1t^4+QCeIOwG&XwlXq0wfr{95S^bhYOR zqy~)fgt)4-Uu|T_K)y>A^mB{fFq@N5u`%{2R(_O&6j$s{YpN0MI+)QgH#UmW4yP!l}R;!MVgdMZ*JH|pOapOI{#`kONV-=6=0E99w zzmvlIZT-!!?Cm3UhJio+~KLrbo*h&SNUf9;~H<7jc!p2n$=SP&9fD11>A; zpBA>5P0{Ij#Kl^rkA8*?_Wc#=r%{;O598Tj!EPJO4+Ht5Upeg!Rge=R=jVKfF^M>~ zAdmT+ONpSlj1A)KG6d1T#6->4NZ+Y!_35^^7{B5ohD(=fvx9lnrAu0s963w};7R6` zN{OtO0$JrlzrULO*uhV^d!(YWurwG`Q#$K>upe(qqln(=Y{goMy?aG+LPduQL{vO z;S23M*@o|E=Jnu8iNmQjJd0%Ok7C)md&r?}CA+b%4rdp9=V-+Xo~xcDU~@+G(cXq? zDZz*t9}gHkM-zwAIaGmU+MOo5ay_~Nwi&U8WkcT)$DkzvQ=k$BuB69O@cHonolrg* zL@?WtyMpUiPc1TtY(@t8hsHk&=Ytb~hTyT`qwL>~K6nxoa0u99)xO_aDGXK<7nP}w8d%-*K3I!HkUYG>O#g6ioU8%k#O zoWMYGV>tCu7)V|n#6U6<(pm({iU#W|*@i0v%0vPk{z!DZdPgQF?IWI9;I4mrzj4XMuF5HvqSYY0M8+SZUu zplnmn4*`xeW&)1*RN6s?!VGeQGJ_;-Gl(?ID>FzFr5-FCTmx1qmknTcH3?<-)BoRbMCq4oO|wh-K&}B)zeV0aH%)AE?wn{A3z!9 zL-kBG|2F)I$%kkt++R%bhiy)+GSIZjO5-$u-78A8{Hxq?X|JK z-Hz?V3s5S{$ccA=vE4Z@QRw-Mck?$$fUm^QQyOKI|1h0-fpxIPg&Wdf z4J`;r{23?sWi=aT0`ey5)w*o64lh5j%{nMO42KRV2V#=-T{L7U4LV5?+es47`96ek7 zg7RXV7F1nqaM;Qv+iYPiTNGgB@j}RZ=6FIAqx11Lvsm6ToQ(FabjWz^gAZ-fZz(#a7=d>MXN z5&t}10n3;9d!Jk%W6$XkO$k-G^a#BaG2v$)$_qltY7b)Z+%KhOUJ?Iea(L6)`yRUu zV8w&tzT>%hi9e-p<9Qf<8a)s%Ik>y`sf3ST>2)N=rTyq}B0tY_fCV8Aimv*v6yR?(ohI-(?akr1!S_K*R|W_DC!E z&GlMY?R2T06qYd-W1FZO;a_hhz+itTs#jpu?2vc!J+O&zPN@pVz`k=*aff5~Mh_+B z;BZ6X%+Nb=Un+LE_?d&xV>hVdc_6?~(!D+3g&GPi8u}NU;PHMKl9am-mqH$O&OLhso@qm zG}t{A0fJ9?r}#tK8l<|%D{g19Uk*Kyco(``grB$2;!8nl@)puL^~|9mh!I!($-T5U z+Ly|w$D3oJ{dSzu&ZqoT)h4{XjeB(bl;tkj>#M&jA3tZ=a=?2kUeY??!VVgD;x)j! zL64vM_x5gpf~HeBd5y0a3!i=?pWfu>L8^(@)ka>4LKDA3CxZqC@gCz9n{vQYp)wv( zAWhzRZiLz=EBRW20fR!jyyr;C8kejW!)p`Qi=TInK}utmPfsUek0E+XIkN>>Q8{Yv znmI`GCvuY3q2P~){rFOm!^KY>d@lK$!|Y|XWw;(N<}OO6G-DUfU~`Xp3)Ujt*h<*@ zC^Sx;qQZ{uE*@HQZN^@%g);Y@{zW^KM$(s+Nc7-GRywRM!XF>Mq{L?G@WO=M4`i1K87nol)^go9Km6 z$p0<@d`hOxd^B~Gr#W)k3*4W|-$HX?;uhqLJ`}V{fwhn{R(UEl@368DKNlEsD!;(h zf>irSj?`6-+$P~>Am*+H6<7z{(}bQBVEb?Y}&q}cqboY z_Wnn2_-$UG!Z`TiQ$&_u&qmptNCnH+*X-DcNM{9tiw2rdmX=#3?f*v9U5q~qwCpo%{*3@WoHT^Q%MN zy0+Dc)&A~8S662&9&Pm#oV2XDyRD_MJ05H6Sb@Iik@wW+Xh%alSkfNtSP@^@7>&h1 z2QCELJ68aYI1f>;UGcWg4j^J1Pz;}hTU?{>pVUEgbtdACoy!|z%^fSEgxA;)vTO;< zSrQh{*e87#*YFiD2<&K$b+)zoi>8&71OlZceh3G0>g@2xrj|~hS{7<4_P4YHwSP@C z)(z(TWm5uEX84O%#^YVxmt1^tGeI(6Ez<2wwBCjUDnbZT(+#Fq%1UTMj%i&JvgKIsBpKpuUYM% z+A=jXb$N6~^NeV4>axJ{WzD6{Eia zS18jp+#wL!x){M99gX}$qNUAN?Yo}_LB~_!$)Dx%Z$9C6IhofBe1#Prf1by|@Uos5 zR%-u%);@6L_Geq$(+@db)7sb4r{4c&or?_y9;iQh95fx%PryGN-j?3N6D;&ne+#ts zOu%~kOn=uI`V%sC+!U#2BQTzRDkhyJ#-R!)g>(hS8^9~m7ab>~DUgw2X@w_{x78v8 zT$3dF0SmRKqn!Q$$1IOe4CFFmqhOY2A_k$BjVDHTmNu|N!-LcY$6Z7NDb46K%(tWA zk7#y)kl^?k;VHtGQSrp5fQXqDp7L5xpn|@G!LkZ=rQQ?hGTe2RPw`c<+j@h@6lsot z0Q6N^?W^cYS=ckPigi%OfcbZZtVZ;O-shRe88V$Bg;|5JryM9|c>?D4oDAHNB$D4g zP4+Wklw?veGv8gAF^pGuy7FFjTKntbW4M)!8jhXxPsc$MNt>25jhqj9eEJl^IY8O? zA7k6YX#XG?Q5>uADL3JZ-Z#_1@(le|7_L=Q{Ifi@4W9Z6Po%=Lpu)2x>{(jjX~O?m zp7IFEt-jI|sr8gQ*D%nqr#>t|s|ZK~ZMD0rBU(g=YS9+m0N0J|v_hQDXWigdwWqwz ze5=bU-SR2Y)dq0!6{x`~<6n~<OQhXIfn)6yAJRZ-+LgfO+o{7l z!L3Zr{r8!o)LWrN&jB_OPd`jx~;wbe2|nnreZll}?s$t;e}It73PV;K*SB z4<`b6bRw>0z}%gnDN|gHB%CsvPjji7n4wP4DNd==ZaUW}Si$ar6L=cjyT+>2h#lBS zYp7UDK6fC(D#-Pb6G^I))J1ZocaWInI*LAWf5?T%{o!)MOx5q|GrnWgyQA5I$fzwB z6H~`x0k|MF|9u0)qFaY7L5}8F_mTilrhk%j1 z%ICaM#$)G}MU}NW+7{{sF-_*mVym)@#v|Fl*EAl#3if1roq(A~s|{?nvw<{qC%Z{f zlJq*^p*=ljJfqCzaMoPrGo4SeDt6a6$!<1GW&JLuGPeV(NhDfChsnbxO6HVqE~sH< zg3srqPbT0!he3d zUkfoUq1Tq-C?NZ^E=z6}UAc}88p3owWym5j4d9+2TYEa~^g}n%EP~Mtc((R1Nglxw z!1#d%qa)Dq=)H{H5wHk`SmVY%D}ou#*pm-^fIS#ql4g)B`;H__qYurN-01VpxyVki z`otTH=(w|^@yzzGe>q~6$P6C#aUGpPa((bfa%Cx;(3>WE208Q0@0p?)qiws9iFh8f zNc#BbBIddaUD1ONggE+LX9a6qV`ywd&7+F3#3mm{C0RY8>@+Sr9#?0{&gxTa<7)ar z@IZu?B7#*{x@?tILWHxl?JR5f#JB;=`r}PlUOKriEHy zN5LF?%3M#R(QcmPG7YRQkTGq>7?Fheton`9GI`NPc|o(yq;>Ykcl(&b!^|tk%{t3UT?5 z8VuET31+i1=8^GP!~V}>YgrRewZ3l+a=n) z2Gczt!8!H2PP_ll+I_yZ#%k&QOiiYciuo%%g;k!SS)R#Np1^F6KVnUx{3MH=8op_S z4@V#VUKRAgu8eL++C{NGJ88PnQ;X~##d$raMq~sh4*TLnR$OB!-1GUw@2#*>S8XmYgg; zj75!9!{Np5N;Y^{&8a0`M6Ks~=7FGyyw<}i5SiK)4SB2WO1)A!aNeikd>P*@zT1M+x!tP50W@L$U&FCFn=Z@vz}Ff*gVERC$oz?= z8dAg8gBm?cjOo0w**Ysx5ERkWMFAKNDqmapviOBoPwiqh`Srjyt2khQ#tn5fQ}wbPI4Y}d2g03Tj+8^(JDMuRg4DMa=0qC zxKLH;Aq&T^Ts1{v`%Q%ZTEon^zNkRERg8--Y$Jo_z#5p5Fz%fY{FSqm+qA8M-{L8Z z#kaBLFOpNvbz6`?3me=e&Gw99`S>1|hqST#He@CbXUWN;mwDZG%3XzF|D%Q{MtIy1 zI>KT@{A=OJ3L)r=?x9fL-;P= zXT*bvEA}rzBg>s^XO`ypX*yKRG0%9OX<+6pGHrB%2D3d`)Dqh(CWGFl3%D!?p{_C& zIn6S#%x$*5sLcr;cC4j|s?B0v_u!TXp=FiGLO=&xQze^BxXUeo6HX47bbk*Z=R5;4 zR&1&Y3%+ohRX{VbsZNV-H9B(`4NTpvq|i8-u|utr^$eCO#dl7nxXd;>(cJ7S;_{*w z|H?0B$;;w5^8PDppBn5u;dxQRb2rKTKo%a0-1F9F=}bAt<7b;FCFy*kCtp6o_~mWO zq6c_pf}WKco*(18Jky8=JNJa{k&AZTZBnTKwZ&i2Mfis!M*qw@B3zlpa(H$TV7S5o^0CoU->b)Y&cBd4k))exzD10*R?wbVt9=Y* z$qq!*7%bKB{EG0j9ud#q=fd-VhUe=vmOWW`tYbOPZVY^&r+qSUmD$gFm`*gg(u=s{ zhq7>6cx7{9CUh7(GM#K~pp5SZ#W|^RS)B;2Zepj{ehG7e&7XX$XDvIOjWP<|Ev@#H zRSI~v;S&hV==3wTvXjBiW?~t~j;`4%!c0uFYWt0%ES1sjQ_u7jjSmq2noOd^|Ms!* zk1Ut?XQnAb1grmRr`a5{KsuXaeLJlX;4yIAU=6DRQ=}XmbG`hd#`AvS`PD3*t@`v$ zJAJBx=w^P71Sm;gBmMqk79NZ4v@M!Zke+pwuY9M-MX5q2Y^QSC48a+!jJf9^ztyy>?8NL?4GvvLT zg(t%KdO*YTW#X$R3y+nr#wOUf$oP2H9@H7)W|8+z>=jEcu4LQ-#L3s8Z5l=}jJPR~DTL{nLBjTygh36|8o_{7h zzH!!hVIBA7c6cbidQHRg4&f<05}s@uUs`E3)Va+TGwfOLRXGj&(ZX{_pj&>nw48Ao z+!4U#1l>xg)4?Qc0~cv!>JPx9H9g~#H*QKmy4#LFeT z6oG1oo-DCUt(+x8T9&nh5B`6;j^)F=at96gM#p?lm-CDCHGZXMU8QG31+LBWbg>kCLp48P_2qS8&jxCMo6hyr zK-^^p(Ri1k%XK$z1M4^*_N=Smz10FC+grS$66on{11AkVu~PQBS`HZTbT#RBpuW|f zcooA^#oOILH`mqaSXpjDgb`1`%anLS7$?=}1iPEV9*AOHl@7pq6NIy3xPh%%h7Jkg zY)==>Pm&p-tn~EY(iTUB=T7|fQGYZ|H3~HfA_g29(F?6=(dGP>mNf`cnXsu3u!7&9 zVyq{Jxb8hky0F|-s(4whc>zQ9zL7GGxL*Aw?q)f;&Nt-sVT0EmK{ zXi<%0^|8z%4&NCGOm(C&gcWPsRqR(Gn2NX#y{HsrG~Orit!+fZ_?TMp1st?uBcKt2 z(mt*j0P&-fSz_&IUKVf^2jpgj_|!Y{H5|-ly4!t;9MEwg=#v z^JNlf=9~mYw<^R0<+HJg>0$pJ$O8uOvXQnB$RGCvoB_DF$ zoNX+~+&A^KjEHRw8+gJLtz=y4-7y2Lk(M=5O;e<1!lB)-H+&agAsWaS_G8^;T;5yp z`vTd8T{%YoTkYBE$T*INVcE7ioR1QYM;upr9)-p0ho!@{t^8UAuGMJQpi$MHhhelH zfpN@$LTf8=xl+4a0q7cFp!N^LFh7C@CSba31g7rt<~yhOYH_0q@KuIBvGPNG*5I;{ zl)NH_pW~(;8O>~&D06MLPK6aKA|5-e%-@(hT0x5SsG|;DRC%`JZzpK^IsSIBE|~{< z1h*drmz)YViOrXo?a4qujwAz;V~v4T6#eXoVq=|Y%zvU}Ceq2426&&dG%}cd=a)!6 zTox5J5=P=?*Dae2hHn4J^?}Axa9YjzsIv@N4&kzm&t|z;ScB0dxe&gim&>(Q?*SdY zYl_rOI5Q+$dbFIf{V9(^(fS?r&>hPu$3!AUDrdewxpKG_%2cKtbPhQgSd;wPl zhdCc@XlITI+7Q9wjm*kQ)6F8bbgg<$rkvB%41&?#1 zo!%3BwHlA@G-iP;Jk~LrW;bRe>pl$+lXa^Rk9GcJ%bMEnGPYlLbnU6E&{vIrI6CN` zK30}_EVK?G$#&t_p}oo_Oq!pl69G2g=;s%eU~7XMtfST zKI=-eTf7FaU85&#(nG7vknXdENR5z6vuSbi?l_T+2Gx%mM2#5|A^vNLaY_0i{nN)t zETR&D*J=-v@x?s_72-SF5>!wrPHTkml_++0X*^tja<%;Mk;c!-ydV{o^c^=8UzwKE z+sPHteO|3$>0o^wEAt@w&`VOpRb$cbNV4?5>_gKR)%oY%AFEA0p(E@wcEqMmPa3$O^PN-tendAjg*@`zlp4NRM#ZF zAMd|3_&n%UMnCQ5XWlm)R)gyA@)U;I)Z=pjC`jEOtiwMXuRt~BS1tNk?YZBOFFb(Q z=zd3@|3oY5`!PQ$Hi%!zP)S#q=Bpij&TGU>toQgaD^a@xRrr3b;rkl#9YzD24~+H! z!a-M)@wZRwlbOlPoYkL!wca2@;%J!jmug0@DAvHzPWoeU4p+>4cC{B zi0dk5l<-prF8iy^F_E*M0{!FSZ8lHb6 zJR7s{Sp6_dX+~d{YNClmg&QpPQ{jeAO)Xf4Q>vGn07FTJ=>lwmrBN0Lt9H-CIuhF3 zJ*0}+C+$9Aqpu)}WVb;Zm)*qkSB}JU-o06}Lx4rPvR%XTJ+j?fEqLs5>AdG<^GH&H z&GoczE)e1%Ka&~D%(K&+RT)L4c%ff|pKXG-_`aJAJ`8ZwZul761?Evlc&7vX({;_# zpYuvnhm!%iQfoKI)Xu<{o{K=I0dt=QPqm>;KWzS4W0~TtaRGvfX!fdxV-mg-j#-)K zy)m1xL6bo%Zp(*_<7VLp_sj4%nGFh;Uxua(4|6;PRl>W^%?uO!z0*pq?eDYsvCOT! ze{*$-CB)TVNrI=N8gcU<}6){nN+O zPR`C3%sR`*sa$K{o9%0?G%U-CIW-z&O*T^?8@bTP3niS|bKR;iZ=G)%^a|%7xe0&U zH5zth%hpQ6Sq>I27`6>ZZuBe&i|~L7y>rZLLV7gzMf33w2jzqoITZ<6=ha&{1ZWZd zTD7**P4scb@&XQBQ&{}3!M=}nnSLz#=={Aw4%}|+)Y=uB+GTXp_{_y}zzl2fubbf6 zxLfqm`2(v!0%$|I&ddgCEJ-iWKeO)mg-rN!EuBx8ad4V9Xzj;J^Ftc^vC>R7zf0qr zYBO@VQP&vnT^YLLv|cth%eHj!-^`UQAg1|qRq3-3fA!k6Np!(%Zx(9l6SF&U4UR1V z>T=7B)hb;h`1460(BRJ}ykU;Xhp&&?(6DO^G&G^@um<-Hd>?)6u4eHKFVf66#5!@q z_bd~|Z1~cJgdET7p?^A`W7n~AG`s&3!13BAfTM^7f|9h{G>7eY$-6j9XE0%imv#-u zvC4yd+ExvRjgGNWN<`!JL(=c2Ed93n&TST2VQ~4}E?A7ta2%^&SfaK6yKH$`Y(rj` zg$5S1m!t2mXgCttI4m|QZ$TCgP3C(w9Q0cYiw;`p@MPieb6@*_CUYj!b;l-C;-{UG z0UXDwLu9`K8b3`GYxZT)(v-1ZEZ+ZeR-oC$b#YjuWn8vDv+Briv*c3Fam>6L1mW19 zEn6#&?BBwaa~vBr93O{{?H`j4lIs>t9!#zeAG=&5?8oww^l|vPN5k=PM+>KE-qudD? zNi(*Y-nN>a!5@xX*&M=-A(+t}jn}tzM8j=4?l-r#viqyr zazW@AShqCV)=q-K714MDdlx`mYk2;ZbM>JLmKa|YP}efIA=rqg$ggaUHO6DjZSn59 zmM{byG!7B2ge?jZ4Ayl(-4ZSIYJgw~Xs&CW*A>O%`dh=R%#4{qLj<~db+omuIUdc? zLTGESWOefm(M6qYt@PT2Tw}nYD)C_cQK6<0u7>8-UG34>sDMENjC8hj#4#;ss+2U~ z%?!;eqO;nYySuI2>9m$nv+B;++U8hm?$&0}h{h!$L!Z^L&ecc6v&tf5fhow?tOMe+Flms%p;;k8pcHVbRt{IVw*vm8+k*jh{9nQ_1X3UIr8ek5{5+=x5Fkw*Yc-xw& zvC*oWgfO92#A40sIr^N0OeY5CCpzM7tD_7)r(!Y4>O=>dY8>mB#~{a;GAip_!7X+O{`{+oiLqk@kF#EZZapP2El1$!CRW!o7prTg_K|!AZK-U z#NnNz%u*gTuwf3Ei708|c-ebv!lWA|^SVeV8I>4g12Ot0@Tt=U{>aMpkYjVZW@;-F z%a=!E^J1gVjI!l;lMa^=_(u%V5hsI9B*KB^oTEo-mTSy|)7!d5Kl8d~b+$%DZy9wp zu~!mk>u%_Zwj8OENduX(k~b5rFe@|oO`yWo>yWEf5RQIqY|dG3a7G zG{?Ym4Q4($Lre~&rbuoSq$Mow$)IQH|1=W7{)s{ zBr{6-sFQ{; zPhPcZJ^;16(P9&La{?n6y`2S0w;U{-oga-SVjbaSIR` zIo3wmE*m;assxG+%$j`T)M?$#9c^*ExemJ88C%aw3lGYbd1Y25M7M~rLCo#*)V&QL2XX*76M}~T?GR3+%~~*g>)PVEaE4miJG-N!^;%NWoXMdgiSCuct=h;4@rFs>EZ)FHSoNS`Q9C$w zR_97o{X62-?aeE4&(G=ISnq9bTdrlRY(ZS~o=cF^4b*ChD4FSFNFht6BM<86Mq%7Q zy68TKt3W{6+1}pV)g3jo$tC;XGy|T*ESY_n1j1 z-v^sU${h?OI@++YqOmI;qhhzIcLW50C`Gxa8B3^*sI(${5%q6w1}iOQ&_rTM36a>) znTWMu@jzeiA3LEI84G6<3=v+wAp=!?Dsn}S1*y?_2179PPTc&A3}_=rZC(v&ndvSgt# zPRpKHmnTii+9?9%%GxMmOoZ4z5vsK!=WT4nU}#8Ncz9a3s-c3`TT0t8-b8QxvLGwX zQn|K*^l(ON6iU{)o<$VFASbY~14{%15Lsi~g_6w&n|y&;&0WpQ+S=RVteDLE!iX}m zjN6XbdeLYdmK?FeW0sLF1XQJouu=$szKtq?=@xpjZB34G);4MIEmT(fU>rZb6|1bV zvAL@Yp@*>^dZjMzk^ppt?X+mbPNHZd26uI5M;#kWx))y=>s;H|&T5a1u-ORR4U^D> z#s<_><8FutON@vR99!;d`_F>V-<8eXEBU@FrqMIBD+aYbcAbWp=R z#u(NWu^QDGW05V*6(#^aSIU^GgppY;Kq8T;7?fq~u|5$0r)5_HX+;sTHMc}D2+U93 z5MAHc99z*%5}i$s6eHBthJ}{3ZA_arH`mCv5=@IHuwSfh_B=MGP=dLQb+a)~anNvg zHMeo6do+WxjE_rI*SrPBH1BU?K&Ho{q^CyH^0&b_tm-JN3s=4jT4iujP?hkESQJYR zYfP(Cy2wUp7etROv{QlVCymYVMp$%a8A}@*m$k(kb^8IUU%xC6u3r@pdX2o3R`eR% zme(!mj*$Ut>uy}mw>D{JYO}LZ-hcFD5X<0|7GYCVCCARgLgw5@3E3o!R zq>Ms6Vgn)vKtU_L3mCae>f0E-e6e?W;}T4!u((Kc%rKNtbUI4l7AWX}>uN_`B-+@# z9A>n!jjif%OA1OE1X)t%;p!;v2#41!XhfKmF`(pr^>tr!m~Xx{7O$)$B909Tz&$dJ zKo=5SkkfKQV|P3JYgco8W!?NM+5I*1$jTc_biAIDO_X+hEEH)anU75li;8vjjy12+ z2QY{TW4X2$5+g+sNL}?B%kJT^yWKl{!)>K5wN-Vh> zwpNk&?{>_FkY};Ek~6(ikcaJ0CTMA>)5g;(kY=|V_<9=Y!n@6 zl{42|1s{U@Jkx~ch#E@HJX33s$ubR%Xipql2N^9-S~d1838+E*ykpOiLR#Yb$>d0X zHRAvHSe@A{P+r)LtO+)Mn=bwqck^8~bJN8AkHh|r><@i+u zOWek?p?&Ux#!v!3Tw`TiX0@}nwnq#LMY=0EZq0a>Y^wRpzw&?0oCzO6%9!Pf_2h{S zXx3uRC+mi_U+Eq(;GhCO*2sBA+JcgM3l-dLV^`$w-B>h@H!fp8>Z!x_Yl<-J6HK<> zE~F>Bh}}x#@y2}OXlc$FiC05s*<}8+o3oXZ9K{@Ong{I`>12r&P2Sib9p1S3SeuF-Hgnv z(wIOkODn+=<6W`z!hQ%Ei?(A?0lx=bu*k$H5^Qa)0aeG~l%Rg9J%yk?7@X6*qOAqn zpzxy`K-*%={NTd&ws`@|(8YoV>w1y(X0W{zz4JvW%e@f);XZaIWl>ev5Fh<+(2UnY zHJY1Ou?#(Db}G~dLpF;LxkQw430c(g5z&mR&E1U8H&@dBe03!-xvaYz+H}p_zp6MY zToS+o0pg7mmGUqRF0Ks^-r(HSEc(C2&tDri!5PcjVi+Fw+fJ<4{#6f+Ei?MYUT*n} z<~nQQGb?0<(3(%F?`B&Jr?6+1SbyX%wh158-eqP9s}@f|CN-t8amBiIjd+*>3i3#A z;_DmN1f(gnc>ufaq$wTPRz9U>?!wQpC&@@tqAMGh({5{e3eK1gJXuGg$28&fD(qm- z&(Xfqhpc@+6`w}9a-0XmO?;>4&e2hUKOeyS{!hT&V1e5OI6pPi4gp8+D=^|a zfahD$JCDR6;PP?J2uH8rqGzy*L%@B`0@nq&>A)!t0as&z+v=7i_B=ujP{7f75S!2)-i21k$8qT}ZtJbRdguN^{^_gL`tf0{oJOTdYKAGW|rXGzjsHvK+tf$PJ= zmwsjgcgO4y*r53pIuq4f}fxFQHw-J+kiVfVCEO1+| zv>&(a7PxXeh?vGw9AZ4qgu)y7I1s^eq7Cy`z+J1si6LlT%AYwb@Ih?s_?iV@AK;!4 zjQ}C=J!^q$f-$wz=W(!OM*4O&+rtGcaOJI%bgo7deTaUqw!n1(Znh1aVu9-iT)hq4 zk1TM$D4v;X1NWK*t_yHAHgKo9%>4EPPJ0Y2gBE;TVS)26m!yBT!PlX|i6PhyxPSpp zjN3n1@JTBq2~$%)M8ChXz?B1ze2O>(+!-gD`RH3INo#E2=2+l-tIT>O@ZDm83jhwT zMn44H_bhPbfV;v*?|)^1+qfFfE*3%pR)O!tlgxZ)Il3v!n(}&=f9`|X4+xmG) zT5W^x1q+=2X3P&8xXFkcjQF~4LF{ES9=#U0jhiIt+cx-iS>OUmNn+1B)p!wneC8B$ zzgv4G>037VYAtY0n=#*P;5J&|`frz{pV+|t$O5-fk)(MxaDTMG?YcvfT5RB^Ldof} z7`O5}CFyA!xVQz*cNc%hkR}#=eE-n`*AKWs8@(#?n)~g$8}Y8qxGl559k@r5?zX|V z#RAv&MM*l}2H&?VaQ$DBq#p|=@F~Xk4;HwMUxpsoz%Qr<>^uJS<6Hw&}Oq0=Mh?{Jrbe@p#$-cmID%l4^r5FW=Jd5AFL6S>Sg4 zNRlYG5{J-(HVa(&qj)El4cwP3a9e+ZXZhN|y=#Fhe+=<~4czr-nE5!+FG=s%zdf%8h z1inWsaC_guJ6l8}01LQ@XPNnp9Kti1;k(5l;5J*}r11_3A%cDgxNlqF`T%#njh^nd z!1cQv5~hfL2z-CC!1bNzkp5tU@1lujJ~p20;P0x`FbaGT3tYL|A#Jw7r&!>2o#No{ z3bEkZX@Lv)91^`BQXHb+vd@_5>q6n{O#y^Y0oP=KYdXWh-}9)!3b@BCaJ~r+{@z9l zTt4bS#GV-XrZXMv-HaNT-tQ$AIA4K7qIWNfL-gBdf!p|Ldp=YPT-RClaNo1QHBEHz zcO_~ai++D$f!hT*JHJ2g95cWD=Q#Mg4=wnT7Puxq^hz*`Ptor)7P!bHhs54XXu;?7 zoBO^0vkv|~K?~f)7PzK!9TL4GP#mJ)J1ua1MGpSHI1Nz1{m25h3vlc`aTd7!7P!3^ zI@r74G%%gtsguln^p`sLd)+MfZnnTlco|MuAj7Ai?<*F#2;dgkz+LfKbH7^w_az&+ zFIwOtGceCd!L>v5`-TP17jj7SE;MlnxKEvH?zjIEheYoW6Ni9XZ-KjirbD9lgNZ}H zjW0CgYpQhccYkSs0?u!N+X}eZ0vSF9+&&AOG|L|D>hsL~MgVuM4Za}@+*ZKNv4L}) zZ^kE8!5-MiWswE03zK7#4ZeT0z}*kHRvWmVS>Sxt4)%UC0V?E@w!lRI_j?=qK3&B5 z5OGOat%JS8N#Jwg3;kW7!Hv^yGy#s@#U&2W?<2()xu7U8B!KWK;J$OA8SVh!dTs3K zLl>FhHX@mxV#CL47Pzeuhs55GrS&cPy>qe!-+X(&mH#<2+};Han!@@a@U67K`4>5) z_jRZYzey|HVu$Uz%RgG+B7l3{2A?#=OkepD2Y)Y>1}o?*u)z7Rw(mD!fr|jnuHP?M z;L5LYNRQgcX{m$xS;2~+@BE9+eE0x2NdVzf!0oWWl>=_N4czL08Q(_0VJhf{ zz;|BI47W80eLu6n_2;1P<`Of$1As&7tskP_3#OXk?!V4n&TA}ieb?K=J#K;9*k}*u zFE#hu)#Tvs<>uUg=`!0djTey3h$?zd^JJwC+(*R|dr-)}5% zO`o^tqvCRNzx^BS`~A8FZr5%0{f@uFg0IIO-zp2-uFdxNc3I&1x7h3Rr^?O!9sr!3 zpRTsRH7WLfdbtKCTFf;6U0C20c@AN@KO@H^6^H1SQeRnu? z9JsB2e^`SP{pJJCuHQWtxWXK8!y26Ew-j(FG3tj<#WO0*^o1?>1YFPpw-9ir=-4<8 zI-RY-2|ii@NAZd{g#1=o;MxJ_7C`tEaEb+PT@JW^x6s!EIEMkB`2KU>g_;?g>BnJWabHIsv1TMbcF)JI+PJY)^Wy1*^MttXmv*GOU zy#qLsk)%=Mxlr5{_Xt>g|Gown&@i|G zccK_nT%)h__fri{1C!3U(*UHw(7k6Y^c4VZpCJJe{ZeZ&X4FpF=a61RTX6{N7f%oR zjYn`=S=o%KGp2<~{r+hIx>pjQ`@uk9dMU0=ojNsC!WuN4bZfZ2+TjqGh>twRi|E6@ zj({xp)?yKUy@&bcUJ^+k5XPqi>{DmUy-&u^=%Yh z)EiwPPwFaH;*X(sm3NeZ#6#~7IEa65@9F3gA|N)2CM&Vto{PsZakT+|W_iTvki56&WAbN< z0$1`e>OKA5o_8THXhkYXBRqsE1lXA1?e#$}$q}Eomx|gXAa&)^-Z#BH_W^)pb&5_M z#_I_+tjQ}Zfr0&rH-``==?pM=wNk@`tcE%L3vo(hyVUSH)x8B{e}Y=)N;`v3s`3`n zL)LrGBOod{;_~*^6Pd&AwVof!NR_=`AMoB5!llc8hjkWj&lG&sWV;shl5Cy2R8P^R z`fD1bVF>d@8ayG)=ZBu8>-|q-hInuPE!0Do-t(j@S;}pY-uD5ZOD`g(+{B^#={h6V zBgnl2mo##3rMn-T;q8459W&vsTT03pBeGT!?OX%T+;9rhzz?AjR}+oH6TCh138+(3 zyyu5z;Z!*|(2FsbXQ&zf^aWrYv zIZJ55#ZOT1Wt?UrA|r{VqV-6)NhOR#@>U>Vit!D6(G?>;laxZ}GuMYRq0d4e(&rfT z1#HAm)pcQa`h?L5pFkwz?_&|pjl(z+BB|4dVlu{Old^aX)Ip!K=i|RXygCe1p?gW- zLWQ0l+Dxa3r9&I|r*bfP1=F0wZ0k5&ki|}yOBrt(gYoubU~6LU13ISq@epxx0;tsJ zC;4mkB<TI)+5BKf;|pHv1D`_t#@#N$iy(1iF&sdchi3!j(Rtqi1H%Cl)%8BhjEYcL}d z5oitE;L<{$X$~LzP%tZI=a$|jLkt(4SQ>ghzBbtZBe&i2@{OXMaB@bO-lHU$U&D(n+@T5;>dhG4}3{LDO-q14`F=Yo6w72&lPSP)? z)-6>&Ox`R>i6wS+Gh60Rn=nOOeswN4oZ}RH36moLOYX?XnvCVF)-2})Zh(6A*?J*y zE1c9x8%`3cp3aAQ!#oPr{$*x*jzy)%IyIBq-Pbo>d)?#Y&*`rb^N0SbPBMRr>qq-3 z@EmQsj|;y60v3Px$_^ecPd3HN^@UZ@uOW7jl&Zp_!Ky-*tKhSMTHw=9pNhMXyTIWC z-Xw)a%7D6|usl^W8Lje@hfeN3P1z~!+=6DQc;TlonJ-FLD9}7pnzIq~y7l`_N#ifo@=LHxOnz%-4N*Qt9-bQ2~L(B1x@uSh7d_(4( z?yzA2f?ziRB#n$XPL;j~v478T%@^~el=GYTjsw>(-0g7x+AICiaUVSTd*jaE;*-8V z{`}28=^tFKUwWlSUG5&AwA1x9viSt>lfD4u{(|$W2lAx7&Ng=KROw;(pNI2WzIuZ6 zMVb2Hux?7|3*Gai01_~?J>$Bov7_z>j(SPD&FRJ0yPcmAu%}AT0PizS-}8CWubls+ z<2Y5i6S(ipJMAm7^pAOeXShyr!@YT@{fjJp!*o3t{C@)fe>#1SJd^43 zl1=?UNLpL~i?jfv6H%{sZ~D`2T)g%A)U1C<4xivneivtI8w=pK03SIjcgCV>@%vQR zTNbaqh4`KJx(bNoaEZ5PA+@_%kKe25G&zMb%;9m~q#s0R9Z*SuIyhN07x_V{5&tj2 ziU3FsPxbaZg9`@ykJ0I@$CJZOZ}MV7zR0IK)%C~~ZcnavS9p8RK{slf4-~8N?P|G; z{r7DuV+ld819xG}OO9X)l~8 z$m>&2Q{^wB>14ImovL^ZG<7e6>POTqGTNz+xbQ#pY{Hu^B|yC+9_c_$X8cDwLhDQiYe+7Z$;4m3i-c`=gPO;FHNeUGBYS z01ZlU)qnDaJ6y`}!51eDD^+*6hBkxzRNGSJEqLX`2ACeQvha%q-25ykj361os)>|7 zPX}9=1B|MzW)p;*WxP6DS`ereFeV2U)x8j}p?0GiblKhj~+j|&;#Y+Rp{)cHM-TpdVAv+LX zK~vP6uT3+|&-82^JLLqAVk z8_EYZv|e;r;lKq>Wd2i>nH| zaK4dFwetw9LX$WN;G~>R)EnC`y|K&N^DS7URMG`#3|~>|(L&0Kb&09taMiDtm#Y%& zaglN-yPdj|^^3EI0i1%N##gFu;Apc)ZFZ8zZZ0ua+h2V3_&V%nO zyOa-{jMw zKcb1}?RgqqLrI8Fa@?h<@Cd%(?fGzs2|Lwe#F5#I4!g!fQQ}&3dbLW0+U2T2faNf;CpJG9D3W^^8pxuw|^#mD*1E(6bwCy zOVlTn&JQ6JFuPWWTcxDB%pKG1B`Uf~NfVY0%=QX|6JZ@QbwE*Ei{D5}YbO z2tFG~Z4;-buN2JSlV(T!60XIkhvtFbp>?2Chro=_*L0XTh7Abq1HZ0G^tp}cN5SAY zkRvhD$CJHNyy(oOSw9A1T)ac42K~9eJt%*hF013S`U!oM__Yar=%e^WhQ`Ei_2I$l!_+>t=CF~>(80uS zwYCb2Dj~Nr0Gw@UA5gRz*89G4AaQ`C3lGJX$_Smfi|b2p?o+ej$-PC00t@`Q9PnL$ z@5+MjDWvKnn$WDu99jM89=DHB;4t>8C9T{+Cr;k9og6s}m{`D=E=D<1_`tXaEkCXM zKTJ08I&zgSJudA`qpkyvNnTjR5;Eu=QHIALp=|ikC6o<+1PSTJ31Z5kZdCawhK!gA zPvZICL{qS{p)jD=GYV3RWfeQdEY!QGfVpG`h- z81#gt!7xKjU@6Y;~%`_P|fQu)kXXw5^#d_(+8%fPpxrXTI23M z16s(MDS>3a462k{iqfqqTm(N9-(*z3L&iPCxz%b-sfto-jZa;i&qMNG#HOU?_`rt? zhQd|6d(G)6*f6$cYHW>9ySq=Kn<@7eWnR8g`XF%oMCV2!=@plPge$pyVn%J5F4{K9 zHJ;}BR28cW<-?$r>*HFKHK-V93IMR)>5I>!v8}?`Vq7nQJSMWSrCDhjUpE_H#L&Kx zt7L#+jDHR8s>qq)69Y;`Oy4Im-uSHsLPg(E4>?4iuhz*ZGu6o$m_kIzg=~OCOgz`G zE-F-Z4eUJuF7k5aK(c?L@^sj{r5rl?6WI4#HyuJ4bj4cVz;DJS2mHzZ-Wz(#JL@Us zX}BnI_rxJjN9X!e6%M7^uU1b~o*H=lgrAU>@A=({ll!1|eogOA!_fP2T@reiE`ZYc zHKi*sB81kd9aJ1&N{Ux2s}(-=DqZoaz(s!QI-l|qhOD4?&zf@~^894K52rLIsm7O~ zjYdRD`?@`lM*&ok{Gc*hQ%Ap`iKV!{%)C`={Fl}gqA-XOr{YT1_~kSdd?E;@F_slg z$#u;wBF*J>LOz8JB%lh%6xq-j5YsHv6bQ9>KKvSEr zOH)GWbRvXZMC+(Xmr|%hr2d@{rBHIXYCeX{zi<&q_eT~p0x{1ZwE)&wE~<6Iu+b{Q zU0adU;A$jQPL+Uy;F}qD)F-+Vogih4KpdqJ>{swFLOkPNWX4?XR^1O`-(}6%euMm;R=nOzyukuhjfcyca4YUfb!e;q&tl!+JzB7U=!u9(VvcpKgIbsi zCs-H=OX@taV1X}&1&g(r1&f*{inkFR``D^imu%n=3g|+A?!;&L?Fl1YGGw?^d7f*| zJ4wE$;1$RL>KECxp6x?$q~v73P8LF?Wmj>IynC;t1N4aBcX=0N2ZIeeMy$RC0bD`J>S6q zWpE&;TPbTpv=E&yRR$y4Omk%vx2He8nr0Z*KsK@>q{7mpf%p}{S2DQho9a_<@`Wx= zoRz!@_0KcZ#qwikq)|x!Ao+pwyR?S*va$#K!F2zk=aobO4cn@bm2V&}SV-EWbxnk0 zviLx>xA$ra+QB9-V~`Mp?qe+LE^=+W$&KnAOaErO)k>FI zfDKw__P!D?+xU666#sNOU>H($iHtiN=uToy@^SYLha)uXy{Fv0BhR7iNNgSY3AzoH zBtECkm6emQkz|~5l?zA}WZ0Fi;FBSr_uc`ebc?b`R$?yX-N_wp7}8P_~)=iObseA8Oi%NWfAM3f_3l;bpXiw zlv9=2F0}$$LNqe$F7+x|@r{DKLRM;Bh}*lxK4|mONs43013~Y8y@Ew6u$H`j`?U85b9~sL29@x|PgQTuH}7~*p56UcD(nlr zpgixbJP7vY5-fZ^O?<$I3ryRs`pTg%40|K00c>0n=9 z=!5Qw>KqBKa-X-i6Ei8j*f6@NU%Vfmj2^KA3q3g)b|7|h8vvvQ413(Q?xb`PH4MGb z?N5bebq=;Kcze(0Q?pblPE!C`suU^v($qV?;lB^=nuWz&x9NWawAnbDv_g2MYLo$G z-|WVN)*i6QQKe;amoiX%i0tZaZ<5k#b&7JRcnBBBU#HxsZlXA}+?#C0*c9(ms4o9g z5Pij_4`4LTS^JsY!=atZ4sYe#RMrRpXwyf$K_$K;XmF?G?-L=42tNre)Oi5xQ31)9 zk~d*EXeqWdCHFE=%0)^G;V4*4#HKB~oxhoAi{DIPdvf6Lz>xFcZrsRs&~l0|wcxhH z#UBRWHw{mpS~cVFApSTFCCMF!L+`}DD zJMHKvHJd0MMVoiUawthccln5sBj zJUp<^d2p9wABNPIYX9cp;%6-bs4fU%{DOS^7EF_901qaH(1kDM-o(`SaQs5q?D*pWsOFxuFXo45*~$h2*SJ zAr|?;=Nr#Qui3OM4_85C75quLN*fPpzR~nT*)VwkH%XV(bBcedusQb>W`sYLA5?bZ zdf_IjD?-QwSNtND5)L_k#72b@v~v)<7pk%4(fd1_fE`O%2Lep58wbS#BA-Qf^g9-1&D^&0-oY7 zRGwgxQTBnBiHcXLA^H1}4Z}K4g4_^q@LtoW5AtFOWRZMARyyUmi8n8 z4;Ti$6-+jLx0Sk$zc=`IWTsSc05{xnm zdd$C|+9nsXs;_Adei0S~vKumGb*#+BkNY?^^7=3>DYv>~&$l015jY4CpfUoqBPY;WY611#PP7(EpF zt%Am6N->k+b*TC<>`l@V9`wwQ5BlV#E2Nlo4pXybD?aB9ymbOtBwrv#tp;3BTFv0W zO%bcE7vRc7YDu9K)gw}JU-G}t0W4Lh@{zStsf!j|ND4AO{Q@DPc-q?IA-re}cTh+H z7iJa=BF>5sGvTbrs7!jqJUKBwxjjH(5R;7&FEp3e0E`WF9ig0`>xXqeiVp%?0-axg zAU+aRPoc6O`Y%)SR1ZGc!cp;nx=>bLxajk8-Ys%!=CjJp6bGJ?x@II*GZK6;IegBV z&m>3u>UGju*C5#;ltW0CgYu8rNgnQC)E8h)N?ij)B<6`fPX6Yc(5}SNf&b1c-r;x# zPW>(lbbI@~J-4IP5B>O8JP>+DdD=U7fARj}Au>oKdtO%t_PoC5HyCP{>YcRv;B)7m ze&SQg>5eCqeFOV|Hkth0Ij|S`SW8IHg{VoGv>HTlAu&?~^_~oa#ujx*fO;_lY7aU1 zB3I29@w+>H3kI4MLa9F_MD+i?fe+6ac=IgBd+2fa1fWFV!J-LnJn|!p=WD;&NN)Ef zf45gTP`nR9cBf|kCyEAty5($T;NVLdGen^3{!WIEG@C-8j}&L3KJbQAiD+b_&&M+# z<2D&+0;)s38CyhUIJ&)gc@=W;E{O83(`gY|E+lhJw*AK>RW91ys!YcG8SmT!#cw~t zWV=tOsN_|yj;8o;*vw}dMn?>7kBZy6p@W6FYVb6(EWRUfAD#T#CPrt zWd>`40Q)*wc?o{~i9K&ByNh1}6E5tMhm7|8A@s7h`a@7#%6LEVATgp`s?L!e1IjZ4 z`%g%feoskAG>ztv5tfS|?|lW^8E!dOdFkLwdtS##Pf#YHo5^5~1$C}H`%c`Yj8o1* zosQIDV&O$-hR!CdWf*>?42xvwE)}MloeLcS;t>)+@lM9Zp5GI5$v^owbOEh=a5q%N zr%WtVex;<*!m#yZR(LSQGRqXL^5drK~_y=zn~wMpp8Gz`f^9ERJDyPd@Pp zxSQmTy#`W}ADwgSPtkw!x95;FdSAI^gL*Mz?00+K485rQ3c~;#rOH!xpqTmsSC8Km zAAq+1Mma#-t22oIJLbvCTYLU+;tR^oRQukY@2vX`G76P4j+6Ei)8i6QcEYB*L$|mRyMj*+&4fWk0fbgmjU&iH^y^Ej2ojvb*uiovQvTf~2P||!%=Bo7SRMqFCA5ny!{4g(e5*QCY z*E{6BciV~E-t}HT@UHh%xlqf0UV?Rg36}YnJV`DHJ>jj~N8(Tbf|UWr3L#Z*kg>ks zyD#nuy%lp~EgRxfUcj!CLG@%+{vkZ!I8?zs>0oM>OKor|6O?WQXg_4z*w3M#VlnAs zg)Mdxmm`|)9N6p3%Tod)v)tctpwn_Cu!ZIZE4^cGz?xONd1&VYJzT7!EF}VZR${js ze;QN7=Rbv2#?OQt*g#%8(mRj|8!=FTNrmBnbg!@RF%dI*tpeVNL6YKU(aO}>wcelX-1PQd z>T6)qBQ#!n_NMi)HiZ29Kxn`Bwxw_bBANya9h_gcDIkj@tii$ng7dh@*72kcQKt_>S+j@Tl&Th?lP9zSPPr{2eyTb2UDt)>cUsW1wE{m-@%S`nfC3}y7j^* zQw(h*H2e>RzOK|p*2t+=xRpvbnpRNLN||W=xb)i1zjoxtRfYBFz82kAMb&96-bI#) z-NPZaf!Bo*bgPINkS=58paAiqf6=1IRgB5xc6V~b8K0RPaU|xbVK;74X{i9EGAxJ{ zq*%N=f6?NrXyt0AD9^LR7k#=Qj`RfFaYyjGJxUKI3lO&+>RA{1nC$7Fk)OzRYX7dHwlnm;0YKTGpQUnF_hc%v(Q@z0LpjmDuLUpg@cPXzCh zuLbc|V;LGmaf$?^JfXlJA;D#I1GQU8tE8znZ4rN;%IOnb)Q zl@wbaL~;^`QGdjG?{R;WJnoPFO#aBIkAJ=PjGlI8vS;KFt@g|kavwKrpM+sE>d$d| zc09iRbH~?4ef;aSXUF3+su&!P&yLp%{?_XSMtdgw>;H27@;n4rT8d~*4v!Zqk65TY zLP}^izQ^;yl9-J=O+*sM%zPxdHduMZ; z-JQEgwCGMOTY=Zrb~Sc2$Kq{qyo@^9%0RBHo!?l77uYs-$2()qE28?v;B@2F=Jxi^ zmS%v=TyXg%muP3vqVBevqK$EXN3s8cjtl(sqU&gDw|{l>y0+Dc)&A~8S662&9&Pm# zoV2XD8?VU5`@7pZR!D22Ex;yay}=q6Oz*rly&;=F50Yv%R1p=2@w>QoOrI4Ut+CFw zR)5j7l9E86w8RgJL40S2KQ^^=`qZ*eOR>MD9WOukuffY^|37>00vOj(-49>cN}_;S z3osyvX*NV9G6+SIWm_h0u&jrrSe6w_c0_8}tfVVzmG!Q&yRzjFh#Wwc1s*$5^O_LFoYJTr2GTrVTcpb@-k^4-|w86xp(gDthBPj^UK;tcjnBQ zbIzPO^S%$*Fx*&ETeBiuHJr(err&z$rBT74W@|FJHSVU9W2pg`K16$ICYg*63`b*$ zOGW+IaTUX&%h zJ+Xvr$LCzQmR!HlDY>DnyKH6rTU8l05WUDPd7-C_L|`Q1u$tBoV4=4OKUDc;0nZ?5zqrqS2yEy4LgFUJTJ_ zF+^^tx}DY0#dR3szM(j6Q-M)Uxp^BER_DQrLI-&Gm7Rk>K_1;ckKU$G_xumf zH<@&cZxi3k9Plvh#B#CZk%xrv>@x_j#1BbPEEyPR$|1KJ$0XGx@A`9DM4-8JtgC@Qph%a*&5% zpKYPOp3s)2&^4{0!KTn~Ybf3n8pYq{Q1`n-eXXG_t)XjL@{+cOde?;dnmM&S)ZH8E zTgOZghVO1!6S@YWIOlKX@OqU2l8|(zinfHV=?r!Esr(4f>s9#^TK;P}yjJPb6pFVh zHRp|n`qn7vBZ{s))Yqht^CF?%R*pj)skquS8(hMv2H-tJ{Ns+wv)e86C(-MWyT60_ zBjN5$ufAD4h+L%^{PFTohgEtjXQb{5NsWN#B>x74eOjOY`cOqnXff#9L*-qXtSZV+ zzK$P%-@%h3gv_rk@uAd4CpyOE$KKR<(pyqoerUE-^=MPK%7a>gLXbzPt6LI_emQ3ewTX?$Kmx$uyTcF6rMw^sRyu>2T7b!*fOGa0BvI()sv#esD-{z`#O#`DM!Q*#*VmpBNI1=I$IU-hF}el$CEESBI~e@#^Hmr=`g>{@Ji1Y zPRVk7Z`N|yeWCiLl<~}cfy%O1+Wf6lmg7LoXwUgCFI1L;QkOF=%jp-OEQ8XXTrVeQ zEla_Axp@Kd;&-NHd06J>R~82CSyUUPda0H6_zLwmbQ@KWkKyO@KWemf&&Rr7#zi^f zvh0!h&$KK~O?ntB?@YAcsmZwG8S%F!a&_0z^yu~#YsO-6Y%J6*8%?G&-Kpe&n@;!c z9CceauIuWF)YWw)ka=u?_6=G`oSIZ}Fq(;;X>O9Am$yDTIM_O#aTBzzZtY$-;M8m# z7>Ll8!e}M}z2j~Ho$EB6TQ}yZTOe11maDmKZR_?R-Lf^<@3?kpL(1Keie=oUbaOP3 zOvDDF@lA=88^u~43axijTipUVSIn5RIhn}B5@T*_cTa63DA}uvm70caZZtENa?_?T zk2qiitt>s6<&j8Y@Y=fi+DIfboJ#J9#NEW!%y7g_rIIOOXjLKRW=wOvnXZ_v0JD_q zM*5@J4jFJG(V+})OQqdZrlXtc0F+FTNDdNN+U@Ax-iqJ$-bl|ft;n8&GD8PtuGhDU zItI8-Ve%AMMq`5*dmm1|#luW6`)k zZk$0&k+w{hz(qzXMMqB?*lt|ct7*T^Q@_40LdEnpxFXp0*_KRnboSS^wiYnHt)7;P zjWISu?N}mq-IyC0&7?ZGodz2snWbUS9g2>{Gm$|z?q;ClQs`(}hwahY7>PtjM^PGT z!K%u&0>D9pY_6`~JpIYSqhsk|s5fwJBprtMTX;53=hAJM=whh}&JgqVv?SX@k3=&OI14*s1AH4>#OMf9v*i4Ar1rBhU%SUNJ4 zOznuK2K{`!aL#4hqj7Y6+glqlG{E#UM)2QvNKa4dK?aheJ0oL>XgszR`_-h1s!)se zt)vnwQ)lYi%j))Z##rAjbU@@aeZ94jR)r)zR@n4V5`_zialz<)gzprtL{1mgC`ZnL zbf(c(W^`1;QMfpdcWip}w2Wb^MaX0w8swTKZFDwsp`p)x}w$0C`eo@qI(yOM;~qYHJnjmD!GA!Ju} zt-CW4O>Iqgj9kG}i~73Jm^)M_@?t2kp9FwIb+_2I4q8)JM4A1a)A;+K8&#o+g;g z*1mt`)*5uNZc6Udt@Z13qPj+@4knB01ot;Xvw?W)1`NO(Fl_WR7tu3!ujBcg*Jk9v z#Z4AX%pa8$#%y#m4o%2(1!tsDXl^4-!JXxI6naa zCT&z5G-!1&{j75oFO%U9UPj$3c$PHNgazD+p0aFQ#~Q+aI?sI8vh2)!2}Y{3Od5Y9 z?L7yt{cS4NoZ3gAVtfy$bv$C4>q?C7w7l4#(P@{G(~9*8@t)JPdFh!s;8_=F4qkEA zvgTA(wD9tlNP)`15(ROsYG}Zkb8L+?7jDxAku zXmpC-XC<8~$Lf&0|4A}b{Ql3N>wcxU$4QcT-}Sy2GDwWa4>w)V{Y&bn_`SoREB`%l zf09Y}mj>MvVR`?NBvkx9Z_rKrKHdnUnBl7Eeqhku3%WrI-C|S(NWF4|--vslEOe_3 zx@$nk_tHpOC3lZOch@D3!}rk`bX~Z|N|#H8xX2TbbJqt!SCA!-Cfm=!}qxubW6_($}O+KF}|f7^hI4=ziU88Z9)B%{jM|U?gicV z6%nqA?m>g@u1g(zI-(7HIUBA2VSuDPnL^4$Ts&FrhPUkGM>vyZ9 zdxgyZ4CuO*a=6kh0t9y${8le_9J+@@{gm8So*$IE8aKUsPZ8m&=zd|))vlE1|B_bG zJ&ArtFURq>inwB_=vJZM(dnK5-9?H>ll!niSAH43#B8DK!P&RYuN!o4vC#d{pql_4 zuI8=R*CI+|Oa4(dq7Lw#&T>j;GV@X|c=QiT+)ut8KHF_X^ys zqtlJH+vVP8&|TAEms|O&AU|iFZi*4HG}SnPP^P?_=K#k-*I#<@{^FvQt^Ag zq(k%O-@pdP`7ar!3-KVhOVX(-Sl#V7G{&o+QuUBQcO~eQETUC(j~R4P(7|=RpQ8I; zNr!Hqf1{wIenS1wE%UGZHG;RI8wVYljQ3M?bq3wd1?YMVx;>yP_qfqLCgL|P>6BgW z0-e&GC{*}E2EPx1u2S-#i{e*b5iG|s(5Wspy7inT%QsrFZ zKnd-4lET`%c_x2$&W^I_n|BlXq1*&t=#Tm_{o8jPrgG7{igGt?!>i-*h0q6vFD%2?IQYzCZ9cbM}-Ja-|>Dzm3;pBZ_319;st_8fo8x>fGl7S;LiZ`bv#VJ z9IDzYe#@W_`cmx;0k#1$fOi4(Uw(a-+*pnmY+W+>vy!n3WQ9)tY+mN|yMFd9^tWT@ zNu2e9dnt)|z(3~C$v-Ba4bR{LH(krlGsMnwGbCxwv+LP+zMS#-*R!``8oqF9myi1O z*2;_0A3_CEzgq+NJm5=!6M+8*_zvJHz>fg`2bhOyJ0DOEcn#q90QB+$`i$*Tz*_-L z0Gh^a0MLFA?TgX3GOh)r06PH_fLj6Y1^fx%PQc#+{sHih0D7S(eY5=t;NJkWUiuo~ zn}F{Do&jJP<@^Fy8i?sSEw20r9P2vmAc^O*;qrtZFC$K&YgsmIe2 zUu@P7y=a2p3=^z`XT|_a0i%E&fcF5V0Jj7F81NT>4+8c9J`T7KK%bC#7(nxeF9RL} zJOTJFfOtI(_%Yx)z*AV<&qwok3E<@bIv2SR@J0Z=DXRf+8G!Q9XNWog-2i&221AhAf_X8dRP(B6p%=MQ5Ck(twFLeEXlKwlmwu0aFkVOrj-f8eYz@Gx> zY@|^BV(=e2%lyU2c#-Dp>gYxLy=Xt14}8>UyZ?kZeI;7aK8P@VI*a08(C{kVcKvtI zJr4M9!1n?F12_$M9&oOu|9Tm4i!AsHfO~@lZIPrnOtuMpXnEfmnr{`!1vDqcLDwm!1KYte%-mV@7D$BOJ}6tYzQdB zzG7|<9LUMhgwa{p^1oA`%S~{w^~gIPGRR9Oe|E`?{PXEwF-Q9HInuvuj`TCzCtv@W z_e;;-p6AU`|9LagpS?b1GxDFSeN6h?l~|y>ghf1u4 zN@2PuPVxFH8U8S?cLP2F_!o&&G%v)J4$BMiIfk_L&}${ixf-D8*2-{~hEr+3N!Lxk z;rjh1+3H1IeE-norR|8_`Ehw zdT+cachfugXt;mjtsenjIChHR?X|i6vqZ5hr3bnvY{!=`Ye=E=ATh0w6?)uC) zRsoaGHtv|laSy%hPs_RM*%Cf!-iAfioTr#V`Gr%pXOel&(q7E)yEFrSu{K|j76T;tqfZ6#^06zzmVvX}sz$*Z+1%v^0pt%Is z8o)9cr{_GI0apO7l(;@zBY+{mHb4gOF2GHIEP$T*{4>B`0X_`48}JFhzW@#cjsd<1 z_z%E;0lozw*-zs7zkr_s@W_XA9v}puv{&J}7;rJ*O@t!=z7f~A0onlTC9W6OKLqpx zVt`S=4#0Z=Q-Iq6e+>8wzy|^Q03Qe32RHfjX0f=Tk z9*lVj;N^e{z=eP}0^R~>09*!G1Ly#B1L%3vcLH2M9FPWF57-6R4R{~mPXWaHFLC`4 z;G=+l0{k=JLBLVK7XbebcpUKGfbRqT2XGqjJmB1O@H`b@5#R#A8vsiHwSX0X%K@!` zPCyUfYCse)3`hdD1Ktg|888j_Bfy^n?gIQB;2yw!!2N)S0G|hZ32*}N{{Y_sJO%g> z;Qs*guueN4P!4zv;P(K(52yw#1-uo|1fciOZvbotyaO-@xE7EC>;y~zZUwv-@F##f z0e=hl2f#l94gx+6I0E=Lz*hiY1JM0Z1m8sXdw^#EKLz{(a1NG<3jnVKybf>?fSzl; z6tEod2Y?p9I>1K2+X2@AwgM7>F#z3rMQ{VclYrX*?+4KRSOj|!{%gQT03QR;JK#SB z_zd84fa8F#0=^FTHsBQChk$1RC0HGo0Tu#Y4R`|l2wsnHCE(3~dcaD+YQS1R7hn@$ z3t#{+0=Nz^4!99;3m^x$1MmUB-vIs|a4+Bh-~qsA0rc+fM*-i3Jc9p3_#1$efFA&U z0{A(g6pQqi0$u@lEr8y;ehHukune#Y@HFxhG$VWk;7ULrAOaWyYy)Hf?*iNe$O85N z{tWO}fDZ%i27ChWFMz{5fU-ed5`fWH8I5U>yMaln0mLx6_?{|fjr z;4#1xfbRmH2K*TC9AN%Sp*~@J;~bb#eViT;sT=0oMa|0d@o42l!KfF5@o||B!*x(|;4gABDbG7ttO} z-RYSsgJwQFyURG zK==FJi0dtY9N-SX2LOKq_n);W4}NhvNBz#zB)LHZ$B<_8z~!E!&i*bi3t!74vk=?B9yIB|PP zHG=aeAFN$Cbv-tvCr_2;K0y+5lk|7U;Zb7or`>-c0fT3$}2nT zJS#!4P?HarzVipnQaZQ03`O+Fm|-p_krX0GBA;g;FX%F>Bw^>Y&+q(^FS zp(hA%IVCO&u)cckwq3Net9)+3yxkm{_}~^)Cy3}|443D`rJ9hp?YbWqK}(_AcAfI# z6uNEKV$`)rr_gP?I=wiBZrgQ(7pKr|yYBYl6uNEK<6fLXx9wVhC4=BcA?WJGDRkSe zxEH6;ZM*1`OoE<5x9xhwi&N;fUC()O3f;DgmK}ngLK7dPX*-I!#Y0o*wq5i^D?vsf zn8Axv2xjo&6oMJRM$l6TX7J(^n)u+|G_!+=G5F$g|0`JN<1bU0CK)=%F#>>9c7+|f+;6Z zaC;tl`pKShJ6eZ5~&WVIgIDuayf#5*!U^JtK@dt|)`U8Hf_g7}e%K1x>tu0bSwa1eiw zPQ)oeOUodBWMY)CM<-|^O~0cPHydPB%||A73$i^P*_{U2hnVaxLAK8$`=mj3Ka(94 zWDj~|j~HZMVY1_b?1V@5EraY7lbsY~&v<0d8Dz9$dt}1FUzCq-Eu`Pk33?DEgpe}U zV#JS3RN$|g4D6=8-J=uL_)9-U*uaGJ3`xn+iAI@tbfU!|>twQa!XBOI_Q0pR#8(iah+^?LB1a}p;IC)FClEP0aSDIW*9d>a zgwN=Nr8JS7PWX|DZo(d&=#z;@Ck73&IFk(vGTJSt-_eO146>Vuq$nIpaz4(hl+~twoZIFGE$?hfW(TRf|*~1(v@rv*WlN}Re$0eCJK37d=@V=%8 z_JRp@iZ8h;I8Jg$Y2eUHSB{i)kCf!&R}=nx6aUj(*Dx_U-|V8_drXQoQy^k-?mp^Y zDPM`#>5n+m@yf-UM$DlB^w;DLRH4BK>Ahl>aX~ab`8;y(qdwEn^8odDJlCkw)DUcg zEUma(sZ$zpAk3c&+*$z_H*k|EsgrvjIV5qt#5dFdYMdzc4VBebjV#a#a8>r_BQNvf zq86#i5$BisHNbNj!uhqu#aWzJO(b}pmofX(+#n8;XsBnjOyV?~~IUnKVnS9fS0N`hCB8F=-HAi(oU&P~QeQv6nsZa* ziq5cUF1Jtep6B!C(&Tb<{6uBaTIBvRo)-xhT$CX<>ve+;;6ydeTIX?bCI~LL0?Rq#>seW!|SEXC-Kv}pH*|4+?YYmI| z__>7YkhzGIwv2@3*XzjmIGLwZ?xQsFQ33s-C-*=F=HqOI1p&dEM$YxMQ;l^|?w)ZbM_Ij11K9e8%D$^K zOzxh2ifM(0W+~+XL?D-v(wO~m?!FUBj#sB%U94h9H1LGed}69>p)A(o5wm|_`|NLI z0u;n&q;^EIH&iz0%=Ql}X4h!s%4lAG>bo=*rpemar3h0mwwF0viB83v^X)&uZ7t9L zFzadwG=vh6RFAyDlS3|7hAlDWyIwtU8}MSDz1rDc9)3jf^AM5{laQ)%;@X}4EKJm? z6;)6eW>@8_%-wnndxJD0Xr((a%s9OuoyO+7a5bXgk z1!A#=(Dd|5N4#Dgi0R(n$0dgRD!ngc%j%4wBF|EEMw_)}Bs$OC%q++V`4;QlsaMzn zDlw;h2bmK}hncX}(7?!xdDi6VwvUGZp1;1@qlAG*=6Nxmz20-uE(JFPBak)EfFM)*HHKOpPs!>BWQz+L;-`Rl&|C$Z2yxoqR6ic9jB5sQ+3Jz+jH3 zmomVXmT>p%v$M@JUy$p}6_dN?gyIS(_pG6O(MQZ!2W6_E1nVGAGav$8@r+Cxi)V^a zq)1I0@fImATu@WlV2WZQJZ0FM_s~>d8quM>OoUonq}$dQwzV37lhkTcirgXk z8W3$>XcZ%?e1=?8`(7g}pfXtQ6ToMmW~b6DwEOq-t#)#;N4<)bt&&fRi?Q!rWbsd@gLyQK`TH!<|QrO|>LW?X>7EqfUUQ=&8V z8Q)TcM=5!Btl|0?7bxN_r#U;i-i82PEYsh+n{x#G{g#6kE+_MG_f&ATfUDPj{Wh`C z!(ruf%W3wTfc#t9MWtpcE8z})8K#b@;$qG3qt(p3IyZGJf88-vwvLPuU?eO*)t+C& zQ{xugJ`3)I1y}Zac{RDeQQ^FXV>AgLzkfK7mOBH~twyxB2qIB|`;X2?p}9c_v3;OLO~=F{xg} zJi^@mstZ}Z@NBPUm@rV9{e4VGXH&XhyAh9ZC#e?*MhxV{Lz zLghGZ;0l?wA=?`Ffs+N?&EAI}yNF5@^kBVw!p~1zs8H2G_pJ!$vof6*t>FzsmG39I zo%i=K5i-*->DiyN1!b056w8zOu|}psgIIt`lII9qY%j)Myl*!Po{j2YQB>`0k6C!# zJI+)vvoSL31s5&sBumvRCs=WUs^a2&7tQ0fZ@6fS>}AT?O3}_zXDJ0Y{&9yF@kv4cBPF4O?(~Ex2PA+-VE0sw!V@Uq0>=Li6?|L`}v}rogH% zA2&(VuyGk?&$tJdCJo&q7yHIi>D>2fcwQ5t7P9DMM=tW|4>W>{>@$6GsxFYJymSep11h{01clSU}&PebUrL`|J6P`tdV2ckSsAk=}S<}0eH!h&uD<5g@j z%@t%8sChocA7@688m#%b@Zs6u3Febuf3p`56nc&29%#3eEsqV%QocE0D1#4F!4~E| zd-3wv&BzKnp>H8`LuP|+LFF@^b9p|aVNA8y>W$1V$jfYO+;z>sh|4$3j36UeeR-`W z=mv&Px&8Yt^V`4X$7n3r*qfnG!;ogrIdiUQ?)!09J~xhiRW&3XXTsi;N%RxkM|e0M zP;s~2g&O9nk@;SXD|~++^Fjgj*&NMge$OkHV4lkzWK#5;{+{%qlPWvb2A=ITZHmNc zw`=e?mfK%(DU}hz3^jr{_Neg4c|Ot9KF%m=%pXzrm({XIitR^_oE@+eckXx?w(z}; zOs!AW$h$Nuakr`9$rDDu*R_?N^=v81L>L+SjLu#S?cG5CTQ&lHje}N`6IQ_-Fb4(;w4Zdn@1@v9Md@h-x=ln8$;gL-;B!H!v-gEqV#zcJ=HgqDnnER6Jj*s!T6g_)I%zrTsd+ z#4uWTla|>lim}5fc$~DTt>rr}mo<3>)&Y```6%s0gLw#`MfZBR@ z#ips%8YkDq!DGxz=i|vWW@D^*Ur+{gplPqCGYcs~>S>k=4YA!3%&gDKc)g${2PMId zfrByV7q6_sc6^))3<^?wBlFDLX5#0!1q^Mjh*Dwy#n8N3UMdw)||2 z!0@<#oHNgs5qE|wI^Qv;4z3`<$gAN_=Ht}lq8e*TPQ`$zHB}h6TQ|6Orz`doaNCGS z>2(`MUoCo?-OSmruh|HL4b-T1kAEYYCKf8Exyti&4R{?JG)Mxjd0wIS%D6Q^sTy<^ z-3DjESDATL?$EJ3)irPM49Y@+I-o9wbv=BW6c`_k2_v)A+xr<8gyd=WdLG)#MS^jI z{k*QMr97bT)m><6{Bqe=u-SaE@3#B*F+MoI$=h4re?sK8%-yt(SM(QeBRP5fMY*ob z1C16U_#U0UdX;3WIGUCZb6%9soF4g_;Ko}fLZxCaT<^zq0dgwBlrvEACe7(0gxb2O z168ZZ9C_LT5u8ElBUtW0ALq)SuU8VuDZE8gAQp-aZQ>B*&n z`emiN{B=g6fP0x)UZ;X4DzEm80van3QNTWC7PQo?{%-TB-OMP@Qo(kU@94UYLZgFrMtP;v4QwdH z<~}LRG`o|7vp(8be6ym3EN=LCUZ+r`Z?-eDSq!C{B~Kx4c>BkhPkx^-isN;#+|Oa2 zk=@#Va`@`gCTK4t}}!o%{o;-@p^92X_BG zaR`cmvCUm8<0&R~;d>8qUQxxG^x(!74B(}S8m;&T5^1f`;NTC=En4o}{&vn8tWm47 zmiyICo|&@ySmZ2aggMGFAbRD*MwcjKUNr}81GZ?AUN#g32VdiyHCQ7c%rlLiGk0L` zN7<{;kGMeE4ycO}@qn_qC{kde+hk>ft6nd;?{g`0(9&-m>pYBYAYT zyxH$fe7G8v&zZKqZR+keWqS%q+kfmJ!r3pt`n;)*xq~+o*4Y2jaNGyYCN%rwiH|%E zHJ{7fauS!|&cVb-7ObVD`zmlTHv73h3wr0ohgUKARJ$VgymR8iagj8hpOm{3xcO+W zD#@q>%(}%Bc^-Zu_Z(-LDjTK;j`husiCi^s^K(;;mZUA5w0~G7c??xo=(o{{-0gyR zFB2QRM9>x!x%&m}F{VWq64*NDdeHB%p2(eI`l-`QPwEHmG3I%M-(Dwji(^!zLshsi zGqiiJN-QUNwMW}KE(@*VY`q@>vo5>FyWO8AZf~q_&Sf6BCsfzCrxdkIs zs{IwX1np@t*eXHWUJPxVX{W{&ttRqLk+jc}^av;IKcSLl^o{2PaoM$gg=qA8FAjeM z5h`!**Qp7?V*2(OBNl75sr3tbs_wrDI-rrMCs4 zi)+fTb`=^z%j?Ot;tri)ewb_IpN4G7W9T(-gDLQQT&BNn0W)8`+eCW}Kyb||_IdD< zKVxM|hR37ko&YYIt_dU1NP`sRfmc1CIMsz;_aF>G^UFq-KdaF#J!tOMVa^L}2eq+1 zdwSyUPCbL3_?$AlHc3{Cw^MclUda27hiG~!e);d?#oVZp7Rv7Q%NBu#Ui3HJReD)h zS>`3#lF7rR*{;$j%X1)t#Y?jd@)f{s<(IWB$}E`ftgOnGO}3SnKKaUA+kzZLJ3*%2 z6x_9VdUH5?{O}X!tUNr{kZY^ResS&iwol`gv^Vbh*)N`d{%t$T4}bIA$;08vZ#=Q` z^9!3lkB6Et$5i>HzE^M}8G4!z>odGtFIc=FE4ob%F#Jx`wV)Bm`*VNbSU zkNZJV|1!A6*m?3r#C-Fd;)R#FB3-;Mb@53A)eDeOhT7@6=~(HKAJYwShkrgV*II&^ zxU+iU?kHRGKal?HJktAZyPk#K7iMu=*N#_x>1QhsXTP{`&FQJQ+W4r>KDt-QWyaBlquLoVQ!KuaZ8RD;c z$J^gO&$+LplfD$P5W)A)!vjwE^#tFq3`Z?TiO>Z6w}uG8lMj|<&zj7>uiouPp1yGV>nEQNPrt+2QFfI0I!~69EsvJ+ z?a5EhM+#bb@AT@@>Fr=dW?uZM$!}h`^7z=6!{3;{f0udmOj}9QwH2f+ydDil)Anwg}3y{|N^u%l`QA&o4au)CDC!hQ!n7faQW*=@ikx%3!dl z`>KuEuX6pMZ=U@26WM2$oP?1V^3<0X z-uw(y{8Si!glWGtU0S*FSoRAGyPjF{KL^>iC$nFA^yH&YTznq*HB7IZzOr=5qcB(L z${#LV^Fss{EcxLBM3{Z-(WgQB^rPST>3_f^)iKDUpjr+^lL8e1Sn@YII8BJf?wb@zkriXFa7~Q$nO}Ht}zOH?v z(~-!yskA#l!YJO9*x4S-P^dYcOuOlfjIEEQ(~ONmv;MeC;m+jN*g!PybPw-LQ($Sm z7hK-p1$#0{DCe#j8ya#`%NttzdYzuww$ZrD7HL>kD{bLy9*bWaWhFWi+mi#VV%q5$ zjSj>TTU)OigCrS2X<6ZDymh;q$j5FNRL0zp8gx_5JEUnvY+#4e9UFJ!&9Il7A_Hu7 zQ_hA|Y-=pBX>`<0b-F_t8ShN)knz@ND!x;h8C8@?JKf1xBC|d@=sJBv{Z5NJni<~c zj>cJE5nY>dqmUsYov2q4+LRa=jwZIcgD@fN))Twl^+WAoifTa}GXJy)cg7N~9&8#M zi4M4lft^loDh6J0mFh)(iYv#WgUFjs#+k{6u?(1#v&9CGOGKqC5g}ncnN)04CMuo+ zx7i)&-8t&Ap6s8ZGByki!6NAl+o3tR9Zt5@l?+&WxSy1jifxN!V%y!chf)#<)8eLL z+fn=5-LX{x|19d&2N1a*Krx4eir(orn!UZ zjt*RlV6(ig8H>d;9SNr^*^Pb=;>gdOHuSbmcQi9F>`fD!bf-No`lq3xG%o0QgqdHd*gy<;INfN|`W9yc3P)9=`T=UE(R4a94A0(51JUM~yJIw&%8(0C z6#&%(_eu;#Q#&nbs4V!u=rxF!n<63+k|P}9cmM^qg*=r95Ex%JFmgB_-yToLWh)W( zTf1Sy+Rj#kqQ~8anvV_SB`ROwZqrQ#c}xG$($FuW!$aLNj{E!Ocx<#KMjgQb9B3>a z_adScXa*hJPYk#SdWC1S8XXbojP67`R~8c$LlcNjce@)$cZ)qrsmW53677<#5eoVL>dR+mgx5umxr1Bd9HGy3vZLhl>-Z&M11p;SL_;M3}0OObTa+4`O^1 zGd>;D62nNOX2Ki#M-U0nd8hy(NP0135+e>q$0?|6**uoUkj&BrE3W z)0-4{LSU5cmDhE#1eZx0s4;qN<;l6~2FNk=4plW(9cR!g62E8F34E+y)0^{Z9qid% zU}tg^3i}P2J6lGhmf%3!)m)6aZ%#yZubaz5z*y8vfky8*eZBM^)W>q~=tpT0M8#6v zRorKORWvo4MuwjCWUKXxkkB11jN(gOi&Nj?ENwx@-S1*zfJuQIh0$I|G0@S}hX#Ih z?QzUCdy}n$n22#0$jkazDwU+UN*89cm|!@fCvrA!?T;?4AL47>a$HrUkx`93 zn9goPP@tKju5M^8U`<^u$Qc73b<2squC}QjSB`)IT?L=I<%*FXQoKEkLa<6PmS4AA zTpMv&T2Eo|SKtZDAqsG=F%hU+E(48pU0N?6z zAy|v1@o2+9s*pnV3}X_rZ22;gAY#j83>oTb=^qxnTNCb};HrY);GwZ{-URhMA}zv# zyd)5|N8>|nn7(H)Yo)(RqxuFfD5OT}F?EclF`{A&O<{k5r>Sz-)52+IeJnvl>!a7Y zy)IV9P1~a}ZYCJK*h5g^TE|f>gU;1%Dk+0q$xK(Y3rz!) z#UZDw=W5KRltX?ZtpK2_(?atd8Qzq@)=QjGDu||w zff~zhXdg?E1bCK2b-IbIa55OP1Jf>^eZsWSaV_Qr*N??BG1>#^cCisbt2NBVFcFK& zNJk=$^(~8*!EP!R*P7EbaNQV2D)b<67o)a{t7wmlNe^bNScRdVg#XRdd* zC9z?o<`pvPO^{?fxb~FDz}iycc!jCbX+c0;8EoiMb)kO9d*nno&#NTf>Q^$2Jd1S^ z^A}i~rZJxOX!qU(bE7*rh9r!O@v$^k6g>k`?7WTZv1X*8YTQ9d%OZd zh5=fVVdH853qEuL+}P`u%V9>w1QwfZ=vvfYQA^nGp|w9|b=V=`pzrIV&SIn6qNCU( z8HF@fk~XKvx^h+v708X_VxpCD1Yfy^CxK8(->USNHfn<7V_4!^tT(Y#;w}MRA~^|V zs5zv0Q%3ozC@8P;TXrU**wo=Et0ZdEzQDrg*vaB5RiSQ$=`v zkJM6>o7pHkw_)UpVzZKwSB|-8`~C(Sx(D7~hMris^L9ou;cYPWrlN^7?O3(B?qEOm zQ5;pX*l56(1vY0jf$U$g%y4onBV-0rxzD{Skj#Ccnq>+X^jGU{ankj40_a(6zPWxy+ea|p#M*GfIwAzUSilGE+3+Sb)f!1(1JD|->U}+H~J2k|(0^6`0A5Fy)86f;xuCPEW0Yd_nYKQh$Ye|5IcMPkgD9nw7eN_lnJm~> zS`9(Wk=;`pg$j`6jYTukiIzlr+jcUWVeFIzY-1-bU>-ZMIH(hoKHhI3-_Apd$wbdU za+Lc$>mh(Q-ywr;rhRrSFy!Ew#%vdPX(GKH8(Xx)Pwprh>w4bDk0p3RAUYcDkHxY0 zQ|>5Y^9^IB(Rz3VY~p3^?a6qtQdHZfZFMI zQ!+y50+_OF7^SWN7o8qq+NzSvD^8=hV1bnaS1{#4f3cIRh8eg6V>C(T1BDHvevyz! zhl88x1VsebByoN%f+(*HiKVNg#~KEcI5)MOHt0oW^zJ@e%&a9E^PwHl z)Sxej*Ks&m=uI)Xinc}LSkA$m>V(h_@}UqmIP_%SBq~D}I$h+aV>E@5B6O4zqvMQR zx;UL|1No(9A{F!|JX&%qR{lOQ9SS0<8aaYodE6oUhUvtyB$B8*5+xnoDHoSy3KgN9 zTp|-woaW(ZEJ6GdYv`OS9mIBLQb7beg>E#|$G6gpe zB^WYhbf?&4MucbkV5ID>?(RTsXd@j6x!wd0y#^or(e6&M2317m(fN(xI>{o0!5lgx;O9zWRT z2QmA^$aFmhzc#ExJV9tULKM!tB{BGuY##v;ns~&J2?Y4t98G6>lj;@+ubm3CppuCm zO4UCYVEHou1|+M?-HNdqp*AnnfoTUJ#H9mUVH6XW4lH&kCN7&=V%rhx5tlY`*@Qul zkQ?1?bP=&O5o;4M(Qs+ECyi~Wc$5kyMz$bMqw@wnjZP#7^LliAxC_t4t``-w1?ye- z2FlbNO<|FbFiNy0iQ|PGh-^ZEc-S8l6Nq3GcYT2dJF%24-Gz-ay3!6UUE9P?CnwQv z0uM3R>VuW}PJ~gqvuQ(0-R!hsl--%-c=x}6k?c^!om^fNJHZBK16fNFW7+CQK#E8Y zc0IYo9V%ak#$%Jzq8B$<5pgi8r>fjKiNbB75-Ap1*uyKr9+jvNZ791J=F)pHq-ct^ zaiWeuy5a`SMY@hadayKt#K37>JjpCdvGTA%ejb{MHKr<|XE-*L*%;e8oY6)G52x+L z!0LpiyXbsM_{xr0+U2^H;Xd5X!%dYEL`91lMtWP!jpMw820lTrs3=Fn=*oqVE)PWe+MIpQG^YmkDq#<^910z$jZ2_Ti zA(B~iA(A5WQDg1B9WhUCFSOh=sW42Ai7JP_WkK@ zQ8`2qx*4a&G`?t+L`?`7OkT&Z|CUP9$pO#b)XJ52IM}cKEx}ef4>QnW7HJ~=Ue9L$ zN;SDK$n$zeKa-c#7EAFA-^_}A2A(Gxc$^f|)IgpL$$nX5%h@oi@aGc-1CbLHYF=SY z$IM}{vu6#ASulCME!khr8~J2{7z^!bn`l$Up438*pX4R#!Qi_|8{2$ZeZ=#zs33nnY4DM0JjJjlS(caMUG=nKpk5X$R(@^E+;s4qHi)MD6lr+v=2yz@wGcjKNRK}B6X4FibqVuuljFh??xO{(eLA|uo<(aLfo-N3) z4BdLoQ8?ZpyrQXT%^GoTGoz;Vd$bE`>yi6+g9m6a69#1zXM#HFWF8+X=P=clhPgmx6-^6K3K6QVL3tlICV~W*~D=Pr_FTGNlQB00Vr1H zE*`G*M-?urI+W!dlLBd%U^R#yHk=#^uUh5PRL8vg{?eCUeu;C*csPw-27#R_aJ>qM zU6=3x-DC*@v8Ni&pc6n$Y{P_w6vXLa4La9E5KBSv7#70ZKya0Q>S(G0Yd%Iq|$8}L^`NUfFn`GckmtXE&!sn-0 zkiCU92|nNjzH}q)Tfj{`-vtC61ml7w0zc?QT_BOkM+w6io5cM}{v%*Wrh`B3zS$&U zbiUM)Wx^dTNc3-L3oGk1sRzRFF*DeipKc>5ctno4@hLU}w9&-}*XzzAWh zy(m8qM+Ux%b_tP5+@g(VZ__MMxlDYI@q!oxPzo( z4~Z1VZ3yuIt*EiwqFp%^6-|=z@JWBTR=9L^_{}f5WScuSHT*YU>yqrS=lm!i(2&oaKv#NrNgKjS3%= zvciH)i4NEMxuiKrL4FPh0d;g;P0a@OD?}07LYg6a=T7! z1t)kiRKes-+0@Sw=2;_XL^B|3h#t!eKxu`8!dgE?wCs>{7K|`AOP8>+xCqhC5+%|8 z3`N=1$jHhyRSJfH6z+4yxQj&IY{0eUJ=lnP4+3i60iMnM7#}>6U$wXyJURdhdYlXw z>9h!Oj}=zVAexmIRnI$k2x_;uGscU{`;)*&^pOaR19k#DVA43LOJ2x7($+#=vNb-BGviR>g?H8MzYx&crRx5^^m^)U#e&0=ex zQso1tR7;`?C_wj2;mVsMxNb_g*P%HgMAeI~8h1w^!n@yLzIT+9M6Vk5`%msj!@M~T z0=f~zi|{QVUQBG4hj+Miy2Gkq9YObBh#(Dm%aS{!Kk-T{R0K%+nDka2pl5#6b;19xD!XHUFwgdVBG)PuF>TN{u~ zFJTYj&_yqoES9ewme8Q;-NxGVLJ7psrf^V!NAeNIV^WDR9M|JsLQbI_Y6Msj-z4l_ zgJb|&5hERMC!mWM`~48iidPmOK{R)+51vOf0k?)ST;lYuX>qoT8{lXM60IVcTGe~` zTi+^UZdDpxb|e!{ED2wdxFqb358!6}bQnd5ZG)?)$3|%*!5!r3uG5pLtB><@ND&+u z;D8l~x;VY3#fz^b7NgYA@CF}xMH~Ip)eLvj%ky6Ry=Z~oB@5t8gx>HGu3A=KUt8Ny zAMVFwWiXsfgi}i!mM?8wIj|%=5XVtgn2rq4P{NHhwKXfkRl}LgX!@;}UW#cdF{s&^ zOwx;YcwtjBklc1@2KTz+>^PRVROIhpwrr?=u)*yg8eF=pe`tBb(!u%_gZ%^1y8iz9 z`o@*ZR@BxuF0Wg$WKO)}@$K8fO9z&&Tsq{gh^}z!miE^U^+y|`11pwAYwM!X<&8@R zS45Zf*VPRSg0)w?&d$y2MOo6@6Zkf?H2S;++pN=tX6%@dwq%!ez# z;;%JS))XpbJYK)ZzYo)24UZQw@~?~jYWP8c&f{}~#9v2!j7EQl#6Ln;4S%=9pMzJi z>G+2w{znG>afvte|B(exWnCcqI(*C0ahgJ9x6Eq|Ex>hHmb+S}oBUb|;I|aOXA0nN zFM$7$1yB0kFY$%+ecY0d>h(t!JeQyBhhHIn)iOP=`~~n^Bp$l~f%?i6pufEU{zC=u z_ZPr_MdB|qozGoKN=OV)&LN5Y;C9ofpZ&SEPYoeekt2c?$WHpw#%Vv}(;IGbPDaJF*TaK-9k%WK0CKbv2fK5onVLYKo<=QfjjmX^#nKg$vDWA}Y_=*EXS2NxS1dmpT_Hax#&>PH z*z7`bi{VFkO@FcJY?Eu7!BE~}_}S2jw03fbA_yT!<`@w3_aY|3G?sm=DbI=9KS z=}dH{Z`ktM>WFZr{cJiH;%CaW$*}cnHn}#t*!a=dZT1nQpIMGVwle7o$+eZu%v-2z zrvKUWv)RCgqr5gN{*->~Ji*}0f<6x*MY zerGCUF8*RGn~D2X_0MNo-nrDJO@>)s8$TPakpC6q2R43lvGbXhgLJl)*QT>ghK0*|**u2Hk+2(6D8xTKJmty^;Q2mEDluT2-K^J3<}Hs7$}Y%&Vrim_Fpyk^&Pa9_?a?__4`8pVv}pi zC{zwJ@7dOe=|i^i7Hb!xGxf9iF45Wi-n4-&Zz26mxrOL#a?QMj`;(w(i&Cck3apsj3#Gwa-D7n@Dbwj5@i7h4WnU6SoheztPhY+zf1QC^du zO>QCknRQf17gL5!t}U-k7aNZ9+H@&KF7Z24->}Igem1!_88)3wx0&EKA^Vwjo=bVpR2Q3!vn{WwOCf&6meb7@GT*WFUs^W2a|@)a0r$(i-$&Tb%kRCa^N0f&dbX-@Ahrp z+Z5`ae?dtI*S@CEmZs1(t)VT=q3-KKy{!s!MW}n;db3)($wqfb8CTQ$+JZ8wl#KbE z^MZLndOP4a^3pp?CjxnW`_8*7vOK^XQ3$8^_mP-Bba>OzW$+Ys#>RSEjMXp=k z)=i(Fz{}K!?QH66+qyT>*V^HcGZj*Puwo{C=<@*lF#&v$qEG?r#3$grj~dvOs#__( zEleM%z?WDH5Urq3kcl&%WZKapAq%t=o;%71FUiqIARPSbDg%t0z(iDg1>B?zmdJ*A2*i zoqE}x%<@PiF?em=a`7_n4%x>CvVh4-?DaiA)33uLDb@Wrp$D?}+{;aJ{GjHWpHp z&8gWsfOm%TtHL7~!s4#4hWV25=6bS*o^BWesb^hwPiJM}{vgYK7;^>2IQkMm>&Ohs zSn}01Mqoktg^)-z6LAxR9aQBFkw||m6T$a1_@fIQJxe2<{k5%~Bejs$N?x(jO^|US zv7wH>bc$*-mW~W1Q#+!mK|fzFs(RUW`oeJQ_SS|Bde_#T#t8mf^sIyN@BxUOk+B3m z!Ll{svMMu_x|LL7W%BgxWp(>HW2|pi&$38I&+#tht>SEqk^#;9ai(K8?V>U}OG4LG# zRo^0`_Dz5qo?fQhI4Ix&y&XN7nNx$`7qDbEzDQ6*`bY4U^XN_|KwZlDyv>;46_I_GY2WM|3Qh)#$ZDM; z&YrLE#Buh#bt?zEidm6A^viJPPZEIN`U&&wha9)1?Y66 zi1RlWC=owJw+UgQldrdTDiAqE1oEfkz8i6!UpX?!Ei|T7{QlaYy9RVN{SFy)dqBtE za$s)0e&3XINakND6bh>dFiOAkp`5N?Ee!dH%tIHY-&-V|V(}d4Xzxe;6u%yW-=6av zhrb;m2^GIFgWuls9cNfE2d(1w=LSD#0luZ6(J6ih4SqigVXqOg)lczz%-~o4YP+4E zHRx6spt}URfYkH9QP9;Yp|~pjx(&L!3h+xCbjJ(O-D%J{ud$com_b)tfbJ=S?wSI0 z3-R3py}Wx0&@D6Q9t54uE`0{wGX?m)+n@_q*vtDNgRUENHo2cO=q3vAJ7v(_TY&DB za4_92Pk@fU!6AJ?`N3Nay7JfB%kfTwZgl~=cNuh}1?WC#(A`yl?q3bMc{W;efez=gWuH#zur2>`4;*P^@Cdc zyWZfp`ZDZOqb}7?)yHmwuKaC|!{79fgo^GX2HomEmggr1-G7^OcQ_889T;>SD5&l) zwSQu_^ZO0DYd|-s3W2NA?*U1t?EEn3sx>-gm*WP%XF#WqnTp>t23_r++RM?3y41@N z{xfmTp+qZw?>6YV_sa7ONvP<4A0I^v@cRqL;WG(??qia!UgEF6({WO5N~+*NeC`Jw zeP>No{i$yfO)dT5pR&u>EOZ}IiJS)E!^)2258^mV?0jq+a2#8S9UR+OQk<|M5M+ag>CmvR+wHd7 z_vp5LOFy>1?6yrQEz}N4oTLjRv_QAJ-OaX?Mu?99!8mLZz5ls0cQhKwNl4Q7-fy?_ zvo&|_J@?#m&pG$pbH8R_D)o!wt1bXX^5ho}cL9#VT<=M~T^!)-UgodTSZJ`VR4 z6Wpc06@*JUGTb@bE)9;0v;=U4`0@)AoDXntVf2gF_gxd5e;T+e;PAq=(e=3oa2y9A zr7-<}0&qlY5&r240WaO z^nDR#QXZGzhg zxI%jMa}(Ttz!lPiVrMRW{|dN5^{6w!39l69%l#%eJK#9as5(6Sbq&t1)zJkw8Vm7@ zg7p9Q8XS+m^7lNX-g%ZMH8^gEN&vTdX%?23OYlY6Xkl};C`=$Pzc{|uflY1ru3>Cm z=fJ?c{_DLJ3#zMcoPXnjK$X|Kz+d6@dMo|-@mBc#H&jvF4eSvyYi8XWZmt(aj*03~ z#OlJ!=+=_de!o@;#f4>js~r;5tcg zg>(|Gc8)x6$%>jG<&ShX>Kega#~{=n4tIU^d{QO-I-9Ol-B3X)hwJRR_UPBuvbe5w z37rNC1YvpW$`#4i%8ydyXSP30uX&`%@`;(wk#C|_icILFW}j8E`X)j?+huq>dNPyA09Dg* zxy@!x{^keCgEk2vd5KNOB3~lgAJOtLcxj(3$id^{F_2_! zC8yRyj3@%U%Swo;SYzt#5rx+E@0*ra4N3Pl{)8rst7}V&#f8 zs8rn_cs7334yEV#WbJV=K3lFm38^sLfj6X7;uUGAl%NYS{zIG!d5L>kZTJJQamXqc zpSPGwI6%{6w2wE*8FOx#kPS!Yh_5q+;OEY1+nW+&&$XI~=tVUROl z{*?G9x7hZJ;?UfG62-q28w4RG+NMO|EfFkzU!3ufMa+mgOBsBV?H@#O-JkqG6lH>c zUbOv(DEx}xe=E*-M--15;ja`O&82sXaX5qbi!&sHQvVvofMtBiUis6 zGqt8n2EPQ~e`&RUW0vr$)&1AAgfGpo|J^L%f6sVg2G@f*!u!yJ_lqujsTg`d6QHFRggXQ2tcTB zO73x?={?QJ(0|navDt)Ujov>t?hE;<1rSmL)6sZ5xfOe8og;HVg52zA961o5#mSe8 zlVisTT9gI7KMV5a3sUv|Oz+F237*XCl438G+ltAGm&>8z=Hyf+u>|I^l$po^{i2S? z*e7~XHP$Cy%W;#vx>hDUwaqec1AkDyLSE*PPLV4hZS~o3@50^fd}<7xrwawzrCxN% zA)g<7&pZ$6lUsd$A#s&XXsFng+&_bLwOoFvJC~Af@){Gfq+`iF&CKXAF{ItnMEavJ zZF=Ql>hOfZ^z2fNsuJ8>YaNT4|7+4d7BE;uUM%R;C94LQ`{Ol<*RPAWgqJ|>$5x+* z7o00DPE8@#;|iXI*nCAH*F)z;N#YXXg_pEYt-(H?*-)3<3aI*7W2!(zuRyijVwbnM z0?#=WJ6f2oW4;~gCD+?z^7Be$_v6wF_9@r0odz2-j)Z%h}?qw*n^M|{U zP^#1f$A3?ri|?Vf>hj6mVq)%M_;_BTOGcK--In+*ja0?G>r-D^v3YZSI!TanqZL$1&F z+sKkI{x#gZt#RwGp{YbkDG=DHI3psEQXbgmir-rZ&wP$YZXuN?XO^MOF+}9v(gcAj zu&rl+!pe#Yg|_A~;*++y>GhKX0A6nx?gKV}sV6To2Den&x4()D)9z zk**7$opCyo(eRR6?P$q!I|{lOsET@#{%wElpYUK*K~4RJefyE1wD~s6-zIP+ z;f19Pq9KJ;MN}H?U_^CtjHJ66tfcMw0u;|GxwRJl6WLuOS=zf_g?KDr->P6wxA>Ou+)LI&BfO32kxUB2mwima^hafYXHS??!xn9Vtf`f$`92pPZu9Psx{ul)oR7Hofy zBLVHNTmCTug3|9r1Mw?yUzM@_m8$Kp8!BB+V9c%J?eF`(Lx@77+et~d5d1!Fto=1m z`=kHTYKh= z+Lyi(|7}c_|A3?v&|1}Bu^W|DhP`GT`gIi?;mAFR;a@Q7}Q>j2c-SU z{o*bE2?oaJ-tr!9&JhK_a@Zy>R%coOxLOJ~Cr@1I97$nllX{+|H;;@tho7S0;%a$$ zP1!-|MP}BXcZS}Ump2wI4+UOKT&0AoP=16H#9%{3%NylzGvMEtCENdD`)|l%O4dg* z;l_!u+8j_MD{l+ROGlwDZOId}6Z7T8HaX!Mf5lQ%!F)7J(LKIts)wqjZboic>Js@L zpHdZc?y~;yG0{0v1Lx`RQKJ4T*xA9Z&Bi~!dx58K!=?1SJ=Hil5miQ-?<5`k@tU9oc;f?pf1o$rE ziuH%`XW6u{_|KXDph~fa4c65EKrf$tE>0zLo{Lg3JgbspB2SJ_jgMcQJTcQbTuYEA zMCWiAfsq5wktN2g>F*hHoe0KPB~Q2#o!O!;NztZ31CZiwa_+MK)#SK{A+SAhsdVu0 zt0T`R=A`x#T-#q+N1k^M{|I3~B(6itw=4F~)uv00DEC4qvd=S8Kfp6V%FUmn-oams zAIgBZatyYsax1b)7J6oy>7Xi?nM)(7!~cm%5iY6JT^KU3nzZ>m521^~ zw7UB-kq890Jc$`ft(cw(sx`Xw?$4Jc0tC)i3EW_T+WF2#-D6_n^4jzj#!}JqzD|WS zv&ySY32oaQS;|{23h@{Uac2u5rW&|YlqF2(PH5Dc96Ozy`smO#@^BJ!bb|QH%n`Dw z3D{Dt>83{EHBd7WoDWwc2!X7|l=t`%tIU`uw~6+-ZK4h8@~{W#3c^2y+6X$i9+??a z7)Lj$nyJ4tH%SsWru9RQpHvz%$rB%UK1jLIoX91k=9Ftv$>zL9E`mP)19J}?u13(j zdWLi4b{KTlL2BKYQZ*`vMo%i`!SUZ&02nFi&hI#=mtKx8bq(V)puE(HP~Tvnp89LM z+5tehOQ_stpQ~(K+MlAC7sVdDZ|k!*A%3@Jim`M=mK>bTR6P<=Gp4>vl`|WA*0(&8 zl_jr^-8u3QF!SnAH-xZPZr(8^hkc5@Y0^4M&ABA89@VU;?($hQMqfm3vO;%D)SwO2 zM&xDGwUF1K5rv-Vk<1}f0-l1Qn+CO!6;R(&of}k7A}Ga1H}O$wm#VB+=oC|z`mgB9 zr%4*0K4}(p#5zLM&Yy#H0W>R{oRjpC>60>G@-(?EAPPcNWVLMl4|7(a%J=M zxo)36sSZhCItkD#$G4wMo?hyF@Xr~mcn>S)beIIox_Y^4XNtCB>$yYQPm<2)?R!IB zMz8|{FV{Uq66S+OHbruh9-2NWhY#6YsvAQc=L1wP)Jdt$B&Uj;$xZb9eVHbxQyUmN zc=ax&>ZR^8!dsom>+me?=Q*&uA&c!2XVOm38nzM&a}JȬ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 literal 0 HcmV?d00001 diff --git a/android/x86/glslang/libglslang.a b/android/x86/glslang/libglslang.a new file mode 100644 index 0000000000000000000000000000000000000000..fc5e33ddfa0d5c378855a6b28249b18ba73ac3a6 GIT binary patch literal 2297190 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

C3o(?VU>{qne_<4UP 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

?C1REQ1luyHJ4Zf<& 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 z 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 z z95ebV{JHnJ(Sg*(pQHmhA&q7|L(QgqD9KJR3R8~W5QGyY$D|e<`qmpwP!ABpe&+2D zv}aL`8J(Nhm=bGwV@#>S+}8#z=bo1KD4Z&z-KiwfoG1apALMRRsAjc6Gm*-IC`&~d zo+onD3OtO&&6)|*YK@|)(Ut7Ib0VWREgbVVcVJ*jUt4Lz+qx#txz#oEFq5H2scM86 zLL-SyM>*6&Vw{R#{U&9SiMl%BiALC1Zz+F#?Z1E+Xij1WW|N^d(YAPRTdD(2bkGcp z7bx0j?9qeFHLN3Nq6OVh(|UB$^ufE(SvDzYrLzw2d!Y^ zhYHM=tKq$|4$SE5J)auqEeOMZdaA>}1Y#2e0CV!M|JFKZZggp8b9V8nUx<=cYKy2O_k~9hNk4?U-OURGKp?Dyh}@2>!mdYf+o{7 z(-p}?qnVS&&#(Q=K-D7np~e!%V_vH9{oyeC*;J&_fWj#=JU-F2x0+I< zjcA5MHJ}sL;D%UbjR_n#*|xQeEf>)j?!59fjnx>;c7)cIVZOR78r`yUXS4_BRd#pb zG{xkd(d~YTjv8Y}>z2VaELK*x^5*N&$!xnrDvNE6Zl=?9m4!Cb_&pCWv>ZpQA>&JQ z)R@PyihrNhXLu}9yh>^e4L-H!vO`pw+wIxiX@4h=VE}Hk3{w9O4#3tows6u+iHO8 z!CpvC4nsGQ?)?V1djKcSKGDMs8sHuR+-wtkwB`$cYQ7zq0Im=jp@$oo0PZFO+;PB} z@v+4KcX9%_{RX&^3E;kOfRnuD>HeDm&OHI#d03#V=hr&{T!jJ74>&3d;u86`(EwNF zHHYgrz(oLOmT!M=fZH?y+%F7pJ%F1dX_ugHCJL0E-+KUuKlKuDegoV?0790imw>y) z05(kinDV;3~)OQa6MQcP3LfkOYrfC5e|z$*V7N7#|PmOSEB#HJ77MFngg#oUoS(0d9U~vh!xyVdCeaF`-d*~YB zo-x23xD9Y7>CUw0vfp0zvwO%gn9!X+*lN#W9jBrVuy9?QiOW^xo98QqlgH1ak z0tk1(`tJ<*1^`EUA&N`jtAvrz)3^V#lEn5pz-_umlK#pB?gA8QJ$>#yS{Ws9fv?s8=LH5+!+JhJ%GDNh0^G|(UH%`Lx6+HRxg2Xy8-S1;4CVXhVQ!uxPb}aUNXQPp8)P- zuwj&rP`Q(UyV4}x8x3&o&uMW8T=3Cpfb#;5@QX{peaisn2b`H)o;Sc%O#pX38X%}v zVH8J}uGauJ064bqp@F`e(C*jsv1vcf0M{v&z&8)= zem&gDKf*f&81UV1fE&5roZnv>;Jjav*xrLid_^!4`gAw_u_Up*1r6!;7~mfIswA;} z1r2b2k4AGz^yUB`M+Ua?|;Dn_YmMpOz^#6fIAL2p9x$cHlWeVMZ!itW^m00I6vTy znc(||0Z#f;?JRl%7jk*Y0OtqXjVAbJqu;5guLp2!KRgaA@GUXGReej6*uHlLxOM~F z{y)QhTap~V!$tnLx%~PKaQ8gI z_i;1O_c?DqzLWnTNq1@Ns&f970dCVlb3MKE%6xqL0at2*Z@mF-0C3luzT<0Cy5_v?rRl1itqTaQh!K@24!eCZE0mz?t#8%K#@muI*JuX^V7! zYJl@j02e6EPqzwiGX)bmd^-(rkqO`)H^6P00B!~p3DxwC9+(1in`caFL_Ro?=G0au{vBTt)!* zz5v2q;7b_co<_ZI)c^(D5d&P+kI=3&p|9!s{B-?4mL#^{7e^`Zy=#Em|196H%K(RC zFBu=@Jp8^BI9p+sMjw$t|6LrefPeD;40}mxVCwh=PC8}q0?z((N%ES&{iy-27;rWd zxRVCB(h1-$xgkGYKj8HJ6oGq{0j_-lxHN|oS@i(m&{b0}ku?t);QktLA`b{yz&&b! z`##`4ref3Jo;T2U6mWJOoZ#aP1Ke@IIZWVa&qks_*y{$kfeGLi zqG0IdC;h^l-%bNu1>lNI(tW}J7Xh5$k-)|CZ#f*q!>(q)%@&z}5PGElS2!F4!q08L z6i>=sM0uaXiTvFJxZ{-?tVoyOg|5(7|AiLGuIo4oe32g7+Mukhr>Cs@2Cvr}m|t1B zaNffCl>x7Jz8^o{azB2&0l$AiMTOT}xzLYax;D+ZJKR`nu?S4WM*-tSP_q+#2f7r! zDwZzGlO)Euo7SyOzw9_gFt_e`g2>Gzecsr&3h^X|eD)z$^9#+euiQK$a zz`733s@pq|`b}Ug`!|GM0cF1c97~-YOGzqlUHU0|dhFWX-wxH5qQNdHqPP*FNZHd* zIyOdcz3mBxI9HfEKX*xP9>f>nDLHadW@S;|)5!vPr8l$Efu}-UVtCBV?t41*t|C-@ z#Idi>x0II6c*1H~GGovxZJqJBRqC_M_@Pz$w&mmhXqA3yah|YB_gK$=)+&A3x?NFN zP&YPanJXQI431g~e`=L}VcDnX0>T~Cx%W9%Nq!~s0WI>oRG;5!UKbCAd@NsaXM)Gw zO_3OP@)4**A!r^;`UJo3^qCP?`ZPe~!OSjSeWt@#l|FM`;(Yn2bQD=(&nA7uus>HP zKbszMr~iE<{jz=CTKUHc%GZ#Q46i%=tVQ1Cvl9}z(dR(6tVTMGYvpGY$YG$4P`2Bg z5&%8fMj#LQysKB=EQoQC;$~J9Wp4JC92tF;itnp=U!3x!pDbm04+$XQLN!$dg-!=Z zV(Qfde)Yo6K%}zG$0D&G6_OtOOO;n~7x}d~4@J_q-gVG9I%rASGb?SG?e<*3iQ!rZ zsJZWH2+#BQQ{O1slPr`+pl`0n+<|xF@BWcRvQ#ysUdyboF&J<1;_T|NzGHH;&zHO) z_^kYHuPgAJeCF-faO z5aBG(lRleVsK}ebuS9sJQ|kMDrqSnh^(}!tBf&v+He|w-GthY(*)Ntk^053=rq(Wp z-LJdcGhcVj4cjxd4mn&nRI3ya#VjhtIaBMF!yfswwxKZMBbn;LD#*p#_uLz<-Nd`J z+0`|$*_Au|x@!aeZy9*QfjwUY*KHFQUGEkVhofe&rD8Z_ZdV zwnKdb$@4OHc?H!Dk=&=`f6CT4GRqtYkZ*Tn=E%11Ltpv^=xg$-OqDIWe5~(hNk{O- z-Z{{RH{|0v>y<|bPg)`N<^qdMbTyAv6@Jemm-Vl-$s_3}7gOmvY*P{#Cg$i;>Zd$= zg{UD2rRp)Nf753y$+_A3vA)5i9qcK&b|lkn3%;^_E-@=FRsx5a_NB8F=e>enXEr?6 zcgl7D02#HM9l6e`Fk~~UX^=Ck3OBpf9z~8Eb*&pfjzGj4>pV=(Ldsr9*$XLqK$7R4 zT|kk%G=0X}dwIRyz&s`+fPpBRQgzc1YdD|ZUeMWm=(a#WyWuZ!f)U2 zligX{-x3szioC&B6dBuLXS9$Roh5hMhUg>svm`&xQbm2^8nW%7z^dR=sn;`g4k`ry z28yz)9P*LOdRzA9vA)wN=#Hc>nCtxnl;Fj;-;#fVjCbS;hgk1rsE*ai!+(QlSNn8TwIweLo?<%imVBI$24776OU|W6x$-yy zj)57U{6uC}dhr7&^c9Fp?7^0KGc)@Jkd1B-4JKR%H`?W2p7{Of6BfC{XHU*T9SbOX zcI9l`isiQv&4cQ}Ef2X4R@oo6B(KPiaXqN5JKoI(P0eHGO&T#4vqNzBIfC z0Q<9b_9|e9nij(rt#qf#V2SKfa(Uos76DA1RohRJ{w zRACO@WWj4OvZ-$%Rg{?po2ki39 z^pm!Yw?3f~iwE=aQxCgDBCE>WWy{pq<-wA72H&v;Uvs6ufH+W^LYOd=gPbY~9(C0WB1@le?Ttfq zGc^vx_GKO4Ai{u_goC^)RKzuyE&P7^eLISrCvlDZ#_;C>r0D?Fy0buKddMc5 zoAgM-O;2yQ?yefakCYzprU%cYUJX*C3E)XLecn&$ThoVa%TsS5HD9)H4@mjUA)uOE9uY<28TC%o# z(I)UD*2`}pCp;y&zyPJ!IOD9`Xg!-AI2(Kd?GxBx5^2`a&k{r$K;g~V5a^NZ@>ZK1 zK`UHoiNR>2g)2#cr-vU#e#j@%zdj=$efvd_QJi&h5G~nV-yh+nn6b)! z-f(q??mOvnH{Lhmn(O!?Boq4L2n2)1#YhNntQJ0$*jLc z$siX$Z+~nKNTycM%#1(%yZ2WHUr6kdPn5j&gIADr$?L&muFriB5I=ksuY2DA-PqXO zJ1(<~g16$}k6pE|{qQ_|Ouv6#uRVRlo&Md3{1%GN&GM149*0^>43T9D`AQ=wQl;zE z;NAB0GpLH?5ke-fv>mazq+At9NzKmgwDdifnw|4zcG~-%OI{2FYglA7+@Due`ZU$w zXqsOnjY^i(OzF9PcdkH=*hF_p-_cpz+S2Y#(uVRkNxQGSdgCXrEiSqKx+S|x%NE~s z!>4Xsbn9)O`Rr92B>ie&N!iRxx^9Vd{SxWgCDIK`q^p-mH{B#HUMzj`lhUqT(#DN= zU4r)|(kGWlyOu~Bmq<&NNLK<1p@?_Ablr8*qD7Ljv%SRjrI+HHrC101NyH>9TgM~Y zRvEuodAV7l-D@RfUs;K5N()MQ6Y=gYsja&=hM!Jsyb^DXlMk{KOGxUDuu?SI*swAj zjpCuUp;38Q8(!1Yuxcd&`AP)jmPC~fU7u5K5;LE8-pk+n`2Ajf-^cGvyYYM>XYEm7DY>e*ZGRvvw+;@8|EB+Gp1v^ZTFk`?vZ1FZlhh`Tb#j z|6lz6m;C-${Qfum{vCd2%^5s@m%slVzaQXt(s#Q4Ub#vCo8KSdcT6F&>ma|6TU>#F zyag3`%Ote%Ks%35H~ljUuI_5@?T)v5i|3b@`~4N=UfNc!-P_&e?VVS#U|wagt;EYV zw)ArS@K%=j%NBZzw*fU&^V-W7wzsym1X^3m%PWKP7yA8`3jzyE&Ixx%$M#O|ytaA4 zd7EPkTNcK!e$BtRwWXq^ZQ=YDf1sshLFK&mg)Q@2u|sz|P^;`UHm+Tv@RHcxRYJ00 zLp!)z?us<7ku1CHv%XHjmtN|y+4@maJ%kr#lyRqb8}3s6861YQJX*@6Rb|p0WzubB zQj|{R@u{a*?KIAiG3?oktuV3W%`}dT zF~l?7>sQ$tV1nI)|F9A8A2tI1zp(N0A2tHUQfbqTfVD;6w31ril>eZ6noh87FIM&I z*Er{|V4ZR=-v76^C;sqD-t#xZ<5o0p6}P&)cqKON(j8^BfOX&!Snc`$;JW7j%B7@i zy%tsFY!(%F)}Fv!T&#VJm$~@Y!&Tv(+Rx&0^9S7E3fnNPn5^yI-oK*NYD zE`j?p#Mi?e$B49*4$uO1V-X!(HI(G{9{FT)PR}*9>sS0jJM9f$s+fI5);% z%+?YZ*WTUpF?0IvnUT-O0l={~9;Z>H`)dvdR|Ix_&xtl634mYpNdF@o4q{~2fD3D> zbZ{V_T^B+A6fE@04TU6~6qkrnVSu|5K!PTM6>t#)TmW!jMZE-EoWlwFssKlNBrZYU zJ_B4m;2Z)7cLDdX0j_xhxMK#mO@I?P2(5U2nZx;cTJ3-{^BsAM!*MXFQxp^)Ao!gD z{iSCi=N`bF5zHf8q)RZmU}@`xnEgOpaS43tv5nk)WGdg0z=BGDrI)U$eMkJ38Ai@Gr=b47@x5aCUW0NV5Xtf zzoTR@m|Q4-m69gjfWyvaC^0L0M3Kq}K^(EULGW2X4eevHWlt~Rm#(3GBgzAwURIyZ zs84UIPogXi?IT=t4ehgWz2VGOjAyn-F#8@+x`e8hI4l>I*;KxFs1362d@W>-7puiEjN9`wpzq_0E! zgl&V8*dR2Im_{1f_XT{XYiQqoJYi&fOi{aRJxvYz}v{#*&RgC8X|E;#FMImc=qTZDloZ15pBAN*?nXebU;NM=%hY)-vHj=!Qqsdp;W=^ z{0JnbvJUOatVn-*hF8N^Aw3o0sy5Ff>Hh^CGfV7+G3LQrpONgC+qm4{Hr~`8$%^D_&aMs0Or-3 zT|@J*HhL_$rBKFP?3_KnVGzHu78HFocfLMLGuv$GL0j;RMB%t)j;>fJUXl)+hd{EEDB9Pofi zxeifFCO6{{HFV@!cktEZb^EpWh#7n@^(uL<)!Ktcldf#!Y{{{=pG*JSS<7L0t)09+ zG=Cm3jW|xejqsJQ0P;M!T6I83YXXM+ZJBz-9kbq>sV8^LxjKPxUreS{PvCbPe&ioH zAN1ISv!6%JJBnnMe{hb_RBBeHu367W_U{G|EyD_7a34LVigF>9BFup+1yuQ#yf#yH zHe=5;6hrJ|CzNQJ`m^BT`HThDX)Iz>0&`DkdaYJ>hN_NLa}${#RnPU6A!Y>@T<8$J5sYS$&cDn@qWf96W<_IbfmFw zW*6HtY$`e1>yRtp25euPKJ1m7?TeM*^kF!_*zKbsJ2Sa;CMK8i+c7RL6bgti^ZX!V zEwWOx1RQ?6Z&4P`og938mYCTCg}ablji$3V#{7o)P{1JoU5xPwDdb7U`0#zw%Jqk+ zud=m^CuWkTO}EMNvqI$OUC0xAcGu+jIb{_(X}$`QCX@&B{Ti+Hvf8>>@TS?_nN+`t zc8TU9_QCOGYt_PHf>+Q>b%_4Tz*yI>60GU zUTWF_!k2!>lDdFA&BoGaJU^hjYwzno9eA#9H0h@Jqg7r@>ile#w<_lf{5~)MC;P&{ z)48ThRWbaXo{~=up1A@Q#mnh;tjTK>Oz&6}Onua@Cptz4?Wwu)J7_$3u3Lu14Dfb7 zoSTa;9{E_N!ExO(y9_`2D+BDg#m5<{T`ls_*{7191cu_#!}jDH zqAb1BAti4bJ?u_8S&Y6h2AiCZHb(L26Lv}tO`;mR<){o#xnB3^6K*)N*A&vbNB$@I zbZ!od$f5ybq0;)4*OTuTcM@h|Hp@@)AG0eSgQd4i@Kf^Be`M|0YIpj{BJxv$#~{3n z=?V-cg5MD)Xw0^0JPmqx0IIU{Tq|M z;$2_MSp%cQhq4ldF~WaHx$K#0PiA!~7Cy|7t4rm>he&xwtNr%mg_&(`IF!whSG(mG zkiGE9D{vjOY}906CeNAB_pykN$Z^8;JzH;)S2|n=scA=;^Xo4nz+oUDv(3REgWK$h zYoP+}^nZ*cJ)p>)no+rNEOp^Zd7A??^C8EmSLz4F(1KuZ;!S{C^&iPyi!%}7rlqa%gY;^_C1ZTLGqz{OPjFMOA zD>_Bu=i^_{kBTug+;;i=nRSj#o#(oB_ROjxs+7^py%=qEcebuH(_NZf=Vu+r!00dy z3_QlNsm>2S=d1Bba2YltR+yOm(&$2)a%7!3WUuH)!c(J@D?i(pUi6|C6uxN1&eDTZ7;YPBaXAFYEyo0+YHK`Y4Ak>8~o zU4c5gyv`wayYXrd9)mHcNS+Uz{Z`k(5h?^ltoQCZIFNBszO7^VR+<~uc^tY~(=2zw zyuF}nJf#OzBd=8IX5}GGna%2-sp|xg%RTaks_c}(LsjS_kBxEjBTe<4l^d;iN>ja? z=p!=Gk3tT=_lq+nnbo%RZ{J@LJe|B40oP=<*@wRcZsfx!PXCaUCwMyb@9Fnmb?yBN zygW?ROSL8Erm;Vpwck=L|2X%VOtl@_NPSMvu-I>47|4aw7N+Wu+@kO@gdrk$kM=G|ShLSA#!weU2vNMnk>}ER;lQ zMz+U-ve{!lq|5nBvms>rpsVKSA(rj$P__@c)4v{3Qk6yPnwAoI;6F^dqYQg@*q{R+OYAfW@){nsUuF z*h^lcR+#m17>-Zvd6(85kOjrsgLi_1^0Tg*GiY9P?ir&viS1e25AmS(xY=-IMb_~c z#_Vk0&31g(1};GrSn%xjKtgu5b^{~wF!sz&LQ;iH5`OZvueSraUFJC@Bo!D7jOPAQ zSN0|-Xy;lUiSottW4N9K>-4V=o-Uj|&i{>Pz4MEt9vi>7`KCpS_*<+v5x)y(A$hw> zyw`MHF!O!-_;oKwARF@q2Ff1#gq2+HK+ z3gyP!FY8g{`(gInJ7b?MUC?I@JCoJUo`Ub&jDE^JlElWgfXC?5TZ*tEjz3O!6}RSt zYQ4?rV8KY7Xu&u-yGrO6A9Oyzw>j@4Vyp0oy|k3c+GrA3of_h)6CL&1aaxQ zmVWZn*(lPXL8@QScU;#iH?}v|2!Fns?)h=yQoGbyRPFTEb0i^v^rKRvi}r8H_uDn4 zH)Ws~*c3T#<#?_nWclebxjO?V`#{2H zq%a>6nzNwmF8WdBZ;X4pF0PWlrOLF3qIdZ`tQT@8y=mrf^sM36c-f?>4a2pU!%vo< zgzGyTj_rx2(yif*>+ll%FF5?R3FxrKvBh{sz_k=1w_ zU3Y8Au)I!k_@)Wqt#w)i(&KM)c%E&{-{lYwn?X2m`SJfFK?ebBh8mCWPchTtdu475pI=yWMlOTD3>L|y{TtQP4=h*5zEui4XFpqU)RVqvABPjzm`6xnQz!6QXO=h4^q3bI8L-|a)e6_i) z`vsijyH#)9V&W~yNt=Mbfbim?xUM8|-w<))#^4@L64z^q^8??nMBFKaEp=n%-@#$r zK@#fsGK8&DmcU^uKWoGCT&*>DZ|}sPAp;hDfmiwXH41#BXX3DN89dW|jz>jWc1E0$ z50f=Zc~UEFNebjgmWKq6`HA_9jVI~oYnHe&ibeNl^n-{LJv`yaaZqA$M(r8tNZFBu z493?sfg>4T&tZ>;$?*%!tC=sfIW<*v?H%>=;Qkr=AB(Xwj(I-~!fjQ{np<**n<>w% z#WpkeTZ6aYx~5=91-x%9SUl6}Hk2VB=6)L%$0P438RiJ63C7HDor8b4x=HSD4Zg!H z{z^yk3w$mf#)czfn_z}Hww%RW)BKfw#)Wh8#k0trkcntSzz{zW7{PPfnLU2Z4l?h6 z*xmNFNAT6)0uBpA^`X-1;lA;=vnWWQ9)d<^$WUVAkp5VJP8ALw(Fml#$ zkAOAoVe#s^mKOMBTV-rZ7}DX)B5)^%l3_*1wM1xlj1w0r?9`fyf&-Ozq`DqPXE)2 z_Gjcj`0p;SHwMYup3xhdD&&l9`RuCY%*p?In&j^;um9T~)&J*QUjHxOYGa8Jp>MJlH#dgTr^>xi5tlQt-R)0?8TpHcNvvX}N2F4;SJ3yu#$@!Q* zPY#1CSLI@uy8s?ShYg1LV1LeIQje- z9n-AC?1b}76M>QZAul3t*MUHyM`V*+_`sz4)xlP{E5@|&9QXdR?U}~L(-BLlMfBF!P<-db8wVgWTou-)*mn;L+;R(C zC*b7XB?6WBc3a?{z#0?#mSDkmJ_=yY_aNZpw;?mWxfVG07)7~M;4;Jgn+47fxMb)2 zwpQfi2GGe6%lf zzWV_uw)8S+nQxB;&W%0E$^6~CYJsZ)+`=UJUV(OK&i7%!vF|hjR_5Dof%Bi2+~3VU z3*6E4p4GpdCM$tD*-3JhY*R9zVBGzI!A!}iv{jsz(F*OOX8acJz=Kr zi4oxLwZQd`0Jq-)w;yoqn~TU<=6fmhggM{+*h`*eP!}(6iv^CHe6C3X_n-xi{P(f% zDwceIW`TPGaLN4axS&tW^m(Qz%KRkxzG#7K1Ki;xa9@C)FymYKx#Z>T7I3nSbpcND zjL<^uvFnExxCa22E#A>h!i^SsN8)>S1h`EWxIY5Up9J447C0}2G#T7v5KZNsA#kh# z+;S5>dPl#{3pjLh?0Ob(PzlCGFm%ncz`Y1KGhZZJtp)BkfI}4-mxS9W;3Qw(0UT6` zaY_Dt%>wrk;2=WACE=d3z|n`TWN>d;;GBSyI0&f>edlvH1`^$ul9I^=`+L{(!d&H)AVX zBQ~wP@>7D_JSl!GZ|5d86Q-s`1qU{LBvKrIn`~6YLnLo9vn$8(%xu$ywkKjwfgz)( zVDIJ)IMW?QnvTv*(=YG^|7+R{k(v}+_@rBXs01g1*LVxVC)F)&IPKfBd7XAzB82@r z*_P(^=KcpTJ_B8@9REWk^T9~^jq1)#u1xKdzE3W)4NiD9+`B*g>QE8Vr-$Ce##|qE zGh}MVW7*pNX?tylfTS=y$TQ3B#o5G6oMIDXD7RPSs6~&z1$)bUeYsuU=c3XeRU=@mOY-wyS z159*tv^OXdPUsdV5K|>@t90W8=o3CQa58CDv;;ilUpeBLC2mblhuB`wspdGj1-<@9~Bj0IJ+X-wqa2VwW zU=raz6k{A{QBeGP7sT2UVA;^!TL~>;9J_Z%E_61+k5I8!2GhbP zt_WQdK5->?S3t(m4qmTgwpEVK^drBKlH*YLm!bp68ATv79R>A@8r`rccL+rRo3s}r z&gZn(1vxJ5uqfBInmL)Jk;3w%wHOyWR(sk9?N7&idZ3MJg~?@v@BRFD%5l-6rOT>@ z{^2nM!HJdO-5#DdERUV=nUDdW3EFGgOL*tJ0cpfpx&?_zup6fLPx>394bZZA`~u1dmp>gT*xp-;xcfEs%^lDG1xAo zcG;l)!-I`#*RPN|JlL#uzl0d7>F}LFCA1LiB39Wss}_Mp)qb=H6d_LuL`67W_*W0l# zq{Jq9!?1$KQ76z)Rjb|Kr7C*IA*|$)Yt=fXk!oa}W7$xs4UEiYw)d<;$Yl&R0D72| zw1Bm_`;PewZ6Pl(U@K$#I%VC)b;pdp;Orm7Ql7U^|2)9cAna&Z&s=foN$!z66%5*ZVlV#JYS7AA6{qFAZojlrs5 zL}{Qvz`6dZh)=|!qb=^-W}o&v(TA%lQ_*<$(?2`N3&jG;3)Cl09>S5kjhiN zWU2NtC+7qtn7n7fg9)bT??Auo9U5-SaNTqG4C{_x_W}E{H)oxnS<7#!nvh?U|(l|v!pmRl}(lyj? zJ9nZQLzfXX>50^o*oOSEaS~+-P@;a%wVchSzWSW8M1Vz{U4zUJhr`Tho(F$ z#El(F%gIF-go0`W!cj%SfqSL6m(v{*LhYJW5~_#^$&J8GA~I3yQ~JR3a)?F+I)tlZ z)j*Z54M<;VPGjE@6SpcZ5#^+W09a`%83clSKDd`^r?des5rf)$OeRJtqLp}y#($vR42M}0%4mS)#@?>TcDA5|L{8;t zaxtcs^wsO*(-E3m>20KQotoLsP)--~*tSMi4C_qce#&@`P1X8&@vvK#yy|3|i%5q$ ziD>D92HgkF8k(t`q6L@pUB8;59GT>Na*A?d5^8qOnBYJ4^cTwa=r?~O* z$tg5HM>@Ci6e6FpU2t!T@``O9i%am;H}qhUZFbgq-%7D9nDAhVt@gZditQ^l@75IC z8@BO7HrpR0r{X8vEf&Nz=Q?#H!3`M zRjAdH&E;zMBJjvUj}<61-4b(^+EtFdY}imAIv9N&nI|Hk_@700B0f_7yYPuGs`o4% zjnZ#t!#>+vL%+{WbQraDh)#Rj;@DPlO=elFs3%~B~Vu-0ZF>(-tNA3NH z>@l^Ms%Ze}F$R#}Gu3zkwdkjQ|GRMCbKw)8YyVoL95aX7;C_Z`y>ti2cYm zo`wcVJHG=gv0S*SqTJ(If6TLv{0y%ZObM2VIRQFqw)s82n>#%Cg%(oKK1L^<(acsy#gv`g4C71c4Qs!z-~L?(8B`zGoz1{n2c4C-tt2B)(;2V zggKoAe2oA}lA?uHz@7gfX~;6aVl-q?im~QsqJf5m7h{f(Ga+`<&=r1kg>u|^86|iN z-ggs=8J1b>G{0h5Tuv$e1<`0i=4wV~*1z9~A<*#YF*~ONTD@l@z?ZF?zD|kOf;Qxj zNxexUYrEL$#YVNeCJjqHOE0v%jrgG<#Rm4YI#NvNHe4UxwNKk0eHt;; zM1$uOYBZlA!b zCU<*`T)3u`nNg1sTVd6ALeDK)hS#1%Z9xs6oq_>fLOyHl>Z7mQ`~F}j_i`7Fc?six zIzS_1%q~m}={T?Sq-<92+Kbl1I5JAT>sf?}-NbnHt{?FyT55tWSw|{l5W3`#EC5|n zF&1->hgjTXABK`cs-4Mjr)+pF&G0 z(SM{6G?fzVp%68O=-m`TZ79)A6r!&u(RK=j7kl1FL)^grekVyV74`&j zVqxBQQ{NbG4?13wUqP?Yab}PkI2tN*`Gy#IjnM?5`&T5O5zKvGW`PxI_csvGM>D>3 zKK%fSgvF6AiZho&>x=ktkmOSJ9`x%&dRMp&fVMY>4u<>oqYf;vaQR2e&E3TW>-0t{ z_nrah!Z=V&4WAea=AnxYUKKuZF^=pZeN*YnEVX99RPxr-Y*Fm49B3D?D6hX{PNuT+ z5zzjaP3`s{w+JmxkmiFg3}7uRjQjwJlttA`*aBX*!LjHk$5<0SIEb};wYv~nk`xXB z?<7v;?!zM+FpG9Oj<;J-9IIp_l~N|Cq&`qh>=Z1g_PSU#1hf{i(VvtS%zX*MH~VY}dylD8NYA>?K7YdIz8q_+o{?GwVsU+VlEzUU`BKAFY#f7B{&_+ zF)|~$2KmH7^K^jDTma% zXcViR#4HFOq<)IXZ|34V1_h?%zJO9=h!DCQ6_&Q%8>@SUqK)j@t65fvLRO;yGpgfS zZBTyuYW|@TNnfWIdbLx1r|@l48<_A~5xn7Uzk<{oP0ulrLdFBUL`$MS1|g=N!BA;{ zbuV4I2)D|m@#zpdxbNpQ5aa33j|FpI0k;S-x*8T4tb@1bjrb5UkIxI2t~-vNq;RN> zmcuiQ<)qQ{g@koIOOd>=dR;2kzmG2k7y}V&<=WD8ttCU<0cy6s^pBu5`lI(*=BNjZ z%ve4}+9{5xny1&^FfyUuN94lQW%VLUKH5p>N8}>1c!;vN9$CbrsB4SnQ`GySRf%zx zBeRH0k0Vogj%cG#j3jDQ_(G%bsLsM_SuDsO6GmBdQEVDU#zE+-XC9I{wQ_Qqi^F;{ zwA0a_96d7$JBfCxUY${(cGJj<4`-IGJ5E$+FDB5zK_!2d2~w6wI$~7`&4w2h&1xqx z1gGKIm0&K@DOd1J6ITU{Q8E=RE6J?RONaoo_)0;PjG7YI0KLJquMwG`za|UKbuGtG zkl9~SaG??_FrY~RaZWbp*=4a8Ld^j`&U1%32-?BD=T}T6!4#|HKe_UlIWvhe}1K22y z1rkbY0f?=Y5wV*R;lyfS;((E@nskINV*P?$P%y@*A5K{8f&@$~(vECcKg(GOxrNB4 zE0}{HLk-$OX=Cl)P;#+L!ba$bPMVK41Dj}Hp=%Oaxc2fH+SXFhwwB4Z1$=_rqK&7c zjgtzp3oWJ|>ONBVY3`S)BPjg|A1tGySaa=I3+4Z-)OY!pZVX!{k`S&y0VH<=Om> z!k1XyUn!pFh=H-*PDcz zHdJgq{Rp6gzOARfgFDvo5x35UkR=NT0M~>#W}!aen)dTJZ*!?^3HXv;(@EW>PFUUlv-nY)N(1(3c-W z)}S|bxnAbe?N7jmOemF(MfN+m2v$`$lD!f}aE93ceLmwSg0mvT-UAA{NZz-;QwZn; zk>BoJjwt;}Zw=iZ_g3L1EOWcO`FP+$p?1@(HJQ4TB}XMeU!$0~LqT9734otSa))IavNeSR}c6wh_~zZZRRGx8eP@WVNHOb?N6H_VSXau zs^w%K4KAVCkZDH*=3$1$u^s&avjq&#VzjV!62U^zPbqfV`&@S{TU0HrNB9Ttt(fV4 z2UG_aLcbsbH-5${hSuNRyJa@DqI}AYX&>=5oa?Ej)k9CRR#Y|gbUinYpfZ zy^1Vk1!2LZI)ha-v;4NJ-RDD#CBS!2rFkH2y|Of6lge4NY>AOMGtwo+(*hS~>nv$Z zx-P~FV_MlZzx&+C>G0WqSYA|6u6gEi%@Z209o@Q{G*;Y#M^SzbQC@~P`J?AE#mRT_ zF4LXMUE=;UY0m}!xx)P4%3tOy?<3Jm??-}>??!q*63#Ql)4p5lncPsvw34TQQv!;=lJWXx7iC`R~LRjzEjkS*Ax3*li)60y3Ew~iX*$lcrhoT^W5YuF?O+J zqlaKi#JI~9d$#n$6b>`W%hcrg*@N&Q`UqO1)`vwvKR58(tL)u|q%iQC0JGhzVny1E z;XTZUC{E>W#u0$>H5OtkJRL@g$sr_%n(iujgez+^uJRBR98^xz!;P(j>DF zgKd}|aLQCPSjD%)T&QDgv%uFTr(SN?tK0=IsF4k%quZQ%Bb_RruD#dOGq><-?H3g1 z4i&tB{X>YGoAb2}Ppm+8H$D1tho1hG&cdt5)7zjA?+N}0!AHp^+koT&9Cxp$f336d za*TRucuIzA`kfAaLtE!Yn3cK1z24ZBrZjq$=lCnO1BATbfV%L7?tSb7fLi`S-|y|I zSfbqv`$8<@-2W>SUZ2G34_%-JFDqaEC8D}|LsFo$J#-cpj18S9DE##3{PhIj!@=_~1>QCr~Xv08|p>cV3);*o0pd_+t~P z5HXNLrR*%6HXhE>gp?;I_|Dl@oJ8*!i7(T@1pYfQ+KP?kInckvEXV1f8rRu;5S{J4 zwf$M2&(t1Sv*u(N|K|31)7CxExC(mce07HljwN8s43CZL9kJ8{(Nf599<0?dhJJ3( zw=%cFvBOdDSl#K)J=t^;mZvsIGfW2TKbc4EM zi9^`5Ykk2~eZCWRz|PQW7?BpiUYufR&xkX$3N9!%#JB@(lhr=#`%iKM zVIL~VaN_P6@{^_G*ibf7z&Gy{vN>`Ll}sVab-c_O@cW25ymfG|paHEBdi5#wu6q$3 zSzyzcYPp?o>dhJU$W1nKTMB)rJ&!ntRx%Fj?Bj?|%%{dNlLkT^-t?4R2^EL;q=frZ zI8{WziYbgLQ4d-hoL1d=p?1sQz`VaO3?!0DApE>LT=RXS>D-gR14I&`AmmZ7~2EAX+#!Hf zQ-6`8Yp+VN=-hOnGB%ihedt(h7SpBfh4K}}t7W;b6dd35QS2h7O{P$v zl()09a1!bLsthoCsB)}hsGRrR#Gd$NZT};<>M#<3T~;5ISQ^838wWt-m1jb-chJoxDd~Vy|fCoZ8M8yYODG1Ob`7}g5 zHX6WG=4cmCXbbJJE%5OQ`N`O6@-K7|`4^%ja4l8Zw{sjoF>W?oOZ7{v+5lR4K9fUy z6=hN=N8Q4`l-ZTG51xg>FWEF&UdY$DA0UY8p!9Gvg0POjFW7@2^S}FG`dj#5;__LT z(7xd#-k5)3MTPvyd)FyYBrsowM?%^|>ruEDGt9~|QEQ4m3VV`lM``gFFO9a3tw2I= z8BuP1lD-K3YbWV7lQJ-?@Bu|OL*dr1%c0>8_3h2r*o4pjSmjxcMLjPTQL3vzMo!fb zHi$!tXq^XC86>g%BhFEJ$td?Y(1d*ByQ{?V2jn+2mPXTs@r93AW(=0P5NEMzDULDb zz#GJC$N7?$vD&1MPHp=LafbfnTKjbD8(Kf-Q2ZTXl{B(`IjKHqhJ3@jmcjFke(V?v zD0=xvk&^Lfoa5cp&cpl2?$GEMq8U(0_mV2{mt(qV4F4&rYoFR3qgnwH+A5Zo25tH_ zBG@Skc2tqu)B;T%i)hlA3X2fOpl?dc=pG7fR#rgt=y0iC~eX9-5GI{zZ#CtfM3_Xq!0a-`+g6E63 zm&?@j6^E?hQJP3)8tiM*+~K{Wm==;A$k@y9rZj9&e_)hR;~BJ7jXN>q)nt@RDmF+P zNuRt}|Ln0ehj`UwLeR=T3U6{@Tm3EJ-jA?U?WQGQG6&t{ax0?C%i-h*f2j}hBfMrw@Kv1 z0NGz`hY(Uz@g)G`#9|Cj(k;cu?9$F0Er&NbQ0^++P|^xGmrnBpiy2-_s|zHQUgEHn za;kh4Nynhqfx6=bP3M$_cc)|2A<5u$#^fWYT2;5kLkzlva3)k|$spL;>S=CmS*u*8lvUOiEh?^E+ZL+rXslaP-(Cx{X6I3SV0n#< zLou40RyPG}>)M-wjkneZn^vK$|4Jk~@3ES1qAi>)V@Fdt_}Igto2@ zqB3PPCz-vhYhPQhB)+A1qEC>J@KR=;7?~_v69&l)LAWGC;*zfeEo(fj4d7&3i18Dr z)80zrEAN4gZ8*#oe(1my4?FypxL)6}x~{F>(@}q0sJ>-&y~15?C>1S$Xj(JuwaBEo zsimG$3+T4?`nLAg)$jrVNng{{j(nQd*L%pBLTk{os@?;D)%9zT_o~}Hb%<+3LkqUv zQs1InB62iJC8T#v{i@K~+BW$A2sSA3)+q|x;UUC^Ydz)C4kgqAN#_M@Ze3j$Y-$Da zOOi#;_0)4#f$HYE)%Ce@{LpZL<#)Bz?kMk}{Ab#$QVdoBTOO$`cn2O-!iJCD!s{&)X_|9AZl+OZ7c74`Wi z4BgluA<-vLr!DTRs>@d7>a?ZaY$I1w+wst2D@DYn#K)96{v5#T>j-|51wLefUy}H| zY`TZA&qwki*8}){1HXsxdl+#*HB}-aYt@aqdubYAs{_HWY)yQu4K&2PG&WJ%X`PI_PmF zJ#s!%AxUVe5WP4tPlCKI5f2BT8kU$-bgM(EPTO>ac|zL`Qi;LaZS#PMBQnQ`5|;}a zOA;a2w>Pu{tN%>;7RP3OxZ{)tc6niE%9b+mbciAo+l$4QSA%fS=4+FIl$A1cvkY7> z11TF_g$rH&B3H>gS9y`EvdC36-{qSxU*9SN)vm%N46I0kRk(cDS()QoE#aGGAjQvI z${_=!EMXZSrIA4``J*GZbEV{nErkSMg~m0*kGirlc6&deK^U(OKh-b ziK}q2%O5cD9+jJ7l+mbNB>1AsU*ak$k#qshAfjH9Wr$Bm#uzfTkmbZ{*$|@?fNQKB7S+)UJPKnEhoB~#@>p@ZXV%4f<6au*VX;5YEBT8NS z9r42d3SNEpJ2ts~?O5zOi0~gB<*q}xzk}aVM+M&9;d&F{U*mVsL1|Z;!i!AdHd8p| zW+V!jBI-CYh`-d+CLLVI-w9{^>d&@?poXm1wj*%w$mQ(R|~xCfHNJ(eWySrI3BLHPDt;%E%_M-i8VKg{R3 zo$OX{bqp_;l`mhgx$*+6cR(#cD=to~C+;h@M&K(Qj?dsz>eW^b@v&u(Nc#a1WUeDA zASs6vgp10zTck-=KKeB2#6AkT*5GHa#GipTxv$%FA**?m$bdb&uiF&>uM%lzoT2Oi zYAR5%_|N7JsY!3&mZ-N=Znd&j@dN)80)N(U{MNd%TR05Y$^88Dj|2|db{Q{Ukt=)1OhVnHu>8L4nEiZDdC~~bVcU9d;G0Ow& z5&sx8u!u7GzK*7HHI)*i$hD@()mY?e4!GJ%T+IS}MS$VrNe$H1iHt+`)0KsUU4XO6 z)`}9Al+B<7Ni;d+Q!0vx6D6Lw9$QY03>TfgVSgBb#By8t*O;sh3X$w#f#)>B_NUEw zs1k&FWiGNGGRZruLgp*rprnJ+A2QODK*QBHmoN-Wh4*8K8$gEpCl;=VR(AyRmFe*Z ztP>mVuafz0&CP8tr6qd!Eba&fnwrRqR(?%YTMeziozcZ`Qf#x0<;6siGqB#^4N3-95-7Sai&zcK9;Pit|M3< zXtJg}3&m$ld&XSnh=oopBsVq8Yph>=i^-$xg6jjXT=iC`h9n3E@YX|3=Xckt}n;LE} zq7Mdj_&9N{>1OhDCH2kq38~KFD?0AnjywQ1)^#-22J7%`kNE_gBVtUB0m(hzxi}6t z>fY-7n%v0-m}l(T8OSlz(%Oy>b@gkQ7eUIuzP(~`e(mA{atfYD5%d@cNEd>&v*+4iYhuFLwG}{$%<~$WTGsG)$b!(ZVy`CMS5S z1n;&&7Ha`!z<7-iY39!!=jd-xY8%6S;0(Ae3^um6 zZm4apZ&@2`tgUZvZ*5Oh9M;bt^JZAz!&zj@f5#Kyii%90oGCi*cSBq@Rs-Hj-Diljtqs~Bu+F4z<8F55{dCf|%i8a33np{Zd;yJa8%+eLl;hfx&&+fnnx%S&pdyC*&epRx<3p}l; zj*%U!&uVB6btEYBVT7C+fgpr;I->7Hj=9rwmFbBNF>m~oLx4c;>Hod*RVR~)t+Kn4)+v?jp zT3hhJJa~KUdY>{~esZ6VUaEe2*@7ikb_DBI-=a*fZ>()-hY19YhR^AusS-_-#FAEm zpDsdRr$1a1@FO@J1;8#^;t)f0_Do9;^qY#G8LkS?9{l7*Y3N7uR&%~>c&6`^@*)_z z8u24IT4tnc`FPMo5#o~c-GOH_zLl60%kMe_D)G@KZZljb;Mlhw0>UNXP9SW~w-F05 zkIKyOP6p=!$c)cDO{|F$GF%ehZ5B9U09!xgU9{?-!{j&w%{uyEo z%YyH7NNc9gKa;Of2{0qy3JcsyEDlgQdC79LTj1INmnDI4mvG;)z&wk{=LCEV*4 zxVG71{mBC7#G;b991qX2_{I|Oehb_aBf#Bhf$JRs?imZ*{t@8bv%nn$Tr&P$h6*&7 zvB3ENwMd|p@My-?jVy3aTi|;Ad~Ha88GQL1l%P3ZUol@xvBIsg!0n%>D7020FIkR%w!)PF zp9I2P!u?smK@G5LO+Zl|fo#Z&XrkXS0S9qqm*cwRzVWKDrb_SJ$1QLkz?rf& z!oRh^c>!mxUzsL-EYBBefnCc1M}3dHh$gynEpSbMlf0n!5^lZ)?smYT3o$MU*C60z zdA9)$tTHZ1UzY{02XLlt%P8-6EpQKw05@QPdkk~as|pug9dR)d}48|L%1OH|Tc9Iqm((xHsU&X6j5mkgm_Coo`-5dcu3iQ4eD*?ldqlj`v`;yli82o|YqweQA^S z7g20%(%$5)qD|W83r9WKuwu@Rw9)n!+NUl2^T1LWuFNd^w0+zWOE#eZ9kg$N?ZqbG z7kREx+61Gw+UK@9f=l3T0_5W#`~Ki?Vm^7D2q+Qk1;%ccfj~MVI=~vhKp=yjv_K}# zsLQs6t{|#Ftly!P3fC1AMn$&*1TQj}!L~4#k9A^#8d}3V3cvieo zaFZ6A9V^F{2REoqkKFDK|M@5@nJ~}>p8^?Ft~=epldjEAr_#~RM^-w%#V4V3;WE3& zunf?NVu z#?ggKAca0jg<~nam)!-}b;p-r|BIj19xVQc%G^(X9nr)0nGt_UV)Pr_dai!EecJK9 zp|pZeI^qodJF2~%xam>P4xjRbCKPMc*k11`INAPgY@+sd%(e9t;SY_%(T#7% zX50(u#-X6zCu{{LJG|PfegBze`z_n38NLRo=V>>%!~LFuPuh>hM&JO7}|{KKqDHe_71?S4lbh+ zIzyweLCV;iLGOm2se$b`?DVG2E!dxXk-othDRZM)HeLv^CLdBBQRVLbGP_MXO4v9e z@z2{+<{^5NdkV3i5UnPU69Q^8zyKfc@wVSDSrDc)Y^$f%;*6A%qREGLA(a5#?eG{W zXiE!Y!`yoWTYSUWLO!s}Y{4!V&K83o*8Mk>y<*)n3+X@O85T@8m{?#6GJI#-!+*B- zR(#fHE4}~U+~b=lPjJ`=UD9Nq_A#9*(03{&60nh{2)`PB5I1arpZ31?Lf^@h=ddU6 z+N~#X7{*1|2bHnm`~xQn`m~qT;z4W^yLBth-&Xt`>m&A`Q&mAagg~Os^CC{TcG2uV ziZuVoj_365UbNv1?7*c4M_oQTbEq|zg6TJCNzJD<;wWYZkUM09lsmj|Wcabz_cXEb z3N31ciu!Bo^K9~PHu<&YNAP+%j(4)tDON+bwGFj7MU&5MXJ^=hiY=op_Gz#6ol1+$x50lZrWR^AjDbP~XPs&Z}R$JD+dI|dTPC*)uh;)K1!p~*}V- z7_pP@=xqGF=(%jiA(gZ*wZ`1xS5BuvhJAVj#{PN{hQibNXcC6hB=UIX(WG14z`a4~aAD?4Z=q1MZg{#NWb0G?b^m zz`;o9s9yG$fxt(M=YgaAHb^%u@Rws{M{S{uNZC;|JB?hE^(@_*0yNs98^dsG1EwLN}02;~<>Nqb08yy2j zwfWdDY_DFl)EK-2gw0M+%J9HJlqrdjHa6WFx;4JD%R_L)!didAmx1_t0vqUy{LJA`K>|-w)Uu|%6`Sd@XU&-5^X1L(;A0pzh_$wO+Gpm? zo|#{;dYWf-a~*bnt;dH1eA@BkPxnoqFe2HQHWzUrzvj$r!Q*4DMn^&PEA_Ac@C zt7gq=n6W0WepSPonX^_k%+8y+X2zT~t5($zfP2G5O~ zOUNeCbA6)ym#`}odG^rVY_lZ|)l#;Z?5ud2-6GA>5z{P4NQ0$iX8TRx|C*4-VrQ80 zRZ}`{n}un%l1Kc&HIM!b8l^EtC~{?%kPWxHOxky042C2@k^W~1>66*@ zr97I*BW_nl_0CQ`!97dhNM=jx#=C0B+JQ66R)UV_X~V^ z2%GAL+1gRf%y(s!xH18cYFQAk7R3*6`Zhz?Vfr)bHEF%=sr6&A-kq)0F*j0l6XGPo)3TY?8&G=vvD)Dif)6^d%(@SfR>>+`thM1Lz z!>WJ&O0ld>Y8exC{<0ftt5jTx6OqI;0aJkHM zaxt@!$cJ4Adkp+{4J#9{!a#^)W%eL*YO3nmJL<_$t$t&$82#Zeqe*Glb5?@6%^O3G z!GdA)CQ3fNb_A0PGj%g&klEalmLOS>nvtwOGvkmo3`bbjoO#^%4Mp_T=9)7IoQ;~< z!6hwgTRDpulH``8XJm>GC?uDM)!i9W4$J)<%pr%RIY*PoVd?&E7FpFM8iKU^{H)C) zZ(Q)d+|F(`pDn-+FRW0%nql|XRu^onSadym zzkZ?FzRbi0SPAkx$>^~DuQWD11Ci%oc${l$=I7AR%;29wE0~j?V-qzeIoH;iYfki6 znJy=!Ji7t2VVWmpCaK6IXx~}9=UK2gw>H;mq5CPM=x;*-EKWN%)V0;N!mM(2Q~T;r zGYlzL;gF$v7?P4{WgY-761dG4I5O;E^IQQd@qOC@=LZ~{(^}wMkPkC`KG-%Tqi?ANZl$n+k|fG} zw^-oXM!@$Y3*5tiGh4z)d`B#Bv}ZP%{CR}D$#(}wpwDWl~{n za(+wT67CfXTrc2g&MPkoS0m&@($@<^2{xw{fD-Oq0Vi$W(p`$uB9Y-vsOfh~z(EYz z)de`S9H9EyH3#)h@Muo#dKz#h(x$8?>| zRxOV%2ETIbmOy2x%_cDsjj0Bml+Tm@#B<~P%T{hsmdotfoxT-reWw`+4$-qTf9Udd zB1&4TZTB|fiMf;N@*V{ktkyfPZBSeK8q_UaUdnKw%j?FCE(FtAu=833Gvl#z!m0r9 z#)F=CFq;KgGICliV9Cpc2za;7{Rb2k-s8|7_jV%G-{tMX z%?5%r-04EFn};a)5Ak3m9{ff;_<#tqk8+Xi@V1K2r4M+?_FwDrK7_ZCe}~*E+LPW+ zdf<%0tB3KVZTCLPBdIWmd<;*>^-0|5LhuP5qTu5qs6F6)n!kKj#E^Sj2Qu%(GyA}b zvtsv)9FOsYwxFtW#PXA%U;$!#kgU5m@+_k|=ms5Bs@P}|6M3AKN@q@H!u<{)-i!C( z-7j$?-W|Z5E(BlXAqu_~555);9*hTnErR@mW|#Mmc#eb_x4Kvs+Oyt6hy$*71Sq~~ z=8J-T#&suai|1bgzcdhbB_*pL#Vzp~Co`f$w91tx(iK3QBvh_wXzpNsw4M-BAJG8r8W9RTAf36nGVO<3d^`VM@Dlz2A+j@1NcVeL@uS_jiaZHs;huMPUko$T9hHaY+}y@`MO1z`6+cn!KO zG$&Rep?i8jcc%7oq=|VD5+<$8z;z?{9MlE}1)ID%Z!wGZ&OPSse$*qj|De?FAgn-cxb;0^lC2yBtv_Ri{xRX$DyN6U5VBe^wz1} zZy+xEC;W|s2egJRVU&d;%r$kKKVat1?ZBgkKf~RWI@+x1r1!$jrr931TxN8<{PHusL8A(a24MSBivd z0A`p54{-Jk_S;7(ED!K}B>_Z)`a?#Ds?wyy!H9uuaA64zsLFytwfh$+U34=>LfR>~ zW+W{D8--44Krje^a_jPzLn?ufZb)R<$3YD)M^r&y@Ot4g!7E%QTm+X1R8)dSLV}V6 z#Ln=JF zBA5ZOD^vsTk}H_6qDd63^NsIz8P%iNS&SSjPp_);LxnRc|`(4Ei3md_1( zbApTT?+sPr(CsQ4{%XiHb4kB{l+rNZN3{$f8z#Xk=>CL_)iBDKjjo26YE!$vLbdk@ z{-nf$Vo&!zwTn8@f)@!`-QEva7ds((FU#pQL(p5AB2ig=R8}o|=i|`;5dcz(ppPpNrVBxmC=sj@LC}>q z4PGK&Rf{Lp)9QE0HI?6-W`fI<^Sac@%O&@5 zmNQX7EYc2xzzo}7Fo4^_LZ?Yx)Nh}}8xyM+NE~5`z)DIhazImX8lWs}(J>fZq6&S% zwfN5n)oD@5W`n7WpZB4ZBl9!ZJ`yj3rDi@p8LJ?QNJwg!d>9f!6H{^x#RMcS9P2Sa zj&|XX(dg8oM5Wrb9=45VtqANDD7V3wm%1y?0Ygc021MTi8nCjEbvOTl;WsJA3z>2h z)wEAk6C(@V&U~>)Kxj7>jiOttijZQ!MuI}sC6s1~SnA2r+DbVUfd!1L;LBhcHLwdKV^uT)C=U|AH`Au+e`)P?Q>+$fQD; z3-AmSYY0>S#^uCJRCJ%xeq_%6|BW4mP zUjgx29-C;czypWS(w0zTL9Lj^UR?i(!g`F_g7<3_bT@I?TvMGCVbs)uMwS}J|91e| zzsUe4tG%HEu{sk0!}%EuB<1BuSxior#h6A18dQxfNaMd1$dwo8S{TSxs@>)Ay2^x> zcib6}O%irQC3M^vrNSd+R|;OEr>1!wysJf)4RxOkPANFiK3RJWe$nhl1%vG_@GJvf%Z_XNp@=i!;LIKK zXYGgSCXpT<~bz`hOdX`Ym+yWm3N5~M1!2OE)M6wd^% z(K5l3?VP}zt-4E_uMDu|ouTb)Y<#TLVFR{Ox8xb>j`0rcT*=wlC|@C}&8BvJ?<4rI z{VM*L!?n!N!?Ay*BBFFC2D2eJjtek7`aZDMQ3;Ynh{Cr z9@0*Seg}3FTcB>}Mi&_7FwoNe1U`QRAfFEgM?)9TL=Z1X#o)!8JQ=S16Tgjd(1+(c?!8#~1lZM!a3Uh>R- zCQIqcQlHLJzLGU{N0##AtRJx@I<{}`T1C0`a}TB|ciX0aFHL#NHuX)ra@_VJ0pR`B zN|*+Nqa8R~Qy*QXD6fpZ;5Xxx_eW3u@;GIm4O^+$!FEc{G)Qr%`97A^nCi z58ISZ8?7gU4(tBG3Cj0C;rCMAJM7Ai)E^mXCn!D0uP4pfJ4$&d?e|9f1_B~EKoT_{?)qN;c`F`rX299Y8jR(6@CLgvd&!ngjkk?Yu ze`!}9O}*d+q)nZ?*RH&tx+A{{mE89ko{kjwEsa3#q_ft;gTaGbr zIh6s2`#Vls-xz1NQ+aU=%^m(Q*74yusK8sV_i^LybBV|tNV!d9@=v$HqChneS)43Qw-af zhRzFbQngYT(p$YvV(-{+e}-||au{uS25rfaCb&3E#vhrUscxdnbbZ$ObAGR|@H@!6 zER1TF>!WD+)kD258{}Y@qe)+h9ZodoEM)6#BqDsU#FoAC#a0K*E(iFmCt)T;Beh<_ z%$6?tNifpL|E#T4jvLs>l9uRb@0E}jzM@uTpe|2_I!+mqmLn-vmK+9k_d2lpbiuvl zqj4)$pDIslz_6!8FSp_5=lC-dC>2?tODgBXm?}vPqI^6mUq)eVp$*X<9-S?tBcYsQ zfgHGlY#0dSV3crYUhMPu(*t?^7=Q$PV1z;dK{x!4iL&z16$a!NYzySzR=O=PQ+=w$ zThgEfXuFeN3tWj?rZ!p+ zP+1ao$SUT!TKM^LES;h7*h0UEy~cvz@=rmY!DWUr^uyRwR3v#lF9YJv<-0jSzMu4N z!(07vZzpbsq&G(H0;>VZXxSYzGPp$==nn5tE!kcS)HnZ)6q zPtOIftHrOgH5@wQ23x??@HWCt+rR*db=utSR|M^9_t)_%`aS$@Jx!lK)cbegKXUg% z4A;YhDH80ispuI6ME7%mz*w1hkK+s!niKZyra0;dhN{zbe=}Uv`M4rs1>us!TR%17 zIBUSF$1r#J8ahV^eHFx_GI~EAMk*X+1xG0?25b)PeM6C**(n zA}$(gS1nL(Jx#XwYS&_f;nP&@-h}`Yk?0S|SVPfX;>CF% zODM>nuM$(E%)`%t5_l0kY?)b*5-X0Z6HETaUN3>?MH|G?hvu9oU|Gu++gIP+$tCMD!TKwIt8@kgBDV-U=L$bIXiFy?8{^2O-FelbaebhzIlzk z98yw&b0&PTQWVN-tg~|}sN7Y2mAxFOXmf3)q?wkV1bTxU-$Hu3Oz3Umub?q@MWS{SEVgN;MrkNHL&-OW#^&~hcQ?n? zJSxK{ae~X1&O~$qYS-Q12q>(IZHzT({g9gF5WVFja@ZK_W?Tu)W$X+simkxL;FU^n z!iWPo&c*$)F#>;Z58;+%a5Up$=gUrm)^LnY!_?_e_G0g6;`j$&B_JtnM$fQ3(vowm z6dkt%9XHZIR7zRbP|6f2cM{q|YjaR#ymLg?pf8lmSZdd=&|VV3hV=^Q4obZcEhm1m zf(@#{T6ITh4ql~4?zD-IC>iJw7WhC4q%4zl2+{5%!P{7RQ)eL64hFSLL`M*;1pC<- z75_NRiI5JNB)-#m;2t)sdmkkWO^aP?=#aSn93Wg=k9fdu zFM(3CKt1zMb@;F#OWki*6(C8jJPjoHy26mq*M(%76Vjk>Cbd}zs;R)N$Hd)F&nPH{ zDU*bbP zDwHJ^QU+Sn@nN=~gCEsSpk<|#cX1M5kh2lw(8o2>=B!|r_6d-3(<^gJMwu|vqNZbL zQC3VAm8}Uiax9>X)G7?6v79Rn)7TJHcq9g{G|Ym|nl1QwaV&?a3i`CndMT(18cpWg zLRCpfF*R)HkE*li50vd^LVqCm#IRz99*zBosuo}I5=WHD=BKE4Fy5mtEF>umZ)~)O zQnj)|bQT&Z1r!x#2K`upy#kA|o3G0~V$4>1dXAMruZ(RND8qyxreZy+jA@oKu31Lu z_Q!ai!*%!2fdF=5Uoon0Fr{G6rsqL6_VE{zPUbV!7>$M;8VHFGmRK>2KWll0``bln zq#Y9`3|lv*?}p%pZU}FL>)pi=EO_HBgf1zE$6+{^#@H5{$z?bPVH)BFFGn3`qcd|< zRSm7ru4V!XB0+Gr?uQ`;+qn)U33x+L+#v^*gnaQbct*38-a{07!`40w$*4!M>&!ff z9jc?3lb`BTtvuaSWq&QaDQVLDt@NDjIhnlBH%;(S-7)GhOa`@G2M+%nwhBsYj6Pjo zY7hU{>G@i8+JS--9hacPw?_)E)=o@|KJzYy*3%9b;A1O&Q9#OzBBi$2g=E3?XQb9n zU_jhWS~arS7X4@3u}>dju=72n+j{CxLql6OTo5U_Qo(5k^9FXp7=x@a+8yCuclh8@ zj3qG(F>T;?V{sSkMMa;FCQ7FQIhL_nK`fmxU>igfQ!!eA_9IR6q6-&j@ z1Gbm@M=Rufn#;P0SSJc2F6(;A2uH9;a3#rEPH4(FyvP9%u2+dQ#=yyNRxbR?Lwy>b z+d&c5*Tn}9IpjmxjLZ;7vVMcM0Dfi4qZ8abi*T<)8x`K2uvnz{=5bt~_AbXeIjmXK zZXHMkKFDGTss#<9%j{iudJ0~#>*J(`M#K%`#erW!GhWf zoScLyZ194}okQL41t%56w71*Sb6){I_wkQ)ypD~E)oE{MokUCtCVd#w>Ull*OjFL4 zpgtSnLMXL@H}S#gz2LNhL+zL0YtzU0q=nS@;*=h`(4;R57C1t`h?b!RWDU~G;JZ-0 zblO%1N}_!tY7CiGVJ@lQ#Jqu0`uL&@@Po1jN|~$>d5}WBxPp92^m$Hy_Yr(DCsPsF zX|?n=sIgris4MWhvG+sOeZ4z)F`|Ei=(iF5wz}*Uym|FQ^@aoL^j#Z9;rm;9Y$LU= zXF!`0K9$-&HZp%G_m%Fb`qf=yc4;4n_c%XPZ|?gLXSH~drBmZ`v$s}wJ#V3j{03b- z$jU(TEFL6gX?Aw*Aa8U;;w|<_V5s{La&iZq1&7v^Vs{4sDXw0UhvD_7U(BbU>h}I~sI@$1cue9G$i==E~aJcQ7S2Rr3wabN<+d z%>9~gTe&^FJBLR4yKs8h0QL0vKvS9yvWR-l=sZ){^bv!2C@!x5xV*{rT#|%MUjI&v zFrkBN!3mM_q3*u;M>lARR(rv_>nE^bj=&rJ3ZT_+gwlYyF2)NS(S`BplviKY z(^R3a9*mJTWhu#~?P$Tf>Rl^nwSzP1dBD(>OyBb%st1A|+x<0Y{6|5=V z;+VV65j?6*fVstFJ^e0yqBaQu`(0WF6p|ML;((;vV^cNf-P&8)E`W(>0~ZAt$=yp? zMeu&%%o?B9kM*pvd}QalcQosUVe2qTzlwTcV^ zjTdx2VT=63KG-{iPpTLz^c@SIuy@#=kDq9loS!~*hYft3qECZJ5-ST12d5z7GW|A3 z^bsn)9P|_%4*fZN>OHmVyPU5RBSp5Do93JL6gW86UW$E*FWAvZQW?*g1~XG}B3z^r zfB4j-6l?DYj`vb}YE(ZL?46 zFPUUh3|@)W$vbvl{z}%LO8vIU+i0vEl&d>bzKFiiu5WR$#Tf8V+pC?V86VnNX1kwi zD^mU!2>I!zYgiY2s_#ff?y06z^w88x|G9(VetUS=U&1F-H@vOA6#mm+AfB0#ni)91 z6w$$u1o3ry*qa=0=B;2J18(Vw@>u&eSOjK#zTMKyJ{|} zT&y0P&wGgT3f|Q|XrBQ4l%wci#zbkug!Vz!3s}Rb!34nGLo3VgP(9M*KAWsH-=-(b zbrV`A+GoIyZwXg|z3HIW+xta(v}Nm{NaItB*Iw0!np6i zA@EJx6-?EaIOn47L(P#Tj$+~^V%(wGx%g7sUK?jyukwYvbyg(ltrZAKC&dL=oTHqTr2 zGBJdpA|x9^EIiu~0&{{`)5t>zWAq>f%ILs+7&-Vba>xd4*#&#l;zJO7)QO$TbSob* z1Sb}}+wSI-slCp+{MA|g*c)Mg0%HbD-cU37+E}I=99S$V!`hWO4iBnk|1rJSZAft; zjU<)~bsxqsX>Pq`lS!~QeP-sJ$>-2M{vc{A4ZH({|Ph}G(ThxsH{G`azFvRcTlz1xoi zdn10wKp7hm4wTV=Ul}NK)9qM_4M#KMz_W5Xt1aaNb%GLGgQJ46kkj!ceUXFKaNKNa zQsxK`jDh~29%JjZ)TS+~I5=AsOZ2S{urEVfh#3O79q%MiUGi%UDP`1Set)UM2Ft1< z`vBw?Qi>T5)6z5!i%;vdJ$&?v3g?Uzn*l8I4X&U5|2F{jI?}@O3fX48s zUB8F0sXK0RXurkQkmqesa~Z+W|4)1G10P3q-HXpiYkLjL?g9ct5U>slNLZL%S+*rG zWM%KJB#>pa#l(_44aShe)RqNnta}eHc3mr@}#Gv;*ckZ2?xtg_QL)yMq<|FOQ+&TB$bI(2Z+;h+U zr!S!qhtlklnYh(pw*MM9IcW~SxNlFyjVAp%eW|Aw5We9*LVN^VtJnK;Wg>lT^w3fI zoccK%LD~i75&?43CD7wb{OLJNi>I2y`&ksGzi%&br&re1zLb6|H(wy)cLO>Ac4CuB z=wUK^Jk$%}%{a !X!V&p@s~rf--=BrQ0g7y{6I)Y{WlJ9+hW|fITZUC)mW*$B2SUUalxMRzjr!-Y$s_sD$Oi=HN9IM+Pt(cN`T`$o~*UR)9K9G6Ql^H*inJC`!TIPi_+H0AAK7%~Cv)z}tD*g`43?SLGhBTD$ zp{_#=%^@;04t4EkF9$~7^o0*-Ev|9OL*A7G#b#bsey!dy!u%86w7_JA8%uzw#YQjm zem`u2%zLf@uXZT6B76VLLvP}(|84EZ$jc#1Y46(AHG?JnBH2?fcD+b11~uW)%(yEv zb|&)y>?zn)+QH1>Gubu8u8O_L6v;p^i#ZMNkyZ5`G4efTRV^+WJ?syU`t~eVM-RK{ zp*Xy+Yaii-xWH@~J#q;Gn8~KW%<_dtwIwbn<(10}{~4THSXeZ!-|NzsxUvHi!*8T& zYhUYkv$??UXosMsZiAVHM(Q?JH;Itcr-$D_o12Q&zRITJzN2A+Y`QKNo%I%+;)fWm zXtY=avoxqR|xU6GQY$tRpH-Y&-?2dp_c! z6P!nqOHaY?fkvd{oTDZ$YSwWR;W)Tdj;br<1}vaZFAgY9>z^R z+EEitcxwy#SO06acXEG-X5V}~K0@{PKYDzGbyS6+kIwbE=2sZ08D3^giekx8cWx5hP~d5S>~nM>#(&k*h@}_S76|7#bmdusZ)C?4sWV` zH{DOqKCJ1@T}-}-+ILgG&OK14jm0qy$WIn=pF3TOe$$-r$z8rZYeMSnW#ROl@!GfH zKllW~uY^)#%TrMudBX4!ltGhK^NGk>ZlYxypNCvN*x+`VlTs`P2=S<9SCu_j^Dq4W z*opm+O*hupz6bI6B!aIq#iNqtg7iw{B{}`I9~*9e?QIO=_*46G?pd$0r{`fkki&`^YsLU=EWZ>- zw1@QZ95ZP$;~vZSBu%TyW3;rUA8tO4@NdZN(SM%xW={4&H|#$g%xCJ?ay=e}3$GLt ziBNq4%gpIm@LRCq4BU-D4!F-q7_rVOeYvs9iTsSp+cYKDoqGt|6|kwQu3@V(5Y2YuT!mVwauM0AmySK|H22 z*I@MgwnIlCgQ0A^2B0ku-iB#|K|#KUwjRJF=TtSSU;x^>EQi_7n0uH$2o)P03B0CqD5v#NY&wlGxe@6DU5T03+>N;#*vwZD zS0)k1P^T}+eIkclT%6NE3^9LS{67|V8C{hl4C*W*dk0=c*qUB~egFpo+3Ea#0oqX6TW`#M&TnO9 zlnu?O$Dk?1Yc|9y1o5iO-K^J>c>Ta>O9&=aw=$`!fTSDST|kxuOHeN5#)N5e8g+I{ z5M^A-py8opOw5ncL9)t~^gO+uCcM)`0CORjmIpF}5#JJw#2_bz-1j;UpoG^>ryEkU@Y%N0M+n4gV`X9eoEsh0qyAa1F$m9qfkfAW-*=#civh zi9NXuOsj9Av@8oPjC5$Bg{Qzm3sUK8jU@=H!GJXciaR-p#cUc=w=>0VkPLcOtC%Z} z$hl?ty`IGJZ>*(QYgB4l+_Z-06p!XcY1X}+C{>0s{dEZCy_&Ir+KzDz`hWX zq8vEF?+fV;ewL`|OZ7!=EheTo#FX5_K!iy|*sX6Vs3Bpwl+(Hp>yDtMv9QlPeNHG} zT8D}164cUxvHfu+T04^>;z?d`CC=oW<0hCkDFj!C_lrhahF_iIiyRJnSgHu5zJ^^%)7`+&luo+9=!)>T^eaExBU3a~*fBodgE2reD{8RqQ)YZEKbKSimdCbd|N zx^lEU6|7VjAt8@Rpg|m!Yset39B8QKSBkPFvZx7`r>~$yj}9VPh5XJrRAG7 zd}*+JnfzLA`O2D|2EMrA==YHi7P1;4&*O#7VC79ydTx$3^y3LxnjZFjq0wYo3k#yu z3{HnIdxw@LkkHK5jya0WszPGJ1jUN9!PwkJl7K66*Mqc$!J}(2BZ23@E@KvYkuT%2 z_7_Ea*NqxNlctOryyM2)-f>K4!o{Z>PSaPpXvp)>o0!Om?KcM=Lg|%ePF=KR=2%Rj z!*p{uK}VEi`!6+)k~E4u#+GTMF<+SW>7^6oOP+u?2U13VI_kc=^#@$ECj_=1p!o{g ztJ>SzYyHjHd(LRD`5@RHZa@c*MLlP{ps^>W=*X2`NuOc?|8>)FXE=&-Eo>W;!PdP z&qEgY|Ff_EG30%czX3gXm=@SsPp=X61lyCH!lAP9h2wG7WaGP8hxF|@Q8-0o?^D?C zrhGik3ilp0gBfU#a&{y-Qlu^{eZDv#kvX0wE~Lr_wf z^o^-h2cQMsfNvKIeq6gnF3DkzoSe$Sa)jE&Zo(DAIoc+$jB*W~<NxmUKi&6sv24>wqgVmo`}A* zp2N&-YkOpEZ^@?*eVtz!3vZi?oYgB^^5wNH=ns#OKb;v{w^94>Kad5s&=XC4+(q(A zZQ0C2N9ZxW3*!~?gda?k_M|&(s{I!D3Oq{cQ_$?DKCd(M`D{@z{BA(fnoZ~jKiAKO zZuS|IO0(co2nVW9*N)H=m;#2FzJt=VhZrLi_aqUr@@GQfu)a6l(+Rg@DqPi_?Aegom`L{b zi{bkb|2`Fb zM0+0@qPV^fpP}m+JXm?T*xQ$9Wvb5GS6o+Q&jiAZbGMo}9)44(oPNMxu9*(p`zGNY zRP)G(RFsoi+%Qc>KL{K|XDR5T>lznuQ77W;blzVqBjR+P;51QZg)YLK;<*0`&#r}& zaLeWRq>MU%cz*o1a6AI{8iaN7urK17(@clJv+|`Q;8W~a@3=RBlfCP_Av`Q)M}eEi zeFM5l92AbP%Y-~2E~QE3MwdvFWcpPeb`yPw8PZDO#~s262Mrt2#aYAhQpUpsUV;lb zghd^~R!dGs~I&0-e-8&`xIu+n}oOMuuK}zGCr?{4x;NZl)Y=~BtEar)7M$&U0Zy!q(2sW z*BW@9=6Fhg!nJD>9+{rk?er}65u^ug{)@+Ip7x5NiiAN+*VaiP2@ z<8)l8KA`qyEyr;aWr(*!5j<|?;crv8U3TUA^O{{wpgIsGg8%0@j#-msMZ!@$UE&c# zLcH##acEpLvC_3~60c=EL8%TfJWT&{Jm;(bNe>M1xK9xwc3wzzu;?>(UZCv($syW2 z1J_)Vm!C|^gCsABIsV1ohM2brI-tQDDOyAC^wQ*wte|H!G7WVi_P^KC<~IQ3 zUpf50L5I8OfNwKSowsB$?BKit=XUW9mz-;17l$yOOc(7A?fS|jT#^hIJ#EKhv`0;d z>*08Q0TGhuk#H3Mnd+@>@Yd9M7lQds-cYL@Cv0_~Si|w*SOOd*?sb2*sL@L%3fW&< z`L|j04SARCFKoEOu1@^Ap0(y_vi(JMXdlN%V^b3Cavl1uOzUbyar5-rC&!oSPthrF zbcqmgqdv5X%JgYFYVd}1Lnp_5-DKP*ZN+X$vXITSi2F2;OSXoTFR4t{daGliL}K2B zDAuCSd#j@&sKFcRvs1?kp2{8jR!e0y*;V^_Ks9nZ%=IbJ zo>a1bQ?j!Q5HV%WhK`Oza%)GjFO>k+?qnWgYifQX(bM@*I9#=^eW0r&frPtyHZ*n+ zo^Z#;_WlHrcclgzJ7O_})tbI93W!CkVw>~G!c~d-rlpJOni7fTM7XND%|@Icxwrpp zvF6TiYkg$Xy58<+a(!1%7v*YkZ+CYR`Rm!x*5AH4**}o9VMufkOA;NREJ3;M>OrOp z5j92hp~Bgk8isIqbJsvu%E(Hr#Vk3qZ1|TvouX{R^Lgo+nGM%4Tqx&(RC`ZqMGuv9 z3kstu#6j(!@;L1Ua$b}#0vr1uiJ64YZ(B(jqIAP~3FA;7GQ|+f--@#(SjBT{0Oiv= z3)iZR5=b)H0mr~FOC}N~pIc3cJlYFloRMJNh7J8ms+om&C(1Vum`}HGc4}E}ntFTt zCS@eddBZ;Daa~Xz46$7VKX1pzLKzV1g+t|2EKI$q4qLiXgjXsFfw0y1JQaj?6;e3i zsI4X!h7$xb)x#>+1=Uo}K3;bUWOGubISW~~sv+UK;5w0)Jh>z;Og1_5gw#l6iqf4V zE+4Y(ncv>mm+a|`wcOM3U|wYIF|k&K6A5dZmgwl+w5hkJv1wg67OM&+5~+>-y;~C2 zAr`CF&*O0hMY8!+<*}N@RYaCDr@yzeJ=H#^V<1&y1vcB6?(0rA-o2F3g^*>5#=C(R7m?i8-qp`I ziDVdWyI>Qvr+WLrM>1)6Xislvk_c+qOcB?`U^%rVqJ2x-LWz$H$|$J${YheA%u>0` zI)S$3zn_5erPp6Nq| zrZZ`%RH(&f=+Va3yNSuT9$b2UYVdc?gY(ovzjJ!dr39v;7pd4Tj8Ka$FppdPX7xWu zqrSl2s4qZ)pSw{Pkt`L{8gZUz)Wc8>c1dl#+pLPM3leC1YbNy?nZTV}gpEe}>>^Br ztl%O{t@wpE;{OkpO)We;q&vEL;5kVpHl@2$T}Btjt}6^iJGLVKHKn==*7zjOCHnf4 zeeM0p*n`VqCwYL8M6$IaGzIycJ754vmb5l&O;A;vhDTz+>}gpbxhTNlxN5ko#@u(0q1a{+dw5Jy2Zi7yu67nIEsZgmxuIpc6B5N8t-m; zFcfQgFpU2y{Ldx(fV!OF8jA{}o(`5*e28+iv`~{e-1#yl4TU#L({F^>RatGKb+Mt! zn0!vswXJpe3TJruA*Ic&QS@z>vIOGh6GPmPXuJnsgnpEf4kS~J_|_UrwAKR+qHxIO z)|CnJh9f!A5Sc?al-PY{V#X82q$j%U<8Efvgg&tPgDqT}l!B-iQ#Y5w)fh48Z^ux8 z;p%E+R@8%bvH$lW1-8wm-pxs3^?6iOVV319X(4J!fd5N$jKXkA7z0IYNs-}{XoQfm zigbQfuNcK?ZA0v-NyUE|KJ&(f^EG@vgJM(Xo7L!#2bmnQ|)@?87DYpH5r^TZSMt4 zf{;tQu;DFo5nVN>Ke>KRBC%oX)&$1f26}tiySq}4BsPbXIW&zR*@IbmSgV$?IQfUy|HkHEKEf_oZpY|b`^6>z_h;38KlND5}f}kdwxZ_zmnh%W1$U#%uB%4fpHWr%HufTXdR!p z1l(UsaQ=X?Mo)&j0qbt8_(H+_nl*wI_#TzuB7mcHdEydqZ%c5>jn4S)LP1;8^#hKr z#p4JCzTFbs?gIGKX?A=gfV)W$hr7U6A;BFl0Jltn3jmo@dHnwpTnKPrfq98^k4SKl z0&oka+w;*<0Pgb=+}Z+gKb7G60LRw)aS8=})mWorEsw)DJInoJ5}d!>SdS+%Ebx6z zf*S;!Rd)!u0~}7Mif;ifB9P(k=Krrq_(&Ph+B|Uye1lkjV$Db2Z0u$xfN&RZU%>hf zE8N;jzQ&Hj3b?O80b1ddIp7NgNN}emxX^8iBG$?gsK8h2vEyq299usp;rqM{7c$n! zaWE5K26ODK^c|dw_0taYeGYTht#HRt7*2e-3iHIRaEIq%9hn24|4f4G!=!q)wo1xJ z3=M-7-_x~xU77^eA5nZErJ++fUE{-V4cKs9Dppx#-pX%buu;NBL*;V$Iw zZ5gfs^6XH)8$Myr$Kc(@dMtrb;0s)1hdX$Wb3KnpaDFUGaB8PFOK`gZM{B6WCDJ`8 z!5wc_6k0DNE&(?m3tOz^F$e?X4grL_fcrxUZUk_&4oF-AZu+%$e7jd0YkXw5jS}3h zdliMPz2JZX-@NPW_y#|%C`j781l%JM++o1YGNJPM*ek*L*Es9vV-nmT;Mh7Hj#H%j zM*%y1yY5#MwjM`Gu(dD}z9(UaSkn!4 zIP-b=jRu@(n@f{+Ifa?Qu0NFEnhL<}<8W0x-XP$%@MpRaP4xc?hZCatF5sXN&5K~@ zIw8Ti*XPTWz6&@%+HZOm_(}oCmst^*30J}4M1IQwM{TLNM1JcfxDepb^q7}`+bF>; zECBZehZFQQ08Y?ONX7FW311W7toDIOSH0Pu-$B4R@$WhgC-VCg;GFUik>H*#knT1K z?ni(VG*Ldp^Z(>HkkT93I*A&l|*(aTihkhQkT|{VU)+qA~(h zq)YH3uY}<^gl`ma#U=19#>ATXWY3(AzP>rVw*>;>c{Mc)<}R356AlFCh42%o3gIUZ z4u$4dR|f)ftHV|F9tfvh3(-hgF1|0`5enk_ zzTqGX7z+Gg)-mI_ip+>xn~o2}LSxI+an0C|n)1yy_6zVY*zPQd-MRwW+nK#3I7nDq z>DHP(V{yNt>wr}MX}>zt_aWK$f^7$tP>OJ<+RAO(lf3qx0n8{sw{sZ&nZHS4U%wpgf;V^9{YJ> zGdJ3Ea$*_w6?A|41p}1*;=5}s;#YU8M(E^y-TfAhos0)*kH~l>kTJHMjF+&0G7(?_ z);GJb!@A$hh}b|rzX?3iyJ}_Tmwp??bgXWMh+~Cxeo1b3VLMB|;G=mrllJ4xa%=W! zBSDunK;DT|ekXYBduT>6-rctMCnA3HUFIi>BQG{?z3*HsIwybh^UJcFA0`AJ_UGe0 ztERkXRTR8t8UXj7;GeXBw4T>o3ye)}u%AlNpV^n|vMpAov|kmPcX>_qy<)#AQgcKL zUFb%#i}VysOLlFfUvn*be*JpUn*0KG(!o0!H1CBi6wv`+$E%pP~hpLKmcX0uct^R zyp+E!w(PO|JXW33yTuzok)z9HFlmX*rk>L}J} zrjjCJOKqEY%nz%<3y;P)+27S6zAfl55{k8i#WKleG}&D>F)T-34+_o}**@4g8M%FN zVVPuKTz`vL0p7aQb{dB4;xTyYEFQ)4dK(@3ME`oQ`h2kPzKo`|ff)jQr9o7IB zhIt8mOAunihZm;%IHbV$umsl!IHCIpRKR^hf*SF?$;7r zA2KBL9)Svcmm|Iv-yq;j{b7N-LxS5?0B(Z>_cY*yF0`hrOK`gjzAd@I&i&nTV7gHLf~Di= z+~OLKdyE@X8eprzn}89>_-V47?d)&qww(`;2%oslxBn{lXU;di+&{x+>y})cjMuR4 zZA5f$PsVZ53_8Fe5nuuSsQSC-ljQkz{=j6JU(|nnK`_6-cWZxF_z6T52YhaLOI%uA z2}29~{JoUDThk&O`0k-y;jxLjOS`*FTNJQE5PfKr{U->`;!lc__#4K;F(L$@7*sDnGOE3dk4yJSK?GYLE#b`@iM>u^;4u{2&u3 zUus(N{cE=Oo$Lqs!SBKk5=F9qL22V6A#{-mVfOPK>Dc8&M-b7T#6Ml<^1D21fSGnG z#ofol&K9>4FvmIEM!K7H7WU5sxDm+uB__P&zi{x+tmg5Gd3t0Jbn`ILccHLB2e_wr z7&99HLvYVHz&+;>c94fL%Y(=LSBJ1uJdEF18nkUAT^O!s7o{8EVOCnId6+eC4H6vj zdJPYos;@|l1)s04NX$hO^ibMj-|nfFv)H%$e9Jk)6SbCU8xIro5Fa=47b_pP@i5LN zrLd1{p6TNP03k(TvdjT%ZS)A$-}|dHHB-ebgLKI`B!9Ipx3asA9K1tf zIoETYtGEjRaGSeh|?wavcEqe!}H9%9G4wkA8zFFsJ)3%Dvo{>aHR zOo@mvh=^_N=uUT9=oml-x==YphVKzHhii}&=ck$3yqq@Y0mm9k5s#@$c;MHT-?DLHP zdC2(0ewm$!C)wvqzFcNIaae(m+CwXSPvhkU4nsEqha=-`aO9(P!uOm6M?O{2PFnH3 zCc%+U)d}A;&|{_VFyL65Psnfy`fiZmT97Df>kTjyu1TJSn<)ea2q5znpPofM{BxYmEa-;;C?Q_ zwE&Lj5SJ*ATR^mxzO{f8b|=9KI6D8t3O5KiC%){E;C2Ddi7#K3;GQmkZ%l&Q4LBzs z{J%(W#{uW$gI5r4%|`^n;zVD$1V`t9ILY&332p>%PV(F-!9}2GoaFTL5?l-5oalQ_ zf?EqXr}Frj1lI>Rh=zHI@_nDfiL_FHi<(e*U;XtUn)oN+z6H2|103t@V|AfPZ_?Jq+IgMfbC5ICT=2@ACK%$+l?{PT6vl_si5Shn! zk*+nb6t5DMcR%8aOW?b$YW`ddU6|Lo#xUkqRn0Rdm7RM|SzEV}S~a_sD-SDuB6)U~ zeag(U?%OjW=2AI+7axJa!ADPLoYJwP7a@O{$4V975DoreWQ633d+x_0j7j5+hVcl~ zYU2^cZvd__0mt>2D|5>GT`xj>i|HtOI?tUUf%h$tjg)G4@jy&$a}!66k83c|>SDds z6&}f)F7iD!qT;UlqNADjyuL+m>aFhZ{>*#$FskB?4+r$tGOfNw>s_cVjcBW)`eM(W zdx7pdiV{(L(Svs?esz@(SN4n}CPM+$ZUDdNbG{J61}$u?L1vS_T~GbasP>V%`@{ zQJqk|N{^!Sc#ah*k3PY~5@DV%s=>c1Qog6YjC?SdensiO@~f({Q>`Fk2u67TXBxX7 zR@MjDyMJBT8CBVS`FpDJ1$EGf7gv4^ls_)I=1q_CRuN6Qe#LdwXT8e%Gs?c`RlYjY zJ$Q-o^_dNd@|&5ZU%5p2yNgObbBQv1@x1R{qKtZcM?A_w&pU|3@L!|+2#-Hf-LM&c zqBbhZSBoyjiVgZaG{Gq7S*nB}(10&_ z(DRb2Y{snNXVjbU^pc8s*a*L3p66tdvfh27NcmBb=SY!qxM((!piF%6R`tevuKkIs zJ{EdiRllw-#CihN4VTMXDyCn)r%rpKNS#oz`izkb_#4%-pQ=}Wu~_|sBG2(6LU$WGT*%|ogi)4*SY zASgdqr~O7%-^|lM{30Ls$%so$Ps@zBA}{C>&kGc6UPk>l&c+sJ5vOqMbrk1g>z9-O zPHVyu&VNf0GUILy#}A_d7-N|@QJRAB9^iL2?xr^fvdbpIzskHfL-%VXL49S2&YIU( zmeCo#TW08gp`XF2>{NTgFK4y~Q4jZ`Hg7M-!{~P>9#@nbdMZIJj-t+{f@LdPRxDeN zgNB3nuf%^f-B}gNd_T0)6(o}MRImi|IqN}oDb8lTHGlkXcI%0gkrOBdV4LVW!{hmD zKfuA~{{rw5%x680BeHSSa{l1!mCpF}u+@y<^%DBRxd6rG<1?a;iMqsoY`Wq~&tb&-O{E#w5$Rdfbguz^@nSU#v&Y zXndfimJhd@ow*1ICPV!hsj zAeYzDk@u9^k@< z6OBvL7qj+^9T#mBfu*ci%VWua+}@#l{5Zp%bHdW_@i^xVzp~{BMa}cZ55c=xpKhJV zd@}B0LuDS3u9#<>vCS_gJd@|pqWz?5#AWSl4Q<4zh7qF{Mwr=$*mP#Q5u4_X8&7vp z6T~JMYfdc?QDR(%ymj01_-t?xAN8T&5N>&`u+g__#8(jww$M+6enLKR;+TbodUXDt5i%iO1otlw0nRnkWx&CM?vCaewdcteR~@GCr8!vW!iy5Z{qavOXN|{SqrTS4^%YWtp>0!&pes?IFV^Cwt}Il8o%D0mSd^iM^%}k2ovn;y zqu+2tNxD%vNnaUNax2X}aBIkW6TZ5&I+q5piRd@{Rz^DU3(F|LrLu_-=ac^|_CEOa z(ds{kH5@{I89A(${6ETk4UBYNR!K#41t^VcnK+F zLD|XatbEP)LZw-_elzQzE&90d_BNlYv8aYJZOBiVP2Wa?)p{xz(zmb$C>P9*%!mgSWpKHR@O)t<$uR7 z7gCc&pGC9!Y_J7E+~ODt*5E~N_7^`HTtiPQT}W0NuXts2qNwW_OYw&l$FiGU+L~Y) zY>LXwSD6gpW+7`fAaXaJoa!%=j|9MP&z$CRXO z6N4rD%9VXGI7rlZf)fW(3XrPomJ=uIPpIh`>&M~2$yMm}XQ)N3KLs#_zND^15bBP} zjq&;u^bNV+i5p5ALN^o~#4{vs`nVB{HwBMmB+!M&LAv8QiQKA$Eaibd+9+xzXQsZ< z&1qck>t*$9z3*`t6RZIQeB~YGzM*5qFc@DvL7fKV1gv&rqX0vbQl^H2ZB$NU0ySw{ zmU+W=F(m;trYX4k9p83kz3;~`U4+lV>drW65U!?tBEQ^<^6f#4XVla+`nKR|5Y{$4 zlD_un0wip-)%1Jl2<)0=!y~?->k*zg<=5Wxedb+|3W@^SSmqbUvn2~aSx`I0BE945 z1t}?HcfD`>3nyPtQ^jM-Z70Xo6qdfJw`s499;LR9-imG;&6N@ao{Mi=?|X4y5&z=4 z?c|Frcp3{X=E2iN@C+90;=yhaJd*`aW+dAp=na(mlfO4RnXFwW#SULCI?1Za`ThfR%P6_o&_! zY=b`ZWnKgZD7w{9ijauFz-7EvMuzvJUe={+a(6@B1+$O%Gyis6)MQo{8!|ssp$YlKiWxi$Y7jxJrci9r zO+t-|22;9EZwvsV2jAUhSuG4s9716E^WdOjO!><;cr-)HWJUtoQ1D;zCChaMM~PPo z6)CVnVnnPKLBl7r1`glQ4EP6fZe+R~QFtqGhtUe8uhS8{1i2)D6bvE@8>Gs3|{^B`%rCLYtY-$Qtp;yyQ8kPWHvN z;6gnWtjSD#@GVr?3E$FuKarO9g72(Xjk}xh;?B}A+8XMyb;CFyMa)GUW-awZ*>_Zd zYHi$6trn^25`B>yW(8W0A~IP(#lqY}`rXV#c~oCcCJO3>f8cV%Owrztp@9St87pL; zWFPiJgNk&q5E&-QORBa26~+%Ug+R%AG3y{-pG=>}qL;8@hgsv%w)nOB677_Ok#ep+ zptHSS?%U&rVx)A_GqPLNLq~JdVR`9W-C5@9$m_u2{i$ZOBfbd~+=E3eD@|hx-SbA6 ztUt}1o=8=q#NE%R$WCB9&UjA^HA*7R3M3VRi@scsx%5r$+#CkQKO3+H6dL!UIoi9K z@uJ*A2aiyU82Smd`+SS`kwv(k%t0UH^K|W9G6=)DI)lIDk}^#T(4~!oo&by>@R~h^ zC{3*y9y-^u6|1aSP=7c!LowamdtHjvy+v7&Rm4FNX03#F^`kQ zmyN4;u3WL=3SZ_=NR>CbD^8D|F6!D(-@dZ~A9kGnv#)*aqAi!I`)fy$=i&X@0pAb} zEklsXvaa7JYO*d^qoMsIUHQJ>JVqAw1MNg_E!*y=M0#eENfxJa> zj{#@7juq_hp=p_A(35$O_z$PhJ1rCHaGY_q5K{nV$p$muK2 zXe-a4!o^O2+W3j=<`d(wGc1cSX77#1m}!^YbfWfH`jClJtJ3avX^Y%IbyHq?;m=5) zI2nV5c(ESK`xoEUev|$MdxcYdCvrLqveM`wDAmlq6%vb zN;TeIn3yE}Cif5RLoKp4bn>skcnd&dQJEUdB!8~y#4s8(l)Kw}ve4>5M~D+%fWXQ9 zQ9tkO3NNp94M%3OKTzslpDTY(`n?-{N2uZPm?6qBDs5#v#-!M{=OVJ;+)%pEx4Gg& zM;B%5)XXV#5vg=yKLH=vB1DOMq^U}=E-p}kkm3gn)_qjj7x2%pIMSqGW@F?o*6F)No za&!3oCVsz;->>9%FTYPW?%=B_pIG9BR^l$I>ss?_O8n$#QK}KuhMH>{I5h%r0)dfN;? zxg;|OT&yZ^jh9R6jSXn~OEexp{eTmhZ8Q8z`ffcsqf~e6jee>juw4U2X_iohMQQrM zTDseevWY{e5D?FDqbWipYK%?QgVq(f+hFU!0QBvd{)`Ga+k5EE?_&2zB{x%_1J_*U=N~N5j#eD1Jw0#( zRe|in+fjH&zw>KUlZrQM5BNS)1pXuD^)TUb*A7qkhW-t)wbRe2zTs!^1Z(N&mvJW_ zpDXzMF~r;P{x2pb9^Z0JHhQa4JMLRN{yZ(kLW9*0@1s9+_&CgVbWAM9reU;_7yk<6 zqy>&+_bSFLDzD7<{pu+MBa}vzE5)dzKlA=YDIc&P(8Hhsi3r^G)k5g*kq}^bZ#-88 zPZ~-*m~~wRRLfSh2;=N1A{E1!gVQ~OwBNGg+eKU160&dnHb|3vCL^BJa_RaLaW!^vL8~Q3j!Q{)(y6604hPsM&s&(2+ zx!)uE6-=P^>U$REUYCuj*(UH8J%rKk$^0D``U0HphH*p)s67{z8;m30UWq1j42aeq zc9XB9mTZIUA{8SXum-Akx~?3HUWqw2!b6-l3eEi6?SD91Oyyf{wAG|vD76{cEhY`) z^@fHtJmll`B|rzSrr)?RJ9NCBI;z}jK{#fN*9VO6LE~0#+-i(lwQ-9Ww}r;7!MH_@ zTZ?gPGH$DkTPxk5lKjlG(hULPc8@XgO`#%WXEf*&&x6~7J_UnQRQ0JTpnf)wXpN%P zM@6t+ALYAemF=v*j~W#Z3JNO9O|v|Os+u@xHVox7>S>?Nz*At(48~KIzO21roH;cJ zhP=x9!Lmu#481o3)ilqPAD$e1r(k}B7-b_H?|HHZA78D&_^J<}9-9ry;N$nQz#3~{ zUMyy0#?3iqVkAu)%UuM)6};p^%W8P;i)Zcf%l!@FjiqtRNL!XEa{EXV9L_e1=!Bna zffL!N+sv^g6&XLsF~F!sYmm^|NrRJp|fh9#Y0wzHLNdCr;Wslhv@3`NrMsBh2q`^<_Nzt6X4U+oWlLw`=fEpJ>vRE>*G4Gb-1>=p4u z^Xj3IRPE4y)PT6H20RhJcV~RH9W$nJyPjy5G681q6#wiev#aF9n$6!CcKm?kXQ+)?Rrk<<8?W{`M zGo-^iHMpHs>$tsIgV9<~b>{t<{UuMt?}Lva0-h|?wiAI$t~877{wVj=Zcs=;00O{# z&X4d!ctqP?von6L>63Z^S^zrtVpjPP7fsT|l-Z$?^nuL#GrmQLd`n*h*O1t>%&8e$ zo-^4uzFW;vpV4wT^CPIoqcjFYy(2CLrI--69aB(;b|MTOwG@mfIO=B}Pt9ar*x`xo zn-LJyMloFp;{h$D!z1iNIzcuiCcA!{`WahR5|AE=`2O`~wJ$=32(~!G}0WvV85zuad-KpK})(&#LDY_2l%rC1Dna3kaYPLQD zhRrIF59xu9zXpw1Iqahcm5H=#VoO9=RnXl5r+$=KPDopiDO!Dl9^>w|7#nQN{cj63 z&h`@gAEv!f8a|nMjMz>iwR((|%AeBXlD3nh{`8F}N8P?5*2P%TMBR$P$L<60*Qwmn z{@H2I(HH44R(eOQBvlH6;GTJKV#P#DHL{mE1>5!e_@0e5p#FQv=7uDP^jJV&64h5! zt9$h@xRHg&Y1MMFL4(UCR>JxWu<|bfT*cT#It5K|Nhw@zU_f_HFtS|Li3m-(T)iUqY+O z?4x(zpyE(hB4Lpz3S$OKHa8C@h(}4yKtg^k2Hs;9Rk;=ma_`Z2%rLQHhEWx3L*h#K zq-kB0rW>gMjiG-%=D8#0Pkl~b5uF`#>$ejpx-oxa8IVUO`T{G!tES}>s{&w1#aMAV zI6EEKtr8=Tt_BMjaqNc@5tp;S*k*sgn^>-F-wy0SlIrkD(HCOnv&f_0?XTT8Fu!6H zTD-jC-P#{+FVcR9%1#}HRV^!6lB~+X_Fv>t-&ap*i#)lYfkiJuHkMDclpE!rx_W0! ziG2?OMef*u`oSHj*W3OuS7e>^Eoi5^p)c(AEgTG{yp|hE;t7DBjJLUc!~YXc=1w+- zNo#Bu6doDe4q1I_3uYz_$A#Y^gY>7S=_{*q)4oF-Qx9p)<@(Bn z`t}Guc`Dwl7_B|zTYNxY*`Td#qAsGHn$%`}WpwyuqwAGzrjg*XY;yx{p5k~=i-^EBa;B1p~tZpv{=vR1O9NNKdRn9jTdU@uO;FP8Fwb(R%`vnI5;+Lz#r+ zBBL?o=wkHPS?N&7(Rp}7MAF9o;@fJEqlJVis;GuHh;RD zPuem&sH|G)ORF=dXZ8mNABUW`ppTPVmhCOk>r3>dWsn(n7B^3j?8@Bzyx)rNyjz>C zFVo=it!MUPcm%qgB-ZRX<$`*BjlOhYw#hxA)t4e3#yhiH%3!e)Y7MA?cO1kaQs%u0 zeQ9ZG799SUvMLN^pe-%cmLgKw&Py3ZrF9hYQpH&64o2@HH09Q2OEYYa+P8eew@{S? zcBHF;x1dZ%HdNvUmfgHJ;fw7(Ivp@@BY5;J0d#Bw`YKj$sHx5NHsC{v-dnBy2A@i` zAG2!WXVqi{sz!k34=-Ovt!X9MLZOKkPi~&6;(?LH)oZCbvzB+oO3dgeU&$KaN@{#4 z3M61HHN<1cUTqXJlOE1|P@K94Q@plpfS?6X9u+SllPfF=r}jvi0Md5?N148gM(jMu z7;<;1hPS2B;r)g_WA#ekQi|5y&ZgSq>6yUpIr>kcGFr5%)HA2@EHGb|Ib3OPZ+O4* z-E!6yb*jH?b^>);r)T3PxMOd}zW$ifM^^KbZ~6N;eNe_DZfMyFOi-sA%r$lq{Mo+C z?Ke{umM+G*-dnLHcgYb-icb}!3GaAgEJsgXxSv>_A>_`(c#Kr`f6s~kCJ~mPX6UZ zC$h^=jK|MVjPdv><933@-+ThXcL?2%fR1VEuH1BHg9fxKwH_C21x)$Ajw(^M&se`= zTR-xyc3d9cHD<7ePhw;@gyPriUSmqpxLE%=U@b6^kT=iEFcj5*aS$)Ye;>+>oEU@M zNshA;7_{5GY;dH>O9LmDKo=U-YB~o~!HDQ|HgH0t#uyMeHIcr?KD0&Fq&XiJy3L&G zZd$Bm>6v7)2B@QJ$k2GstBqS>HQudfsMX^_#29pL&p8H8Cdn%+fw+r#G&0-V$af2F z$Z6xrsC!x?VyC)SNIJR_r`5WZjXz^7lZ)0q>mFoi_f z(A}v$v)Q9Ih8}+3%24xD+jJW9s*uLKOdi8tB#lLUHaw5=SQrgQX0}ZS6aEf5wSk%n zRIw&jyyf~PKdExGTOQWaMTw$xsL0Xku`#lVe?+Eq=;RwvK}ZUQP0A(@a2`!UT#d3T zvJ8n42~yb}y@Le%9OGin{vkf@Y?5IxXs*N{d~P_Ab$RtBuRpWjg&gL!GkC?EF9xfw z&PzY&)SJNX{VA7vJhu;gDhJPkj8}erc>ugJW{aRoyo`|wRP4Vp>0s=bZY{&y?+d|T zKr#zb=VF0Hbu+P&-<|xMB1PubjP>{T_6Iupli2U1XG36MV|!<^|Moyny1P5j)zg%W_$c7{Yw9AWy@@(eYVoS z4$tfGvJP+Sl-t%YQqSvW(ovfTupQ26JIXV^Zl9TDJSFRMr$g#r0<-Dg`e~|g);RwW z&#kGNb?u#rj`o3+V$J8-XhBPA?pt6}N(eV`e7tX=xo;us{ew5^qstX_n_Ioc<8ti; z6N3n29Rb|0#Xs%6w-_p=D8_aJTqe#{Ah;-f$A#m}WVmJlCvd5cwluMnW_*#LuMz1H z4#Gv(5Yl(i1JY#2DBv)K657IV+UH!E;$e_L=R_3WuR3f@NS%)#QCwV?8#m<{+z0vd z7YH|H+KxMt#~rQnMv6W^C$!kx6!W&!dE4r|tLwaL>bz^C-p;6ZW7OLn_4YM*BM;8; z17@+e1<%Xba~*qbmC1_CQMxU#%@$bk7$ZaxkhKv1Vn4x7JWF&+JSbXjPs_-s*thVT zi0&e$+VdL9=e4@d8+wRnsE&JU>bwgVc_R(p(E2%nm=~XT$RaOT(opAZV%ZB#%3f%W z5+fW7!MKhpqxs{%A5wF?4*SN2w05jitUKib+XEx<8>LNg_!=fJ(-l@(aCTO#sjY4@D z;_(>`h;Pv|OT48~Z`mTsh(9j!LUQvh9_I$0rX`L|z79_Tt_(Qb(+Cki@6S#H<4HOH zeiH%Nzb|DpLUaUyl&94ke)eSe7H>&Zj>6J-lE;biIOme_=Qw<~4c?LO_sM*ZAkG;c zKQ}qPq$7%6vd4$oKpd(TuW}rV(W7*c09eaE?mbwPuO~k$s>6G6<#ZX>LDV&p#V4oZ z2NxGp)~?j>Fq(hodIle@_!oO6I*Tut>JKBd57CZrJha9`!Xeec$GyQt-tszcCE_;W zI3isP*|T7MrB>b!!8FOT>B7U&!f~f6+bsA zj}fD-{sG4`3n&POrA{#U8sgtO@!566fH7oD(uw#)DznUuA6(V+W73q@14iY9;G=Rj z=T!o;8&>nUPP9;-{rvkc@$4d}f{CBWuT-u@e`%K)6g;939+8et@PXwPvR>nG!oWV-0fOf(z3fhA0cqe7-(N=3cp#w)%ycq^mc5FXas zW&Hs=`%&apS*QFo&}=gW$Re3K1cs@w2@u{saS+66eG+2x@Kiqc3wCa?1JKPIJ9 z&EZ$u;H7kmpcE_#Q99i`UWF}QKAroebiTyli*52Pr}K_2od|IMh{vNjq51qUS(M9u zw^P{@j#8}bqU-1MWAelihqO;S=tGn?{IB6SGI%~aj(b^sjC%w3u*L_K3mOj9@P0da zK>ZbscRQ zsfg9-tzN`>0?>5;C|YJG35{f{z+3NaKtBe(1mLB%ZVfkBMSD&>>EmIPkF)cnXpvn9 ztr9%yuv4HYe*jebINtw8cDtP?lHMp9wa2eRckgb|#W8wwE7n<+#u8y+q;@#eeQNKEUpb1wk{g|}n<$jYz?#UK?io@T<;WI@kuM6?&QDcdR z&+_jyjGxEnB%9mqEKCUV1(LSf&IKwDaR%;#=jP!Db`}(^7d$Y#%mxpZdn2vv6S|Mm zr)F=Y-Hv6m{dJw4LX;C|4C4P;5-wb~(GU1y(Vrbw{rM9Pw}8XR_Vhy*z7wd2pY23y zgDwgS@Gx%Xvao6%b`66v;2Ipl*6=VP|AeoPhjDY1;Tv)Y`vWN~fVh9b!{U^#AxESP znP~#kG!Q}XK@PM0oVu^LQk5ATFl-@_&IiEf`U()4GD`+Gw}s#z2o-(FqI;RC&1}VA zavGkZ__Vj51Fc2fg83jEa8djRFT)S6I}yco+>FOMjPU=+^;psahJ27M*UjNb(XRg1RC~umah#pm*uyq)@3(AcE@|js{2XeTfzkQR*9=5N%piX>jZE0M-GO>Y< z3~f&dIurLb&mHL7jNSD6HZMwdb$2%PZrG4?%A|}Yl^8&279d2Vl{(k=L|>}^oG_ap zE;un&78ya&Sy|HF*_klPr$91v%t3)qW|>SbHIcRnA{SdC(ZK}2qrJO3kxKS&f_z)K z?krs4xm|{swLUVCN^Zh20UfR3#DknZ6jp&~RXiGPecwIhSk>5)K8b@_xoF2)EQdX` zvazHZA@$+8{Aqb|Al;pcor@y-p8n2MSIzHB58$*Aa0hjtk&X(-2B02^Ex)I^H8nqx z=;?eY9ImpCQ8jinw}ukoaL2~>{zR(3y(=})*b$3SU@e$UoB!jK3WU&+68*hw`~HrB zRCxZmXb#WCKpH9lSlH5@+Q`{xJ*L4qA7SvZz0)W$5iy_EJq04o?@4a4^YkOh@^Z$U zYJ*{2>oKgCY~R$_(K)Z*xZ_!EKE+aG)a`2TdNa|t@FXfSXDTYAjwUvL(`BL=SCKS3QUz=VbBMU)g%Z`*P1SOWoRrI;EzuTAw1vT2u&_1(F6JpUvmKr! z(@yEd7KfSYkdx?Wtx5o1RuIsvTth&&{?3yUH6fqSTwYH_HFeC=yi~HgdxN7aOpz(k zuw(3xv{uw46779`$)3)brMb%Ibdn06imc4%7$LhK9nxB}?#3)NB2OtV6FM(_U3$H< zSjSMIHaiLFlp_=7T9-~5`fffMJ~+hwf`xKE4yuB@$67ipX2K-N zID4&FFpx|>)VqFtY%3I5O;_&#Yg1TgXIHd5$0a$s7>h*YNtlhM3AO(v$ zk&1l?ywwAb^mI7a*Y&*25n8 zP&t~HE{tMIg;m=}hSB==u5PQvnHQxgauzJX3^uUjo)00BHNBfTOB|(oilh`$*i(&O zpps89`c$j=6w#fdqE8Xag;e$PL4AIeeTtYrg6jU!)Ul7Kikw5b(S0`h6k>Lvqh9z( zt-wNkBZr<*ULkO;(tCC*czri{3(jVBogD$>z9-fHNTIsSiNMjHMvvLq6sHDmLxJY) zEKTp(u`>UGUG*32^4iIl!NS$?-u`u6ou=Ccs3jK<+$5Hsx7`Dg&%wD68wMEfJAq~4 zIbnW8q2-uEXU~VF%hlE@cU0w%wrRroz8XcWH5|ZQy*-msZamjl`}E^E(h-k{9}7F%k+WC zg+H#GD{~*B~ z#vC6$)Am<``T2`&VGRbf1^tS^(!H2mdU=4HkgA2!qvDzU&6vEI}OZ zg1(z2xWjRI*-*#-!8y)JK&=^%vLxOmYf6Jf9G&w z$oM$mL>>v8p6UN9GCs_~pgFJN5^?@Xf@{GkYarRY1e_le3as?41su(B6_TO~Neb9R!@U4H5XhD#7_NamFd#UrBHg!2Qx8-KD7fwtS#5qB*7F66w-jJ`^li z@!WO!^(F+1;%Cu6=sRn= zPk&NT*!)llZk+_@5AwO265QX&a5pLn&Ce8vQg+(E!qI^g?r362hhy~P3UxC9ph9Gh1ur8^IL%t~J$;F=up4M=b!fNOMs`?dt< zuYkSb05>7Q^#Kll<|X*D5cY5?lz4w3D8k20d#{Hv+h?IHY@z1a};8Y%ZXb z?k)*#7Ys}`FHeH|2MO*V;MjaT39b|jx6zAV87<~!Rj zKa=2E0LSLJN%&@6YNu}(;D}yv0S&uoUYa!@PXkWOc_RP;w?~584LC6m&I)%a8dNL3 zg9YFolHiU5&PfiwF2PY|(L|Y-pznkP=Pv+v2aI_ueSrdSJ0!Re;NoVgdA>X&!3_eA z&B5cag1(9pd%A~f6ouy5iA%seD8oTWpAta03%GAcaD%rS^XCMpfOB18Pj}=FKv)Dp zz{O=aOsKPfndxql;0_jm8=>f2JG31@J#8 z;Vb)8K9Bfp+I4@-;e^Zu0OxdW{GW3;ic42Tgx$;^k>9`NaDp$DfLjY)A})~+f)_lY QZ%?)=%8Q6AE`jg=0JcwPRR910 literal 0 HcmV?d00001 diff --git a/android/x86/include/SPIRV/GLSL.ext.AMD.h b/android/x86/include/SPIRV/GLSL.ext.AMD.h new file mode 100644 index 00000000..009d2f1c --- /dev/null +++ b/android/x86/include/SPIRV/GLSL.ext.AMD.h @@ -0,0 +1,108 @@ +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextAMD_H +#define GLSLextAMD_H + +static const int GLSLextAMDVersion = 100; +static const int GLSLextAMDRevision = 7; + +// SPV_AMD_shader_ballot +static const char* const E_SPV_AMD_shader_ballot = "SPV_AMD_shader_ballot"; + +enum ShaderBallotAMD { + ShaderBallotBadAMD = 0, // Don't use + + SwizzleInvocationsAMD = 1, + SwizzleInvocationsMaskedAMD = 2, + WriteInvocationAMD = 3, + MbcntAMD = 4, + + ShaderBallotCountAMD +}; + +// SPV_AMD_shader_trinary_minmax +static const char* const E_SPV_AMD_shader_trinary_minmax = "SPV_AMD_shader_trinary_minmax"; + +enum ShaderTrinaryMinMaxAMD { + ShaderTrinaryMinMaxBadAMD = 0, // Don't use + + FMin3AMD = 1, + UMin3AMD = 2, + SMin3AMD = 3, + FMax3AMD = 4, + UMax3AMD = 5, + SMax3AMD = 6, + FMid3AMD = 7, + UMid3AMD = 8, + SMid3AMD = 9, + + ShaderTrinaryMinMaxCountAMD +}; + +// SPV_AMD_shader_explicit_vertex_parameter +static const char* const E_SPV_AMD_shader_explicit_vertex_parameter = "SPV_AMD_shader_explicit_vertex_parameter"; + +enum ShaderExplicitVertexParameterAMD { + ShaderExplicitVertexParameterBadAMD = 0, // Don't use + + InterpolateAtVertexAMD = 1, + + ShaderExplicitVertexParameterCountAMD +}; + +// SPV_AMD_gcn_shader +static const char* const E_SPV_AMD_gcn_shader = "SPV_AMD_gcn_shader"; + +enum GcnShaderAMD { + GcnShaderBadAMD = 0, // Don't use + + CubeFaceIndexAMD = 1, + CubeFaceCoordAMD = 2, + TimeAMD = 3, + + GcnShaderCountAMD +}; + +// SPV_AMD_gpu_shader_half_float +static const char* const E_SPV_AMD_gpu_shader_half_float = "SPV_AMD_gpu_shader_half_float"; + +// SPV_AMD_texture_gather_bias_lod +static const char* const E_SPV_AMD_texture_gather_bias_lod = "SPV_AMD_texture_gather_bias_lod"; + +// SPV_AMD_gpu_shader_int16 +static const char* const E_SPV_AMD_gpu_shader_int16 = "SPV_AMD_gpu_shader_int16"; + +// SPV_AMD_shader_image_load_store_lod +static const char* const E_SPV_AMD_shader_image_load_store_lod = "SPV_AMD_shader_image_load_store_lod"; + +// SPV_AMD_shader_fragment_mask +static const char* const E_SPV_AMD_shader_fragment_mask = "SPV_AMD_shader_fragment_mask"; + +// SPV_AMD_gpu_shader_half_float_fetch +static const char* const E_SPV_AMD_gpu_shader_half_float_fetch = "SPV_AMD_gpu_shader_half_float_fetch"; + +#endif // #ifndef GLSLextAMD_H diff --git a/android/x86/include/SPIRV/GLSL.ext.EXT.h b/android/x86/include/SPIRV/GLSL.ext.EXT.h new file mode 100644 index 00000000..40164b61 --- /dev/null +++ b/android/x86/include/SPIRV/GLSL.ext.EXT.h @@ -0,0 +1,39 @@ +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextEXT_H +#define GLSLextEXT_H + +static const int GLSLextEXTVersion = 100; +static const int GLSLextEXTRevision = 2; + +static const char* const E_SPV_EXT_shader_stencil_export = "SPV_EXT_shader_stencil_export"; +static const char* const E_SPV_EXT_shader_viewport_index_layer = "SPV_EXT_shader_viewport_index_layer"; +static const char* const E_SPV_EXT_fragment_fully_covered = "SPV_EXT_fragment_fully_covered"; +static const char* const E_SPV_EXT_fragment_invocation_density = "SPV_EXT_fragment_invocation_density"; +static const char* const E_SPV_EXT_demote_to_helper_invocation = "SPV_EXT_demote_to_helper_invocation"; + +#endif // #ifndef GLSLextEXT_H diff --git a/android/x86/include/SPIRV/GLSL.ext.KHR.h b/android/x86/include/SPIRV/GLSL.ext.KHR.h new file mode 100644 index 00000000..d783a8f2 --- /dev/null +++ b/android/x86/include/SPIRV/GLSL.ext.KHR.h @@ -0,0 +1,51 @@ +/* +** Copyright (c) 2014-2020 The Khronos Group Inc. +** Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextKHR_H +#define GLSLextKHR_H + +static const int GLSLextKHRVersion = 100; +static const int GLSLextKHRRevision = 2; + +static const char* const E_SPV_KHR_shader_ballot = "SPV_KHR_shader_ballot"; +static const char* const E_SPV_KHR_subgroup_vote = "SPV_KHR_subgroup_vote"; +static const char* const E_SPV_KHR_device_group = "SPV_KHR_device_group"; +static const char* const E_SPV_KHR_multiview = "SPV_KHR_multiview"; +static const char* const E_SPV_KHR_shader_draw_parameters = "SPV_KHR_shader_draw_parameters"; +static const char* const E_SPV_KHR_16bit_storage = "SPV_KHR_16bit_storage"; +static const char* const E_SPV_KHR_8bit_storage = "SPV_KHR_8bit_storage"; +static const char* const E_SPV_KHR_storage_buffer_storage_class = "SPV_KHR_storage_buffer_storage_class"; +static const char* const E_SPV_KHR_post_depth_coverage = "SPV_KHR_post_depth_coverage"; +static const char* const E_SPV_KHR_vulkan_memory_model = "SPV_KHR_vulkan_memory_model"; +static const char* const E_SPV_EXT_physical_storage_buffer = "SPV_EXT_physical_storage_buffer"; +static const char* const E_SPV_KHR_physical_storage_buffer = "SPV_KHR_physical_storage_buffer"; +static const char* const E_SPV_EXT_fragment_shader_interlock = "SPV_EXT_fragment_shader_interlock"; +static const char* const E_SPV_KHR_shader_clock = "SPV_KHR_shader_clock"; +static const char* const E_SPV_KHR_non_semantic_info = "SPV_KHR_non_semantic_info"; +static const char* const E_SPV_KHR_ray_tracing = "SPV_KHR_ray_tracing"; +static const char* const E_SPV_KHR_ray_query = "SPV_KHR_ray_query"; +#endif // #ifndef GLSLextKHR_H diff --git a/android/x86/include/SPIRV/GLSL.ext.NV.h b/android/x86/include/SPIRV/GLSL.ext.NV.h new file mode 100644 index 00000000..50146da1 --- /dev/null +++ b/android/x86/include/SPIRV/GLSL.ext.NV.h @@ -0,0 +1,81 @@ +/* +** Copyright (c) 2014-2017 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextNV_H +#define GLSLextNV_H + +enum BuiltIn; +enum Decoration; +enum Op; +enum Capability; + +static const int GLSLextNVVersion = 100; +static const int GLSLextNVRevision = 11; + +//SPV_NV_sample_mask_override_coverage +const char* const E_SPV_NV_sample_mask_override_coverage = "SPV_NV_sample_mask_override_coverage"; + +//SPV_NV_geometry_shader_passthrough +const char* const E_SPV_NV_geometry_shader_passthrough = "SPV_NV_geometry_shader_passthrough"; + +//SPV_NV_viewport_array2 +const char* const E_SPV_NV_viewport_array2 = "SPV_NV_viewport_array2"; +const char* const E_ARB_shader_viewport_layer_array = "SPV_ARB_shader_viewport_layer_array"; + +//SPV_NV_stereo_view_rendering +const char* const E_SPV_NV_stereo_view_rendering = "SPV_NV_stereo_view_rendering"; + +//SPV_NVX_multiview_per_view_attributes +const char* const E_SPV_NVX_multiview_per_view_attributes = "SPV_NVX_multiview_per_view_attributes"; + +//SPV_NV_shader_subgroup_partitioned +const char* const E_SPV_NV_shader_subgroup_partitioned = "SPV_NV_shader_subgroup_partitioned"; + +//SPV_NV_fragment_shader_barycentric +const char* const E_SPV_NV_fragment_shader_barycentric = "SPV_NV_fragment_shader_barycentric"; + +//SPV_NV_compute_shader_derivatives +const char* const E_SPV_NV_compute_shader_derivatives = "SPV_NV_compute_shader_derivatives"; + +//SPV_NV_shader_image_footprint +const char* const E_SPV_NV_shader_image_footprint = "SPV_NV_shader_image_footprint"; + +//SPV_NV_mesh_shader +const char* const E_SPV_NV_mesh_shader = "SPV_NV_mesh_shader"; + +//SPV_NV_raytracing +const char* const E_SPV_NV_ray_tracing = "SPV_NV_ray_tracing"; + +//SPV_NV_shading_rate +const char* const E_SPV_NV_shading_rate = "SPV_NV_shading_rate"; + +//SPV_NV_cooperative_matrix +const char* const E_SPV_NV_cooperative_matrix = "SPV_NV_cooperative_matrix"; + +//SPV_NV_shader_sm_builtins +const char* const E_SPV_NV_shader_sm_builtins = "SPV_NV_shader_sm_builtins"; + +#endif // #ifndef GLSLextNV_H diff --git a/android/x86/include/SPIRV/GLSL.std.450.h b/android/x86/include/SPIRV/GLSL.std.450.h new file mode 100644 index 00000000..df31092b --- /dev/null +++ b/android/x86/include/SPIRV/GLSL.std.450.h @@ -0,0 +1,131 @@ +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLstd450_H +#define GLSLstd450_H + +static const int GLSLstd450Version = 100; +static const int GLSLstd450Revision = 1; + +enum GLSLstd450 { + GLSLstd450Bad = 0, // Don't use + + GLSLstd450Round = 1, + GLSLstd450RoundEven = 2, + GLSLstd450Trunc = 3, + GLSLstd450FAbs = 4, + GLSLstd450SAbs = 5, + GLSLstd450FSign = 6, + GLSLstd450SSign = 7, + GLSLstd450Floor = 8, + GLSLstd450Ceil = 9, + GLSLstd450Fract = 10, + + GLSLstd450Radians = 11, + GLSLstd450Degrees = 12, + GLSLstd450Sin = 13, + GLSLstd450Cos = 14, + GLSLstd450Tan = 15, + GLSLstd450Asin = 16, + GLSLstd450Acos = 17, + GLSLstd450Atan = 18, + GLSLstd450Sinh = 19, + GLSLstd450Cosh = 20, + GLSLstd450Tanh = 21, + GLSLstd450Asinh = 22, + GLSLstd450Acosh = 23, + GLSLstd450Atanh = 24, + GLSLstd450Atan2 = 25, + + GLSLstd450Pow = 26, + GLSLstd450Exp = 27, + GLSLstd450Log = 28, + GLSLstd450Exp2 = 29, + GLSLstd450Log2 = 30, + GLSLstd450Sqrt = 31, + GLSLstd450InverseSqrt = 32, + + GLSLstd450Determinant = 33, + GLSLstd450MatrixInverse = 34, + + GLSLstd450Modf = 35, // second operand needs an OpVariable to write to + GLSLstd450ModfStruct = 36, // no OpVariable operand + GLSLstd450FMin = 37, + GLSLstd450UMin = 38, + GLSLstd450SMin = 39, + GLSLstd450FMax = 40, + GLSLstd450UMax = 41, + GLSLstd450SMax = 42, + GLSLstd450FClamp = 43, + GLSLstd450UClamp = 44, + GLSLstd450SClamp = 45, + GLSLstd450FMix = 46, + GLSLstd450IMix = 47, // Reserved + GLSLstd450Step = 48, + GLSLstd450SmoothStep = 49, + + GLSLstd450Fma = 50, + GLSLstd450Frexp = 51, // second operand needs an OpVariable to write to + GLSLstd450FrexpStruct = 52, // no OpVariable operand + GLSLstd450Ldexp = 53, + + GLSLstd450PackSnorm4x8 = 54, + GLSLstd450PackUnorm4x8 = 55, + GLSLstd450PackSnorm2x16 = 56, + GLSLstd450PackUnorm2x16 = 57, + GLSLstd450PackHalf2x16 = 58, + GLSLstd450PackDouble2x32 = 59, + GLSLstd450UnpackSnorm2x16 = 60, + GLSLstd450UnpackUnorm2x16 = 61, + GLSLstd450UnpackHalf2x16 = 62, + GLSLstd450UnpackSnorm4x8 = 63, + GLSLstd450UnpackUnorm4x8 = 64, + GLSLstd450UnpackDouble2x32 = 65, + + GLSLstd450Length = 66, + GLSLstd450Distance = 67, + GLSLstd450Cross = 68, + GLSLstd450Normalize = 69, + GLSLstd450FaceForward = 70, + GLSLstd450Reflect = 71, + GLSLstd450Refract = 72, + + GLSLstd450FindILsb = 73, + GLSLstd450FindSMsb = 74, + GLSLstd450FindUMsb = 75, + + GLSLstd450InterpolateAtCentroid = 76, + GLSLstd450InterpolateAtSample = 77, + GLSLstd450InterpolateAtOffset = 78, + + GLSLstd450NMin = 79, + GLSLstd450NMax = 80, + GLSLstd450NClamp = 81, + + GLSLstd450Count +}; + +#endif // #ifndef GLSLstd450_H diff --git a/android/x86/include/SPIRV/GlslangToSpv.h b/android/x86/include/SPIRV/GlslangToSpv.h new file mode 100644 index 00000000..3907be43 --- /dev/null +++ b/android/x86/include/SPIRV/GlslangToSpv.h @@ -0,0 +1,61 @@ +// +// Copyright (C) 2014 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#pragma once + +#if defined(_MSC_VER) && _MSC_VER >= 1900 + #pragma warning(disable : 4464) // relative include path contains '..' +#endif + +#include "SpvTools.h" +#include "glslang/Include/intermediate.h" + +#include +#include + +#include "Logger.h" + +namespace glslang { + +void GetSpirvVersion(std::string&); +int GetSpirvGeneratorVersion(); +void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, + SpvOptions* options = nullptr); +void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger* logger, SpvOptions* options = nullptr); +void OutputSpvBin(const std::vector& spirv, const char* baseName); +void OutputSpvHex(const std::vector& spirv, const char* baseName, const char* varName); + +} diff --git a/android/x86/include/SPIRV/Logger.h b/android/x86/include/SPIRV/Logger.h new file mode 100644 index 00000000..411367c0 --- /dev/null +++ b/android/x86/include/SPIRV/Logger.h @@ -0,0 +1,83 @@ +// +// Copyright (C) 2016 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef GLSLANG_SPIRV_LOGGER_H +#define GLSLANG_SPIRV_LOGGER_H + +#include +#include + +namespace spv { + +// A class for holding all SPIR-V build status messages, including +// missing/TBD functionalities, warnings, and errors. +class SpvBuildLogger { +public: + SpvBuildLogger() {} + +#ifdef GLSLANG_WEB + void tbdFunctionality(const std::string& f) { } + void missingFunctionality(const std::string& f) { } + void warning(const std::string& w) { } + void error(const std::string& e) { errors.push_back(e); } + std::string getAllMessages() { return ""; } +#else + + // Registers a TBD functionality. + void tbdFunctionality(const std::string& f); + // Registers a missing functionality. + void missingFunctionality(const std::string& f); + + // Logs a warning. + void warning(const std::string& w) { warnings.push_back(w); } + // Logs an error. + void error(const std::string& e) { errors.push_back(e); } + + // Returns all messages accumulated in the order of: + // TBD functionalities, missing functionalities, warnings, errors. + std::string getAllMessages() const; +#endif + +private: + SpvBuildLogger(const SpvBuildLogger&); + + std::vector tbdFeatures; + std::vector missingFeatures; + std::vector warnings; + std::vector errors; +}; + +} // end spv namespace + +#endif // GLSLANG_SPIRV_LOGGER_H diff --git a/android/x86/include/SPIRV/NonSemanticDebugPrintf.h b/android/x86/include/SPIRV/NonSemanticDebugPrintf.h new file mode 100644 index 00000000..83796d75 --- /dev/null +++ b/android/x86/include/SPIRV/NonSemanticDebugPrintf.h @@ -0,0 +1,50 @@ +// Copyright (c) 2020 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and/or associated documentation files (the +// "Materials"), to deal in the Materials without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Materials, and to +// permit persons to whom the Materials are furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS +// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS +// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT +// https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +// + +#ifndef SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ +#define SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + NonSemanticDebugPrintfRevision = 1, + NonSemanticDebugPrintfRevision_BitWidthPadding = 0x7fffffff +}; + +enum NonSemanticDebugPrintfInstructions { + NonSemanticDebugPrintfDebugPrintf = 1, + NonSemanticDebugPrintfInstructionsMax = 0x7fffffff +}; + + +#ifdef __cplusplus +} +#endif + +#endif // SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ diff --git a/android/x86/include/SPIRV/SPVRemapper.h b/android/x86/include/SPIRV/SPVRemapper.h new file mode 100644 index 00000000..d6b9c346 --- /dev/null +++ b/android/x86/include/SPIRV/SPVRemapper.h @@ -0,0 +1,304 @@ +// +// Copyright (C) 2015 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef SPIRVREMAPPER_H +#define SPIRVREMAPPER_H + +#include +#include +#include +#include + +namespace spv { + +// MSVC defines __cplusplus as an older value, even when it supports almost all of 11. +// We handle that here by making our own symbol. +#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1700) +# define use_cpp11 1 +#endif + +class spirvbin_base_t +{ +public: + enum Options { + NONE = 0, + STRIP = (1<<0), + MAP_TYPES = (1<<1), + MAP_NAMES = (1<<2), + MAP_FUNCS = (1<<3), + DCE_FUNCS = (1<<4), + DCE_VARS = (1<<5), + DCE_TYPES = (1<<6), + OPT_LOADSTORE = (1<<7), + OPT_FWD_LS = (1<<8), // EXPERIMENTAL: PRODUCES INVALID SCHEMA-0 SPIRV + MAP_ALL = (MAP_TYPES | MAP_NAMES | MAP_FUNCS), + DCE_ALL = (DCE_FUNCS | DCE_VARS | DCE_TYPES), + OPT_ALL = (OPT_LOADSTORE), + + ALL_BUT_STRIP = (MAP_ALL | DCE_ALL | OPT_ALL), + DO_EVERYTHING = (STRIP | ALL_BUT_STRIP) + }; +}; + +} // namespace SPV + +#if !defined (use_cpp11) +#include +#include + +namespace spv { +class spirvbin_t : public spirvbin_base_t +{ +public: + spirvbin_t(int /*verbose = 0*/) { } + + void remap(std::vector& /*spv*/, unsigned int /*opts = 0*/) + { + printf("Tool not compiled for C++11, which is required for SPIR-V remapping.\n"); + exit(5); + } +}; + +} // namespace SPV + +#else // defined (use_cpp11) + +#include +#include +#include +#include +#include +#include +#include + +#include "spirv.hpp" +#include "spvIR.h" + +namespace spv { + +// class to hold SPIR-V binary data for remapping, DCE, and debug stripping +class spirvbin_t : public spirvbin_base_t +{ +public: + spirvbin_t(int verbose = 0) : entryPoint(spv::NoResult), largestNewId(0), verbose(verbose), errorLatch(false) + { } + + virtual ~spirvbin_t() { } + + // remap on an existing binary in memory + void remap(std::vector& spv, std::uint32_t opts = DO_EVERYTHING); + + // Type for error/log handler functions + typedef std::function errorfn_t; + typedef std::function logfn_t; + + // Register error/log handling functions (can be lambda fn / functor / etc) + static void registerErrorHandler(errorfn_t handler) { errorHandler = handler; } + static void registerLogHandler(logfn_t handler) { logHandler = handler; } + +protected: + // This can be overridden to provide other message behavior if needed + virtual void msg(int minVerbosity, int indent, const std::string& txt) const; + +private: + // Local to global, or global to local ID map + typedef std::unordered_map idmap_t; + typedef std::unordered_set idset_t; + typedef std::unordered_map blockmap_t; + + void remap(std::uint32_t opts = DO_EVERYTHING); + + // Map of names to IDs + typedef std::unordered_map namemap_t; + + typedef std::uint32_t spirword_t; + + typedef std::pair range_t; + typedef std::function idfn_t; + typedef std::function instfn_t; + + // Special Values for ID map: + static const spv::Id unmapped; // unchanged from default value + static const spv::Id unused; // unused ID + static const int header_size; // SPIR header = 5 words + + class id_iterator_t; + + // For mapping type entries between different shaders + typedef std::vector typeentry_t; + typedef std::map globaltypes_t; + + // A set that preserves position order, and a reverse map + typedef std::set posmap_t; + typedef std::unordered_map posmap_rev_t; + + // Maps and ID to the size of its base type, if known. + typedef std::unordered_map typesize_map_t; + + // handle error + void error(const std::string& txt) const { errorLatch = true; errorHandler(txt); } + + bool isConstOp(spv::Op opCode) const; + bool isTypeOp(spv::Op opCode) const; + bool isStripOp(spv::Op opCode) const; + bool isFlowCtrl(spv::Op opCode) const; + range_t literalRange(spv::Op opCode) const; + range_t typeRange(spv::Op opCode) const; + range_t constRange(spv::Op opCode) const; + unsigned typeSizeInWords(spv::Id id) const; + unsigned idTypeSizeInWords(spv::Id id) const; + + spv::Id& asId(unsigned word) { return spv[word]; } + const spv::Id& asId(unsigned word) const { return spv[word]; } + spv::Op asOpCode(unsigned word) const { return opOpCode(spv[word]); } + std::uint32_t asOpCodeHash(unsigned word); + spv::Decoration asDecoration(unsigned word) const { return spv::Decoration(spv[word]); } + unsigned asWordCount(unsigned word) const { return opWordCount(spv[word]); } + spv::Id asTypeConstId(unsigned word) const { return asId(word + (isTypeOp(asOpCode(word)) ? 1 : 2)); } + unsigned idPos(spv::Id id) const; + + static unsigned opWordCount(spirword_t data) { return data >> spv::WordCountShift; } + static spv::Op opOpCode(spirword_t data) { return spv::Op(data & spv::OpCodeMask); } + + // Header access & set methods + spirword_t magic() const { return spv[0]; } // return magic number + spirword_t bound() const { return spv[3]; } // return Id bound from header + spirword_t bound(spirword_t b) { return spv[3] = b; } + spirword_t genmagic() const { return spv[2]; } // generator magic + spirword_t genmagic(spirword_t m) { return spv[2] = m; } + spirword_t schemaNum() const { return spv[4]; } // schema number from header + + // Mapping fns: get + spv::Id localId(spv::Id id) const { return idMapL[id]; } + + // Mapping fns: set + inline spv::Id localId(spv::Id id, spv::Id newId); + void countIds(spv::Id id); + + // Return next unused new local ID. + // NOTE: boost::dynamic_bitset would be more efficient due to find_next(), + // which std::vector doens't have. + inline spv::Id nextUnusedId(spv::Id id); + + void buildLocalMaps(); + std::string literalString(unsigned word) const; // Return literal as a std::string + int literalStringWords(const std::string& str) const { return (int(str.size())+4)/4; } + + bool isNewIdMapped(spv::Id newId) const { return isMapped(newId); } + bool isOldIdUnmapped(spv::Id oldId) const { return localId(oldId) == unmapped; } + bool isOldIdUnused(spv::Id oldId) const { return localId(oldId) == unused; } + bool isOldIdMapped(spv::Id oldId) const { return !isOldIdUnused(oldId) && !isOldIdUnmapped(oldId); } + bool isFunction(spv::Id oldId) const { return fnPos.find(oldId) != fnPos.end(); } + + // bool matchType(const globaltypes_t& globalTypes, spv::Id lt, spv::Id gt) const; + // spv::Id findType(const globaltypes_t& globalTypes, spv::Id lt) const; + std::uint32_t hashType(unsigned typeStart) const; + + spirvbin_t& process(instfn_t, idfn_t, unsigned begin = 0, unsigned end = 0); + int processInstruction(unsigned word, instfn_t, idfn_t); + + void validate() const; + void mapTypeConst(); + void mapFnBodies(); + void optLoadStore(); + void dceFuncs(); + void dceVars(); + void dceTypes(); + void mapNames(); + void foldIds(); // fold IDs to smallest space + void forwardLoadStores(); // load store forwarding (EXPERIMENTAL) + void offsetIds(); // create relative offset IDs + + void applyMap(); // remap per local name map + void mapRemainder(); // map any IDs we haven't touched yet + void stripDebug(); // strip all debug info + void stripDeadRefs(); // strips debug info for now-dead references after DCE + void strip(); // remove debug symbols + + std::vector spv; // SPIR words + + namemap_t nameMap; // ID names from OpName + + // Since we want to also do binary ops, we can't use std::vector. we could use + // boost::dynamic_bitset, but we're trying to avoid a boost dependency. + typedef std::uint64_t bits_t; + std::vector mapped; // which new IDs have been mapped + static const int mBits = sizeof(bits_t) * 4; + + bool isMapped(spv::Id id) const { return id < maxMappedId() && ((mapped[id/mBits] & (1LL<<(id%mBits))) != 0); } + void setMapped(spv::Id id) { resizeMapped(id); mapped[id/mBits] |= (1LL<<(id%mBits)); } + void resizeMapped(spv::Id id) { if (id >= maxMappedId()) mapped.resize(id/mBits+1, 0); } + size_t maxMappedId() const { return mapped.size() * mBits; } + + // Add a strip range for a given instruction starting at 'start' + // Note: avoiding brace initializers to please older versions os MSVC. + void stripInst(unsigned start) { stripRange.push_back(range_t(start, start + asWordCount(start))); } + + // Function start and end. use unordered_map because we'll have + // many fewer functions than IDs. + std::unordered_map fnPos; + + // Which functions are called, anywhere in the module, with a call count + std::unordered_map fnCalls; + + posmap_t typeConstPos; // word positions that define types & consts (ordered) + posmap_rev_t idPosR; // reverse map from IDs to positions + typesize_map_t idTypeSizeMap; // maps each ID to its type size, if known. + + std::vector idMapL; // ID {M}ap from {L}ocal to {G}lobal IDs + + spv::Id entryPoint; // module entry point + spv::Id largestNewId; // biggest new ID we have mapped anything to + + // Sections of the binary to strip, given as [begin,end) + std::vector stripRange; + + // processing options: + std::uint32_t options; + int verbose; // verbosity level + + // Error latch: this is set if the error handler is ever executed. It would be better to + // use a try/catch block and throw, but that's not desired for certain environments, so + // this is the alternative. + mutable bool errorLatch; + + static errorfn_t errorHandler; + static logfn_t logHandler; +}; + +} // namespace SPV + +#endif // defined (use_cpp11) +#endif // SPIRVREMAPPER_H diff --git a/android/x86/include/SPIRV/SpvBuilder.h b/android/x86/include/SPIRV/SpvBuilder.h new file mode 100644 index 00000000..71b90d60 --- /dev/null +++ b/android/x86/include/SPIRV/SpvBuilder.h @@ -0,0 +1,838 @@ +// +// Copyright (C) 2014-2015 LunarG, Inc. +// Copyright (C) 2015-2020 Google, Inc. +// Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// "Builder" is an interface to fully build SPIR-V IR. Allocate one of +// these to build (a thread safe) internal SPIR-V representation (IR), +// and then dump it as a binary stream according to the SPIR-V specification. +// +// A Builder has a 1:1 relationship with a SPIR-V module. +// + +#pragma once +#ifndef SpvBuilder_H +#define SpvBuilder_H + +#include "Logger.h" +#include "spirv.hpp" +#include "spvIR.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace spv { + +typedef enum { + Spv_1_0 = (1 << 16), + Spv_1_1 = (1 << 16) | (1 << 8), + Spv_1_2 = (1 << 16) | (2 << 8), + Spv_1_3 = (1 << 16) | (3 << 8), + Spv_1_4 = (1 << 16) | (4 << 8), + Spv_1_5 = (1 << 16) | (5 << 8), +} SpvVersion; + +class Builder { +public: + Builder(unsigned int spvVersion, unsigned int userNumber, SpvBuildLogger* logger); + virtual ~Builder(); + + static const int maxMatrixSize = 4; + + unsigned int getSpvVersion() const { return spvVersion; } + + void setSource(spv::SourceLanguage lang, int version) + { + source = lang; + sourceVersion = version; + } + spv::Id getStringId(const std::string& str) + { + auto sItr = stringIds.find(str); + if (sItr != stringIds.end()) + return sItr->second; + spv::Id strId = getUniqueId(); + Instruction* fileString = new Instruction(strId, NoType, OpString); + const char* file_c_str = str.c_str(); + fileString->addStringOperand(file_c_str); + strings.push_back(std::unique_ptr(fileString)); + module.mapInstruction(fileString); + stringIds[file_c_str] = strId; + return strId; + } + void setSourceFile(const std::string& file) + { + sourceFileStringId = getStringId(file); + } + void setSourceText(const std::string& text) { sourceText = text; } + void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); } + void addModuleProcessed(const std::string& p) { moduleProcesses.push_back(p.c_str()); } + void setEmitOpLines() { emitOpLines = true; } + void addExtension(const char* ext) { extensions.insert(ext); } + void removeExtension(const char* ext) + { + extensions.erase(ext); + } + void addIncorporatedExtension(const char* ext, SpvVersion incorporatedVersion) + { + if (getSpvVersion() < static_cast(incorporatedVersion)) + addExtension(ext); + } + void promoteIncorporatedExtension(const char* baseExt, const char* promoExt, SpvVersion incorporatedVersion) + { + removeExtension(baseExt); + addIncorporatedExtension(promoExt, incorporatedVersion); + } + void addInclude(const std::string& name, const std::string& text) + { + spv::Id incId = getStringId(name); + includeFiles[incId] = &text; + } + Id import(const char*); + void setMemoryModel(spv::AddressingModel addr, spv::MemoryModel mem) + { + addressModel = addr; + memoryModel = mem; + } + + void addCapability(spv::Capability cap) { capabilities.insert(cap); } + + // To get a new for anything needing a new one. + Id getUniqueId() { return ++uniqueId; } + + // To get a set of new s, e.g., for a set of function parameters + Id getUniqueIds(int numIds) + { + Id id = uniqueId + 1; + uniqueId += numIds; + return id; + } + + // Generate OpLine for non-filename-based #line directives (ie no filename + // seen yet): Log the current line, and if different than the last one, + // issue a new OpLine using the new line and current source file name. + void setLine(int line); + + // If filename null, generate OpLine for non-filename-based line directives, + // else do filename-based: Log the current line and file, and if different + // than the last one, issue a new OpLine using the new line and file + // name. + void setLine(int line, const char* filename); + // Low-level OpLine. See setLine() for a layered helper. + void addLine(Id fileName, int line, int column); + + // For creating new types (will return old type if the requested one was already made). + Id makeVoidType(); + Id makeBoolType(); + Id makePointer(StorageClass, Id pointee); + Id makeForwardPointer(StorageClass); + Id makePointerFromForwardPointer(StorageClass, Id forwardPointerType, Id pointee); + Id makeIntegerType(int width, bool hasSign); // generic + Id makeIntType(int width) { return makeIntegerType(width, true); } + Id makeUintType(int width) { return makeIntegerType(width, false); } + Id makeFloatType(int width); + Id makeStructType(const std::vector& members, const char*); + Id makeStructResultType(Id type0, Id type1); + Id makeVectorType(Id component, int size); + Id makeMatrixType(Id component, int cols, int rows); + Id makeArrayType(Id element, Id sizeId, int stride); // 0 stride means no stride decoration + Id makeRuntimeArray(Id element); + Id makeFunctionType(Id returnType, const std::vector& paramTypes); + Id makeImageType(Id sampledType, Dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format); + Id makeSamplerType(); + Id makeSampledImageType(Id imageType); + Id makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols); + + // accelerationStructureNV type + Id makeAccelerationStructureType(); + // rayQueryEXT type + Id makeRayQueryType(); + + // For querying about types. + Id getTypeId(Id resultId) const { return module.getTypeId(resultId); } + Id getDerefTypeId(Id resultId) const; + Op getOpCode(Id id) const { return module.getInstruction(id)->getOpCode(); } + Op getTypeClass(Id typeId) const { return getOpCode(typeId); } + Op getMostBasicTypeClass(Id typeId) const; + int getNumComponents(Id resultId) const { return getNumTypeComponents(getTypeId(resultId)); } + int getNumTypeConstituents(Id typeId) const; + int getNumTypeComponents(Id typeId) const { return getNumTypeConstituents(typeId); } + Id getScalarTypeId(Id typeId) const; + Id getContainedTypeId(Id typeId) const; + Id getContainedTypeId(Id typeId, int) const; + StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); } + ImageFormat getImageTypeFormat(Id typeId) const + { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); } + + bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); } + bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); } + bool isVector(Id resultId) const { return isVectorType(getTypeId(resultId)); } + bool isMatrix(Id resultId) const { return isMatrixType(getTypeId(resultId)); } + bool isCooperativeMatrix(Id resultId)const { return isCooperativeMatrixType(getTypeId(resultId)); } + bool isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); } + bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); } + + bool isBoolType(Id typeId) + { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); } + bool isIntType(Id typeId) const + { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; } + bool isUintType(Id typeId) const + { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; } + bool isFloatType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat; } + bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; } + bool isScalarType(Id typeId) const + { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt || + getTypeClass(typeId) == OpTypeBool; } + bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; } + bool isMatrixType(Id typeId) const { return getTypeClass(typeId) == OpTypeMatrix; } + bool isStructType(Id typeId) const { return getTypeClass(typeId) == OpTypeStruct; } + bool isArrayType(Id typeId) const { return getTypeClass(typeId) == OpTypeArray; } +#ifdef GLSLANG_WEB + bool isCooperativeMatrixType(Id typeId)const { return false; } +#else + bool isCooperativeMatrixType(Id typeId)const { return getTypeClass(typeId) == OpTypeCooperativeMatrixNV; } +#endif + bool isAggregateType(Id typeId) const + { return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); } + bool isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; } + bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; } + bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; } + bool containsType(Id typeId, Op typeOp, unsigned int width) const; + bool containsPhysicalStorageBufferOrArray(Id typeId) const; + + bool isConstantOpCode(Op opcode) const; + bool isSpecConstantOpCode(Op opcode) const; + bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); } + bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; } + bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); } + unsigned int getConstantScalar(Id resultId) const + { return module.getInstruction(resultId)->getImmediateOperand(0); } + StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); } + + int getScalarTypeWidth(Id typeId) const + { + Id scalarTypeId = getScalarTypeId(typeId); + assert(getTypeClass(scalarTypeId) == OpTypeInt || getTypeClass(scalarTypeId) == OpTypeFloat); + return module.getInstruction(scalarTypeId)->getImmediateOperand(0); + } + + int getTypeNumColumns(Id typeId) const + { + assert(isMatrixType(typeId)); + return getNumTypeConstituents(typeId); + } + int getNumColumns(Id resultId) const { return getTypeNumColumns(getTypeId(resultId)); } + int getTypeNumRows(Id typeId) const + { + assert(isMatrixType(typeId)); + return getNumTypeComponents(getContainedTypeId(typeId)); + } + int getNumRows(Id resultId) const { return getTypeNumRows(getTypeId(resultId)); } + + Dim getTypeDimensionality(Id typeId) const + { + assert(isImageType(typeId)); + return (Dim)module.getInstruction(typeId)->getImmediateOperand(1); + } + Id getImageType(Id resultId) const + { + Id typeId = getTypeId(resultId); + assert(isImageType(typeId) || isSampledImageType(typeId)); + return isSampledImageType(typeId) ? module.getInstruction(typeId)->getIdOperand(0) : typeId; + } + bool isArrayedImageType(Id typeId) const + { + assert(isImageType(typeId)); + return module.getInstruction(typeId)->getImmediateOperand(3) != 0; + } + + // For making new constants (will return old constant if the requested one was already made). + Id makeBoolConstant(bool b, bool specConstant = false); + Id makeInt8Constant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); } + Id makeUint8Constant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(8), u, specConstant); } + Id makeInt16Constant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(16), (unsigned)i, specConstant); } + Id makeUint16Constant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(16), u, specConstant); } + Id makeIntConstant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); } + Id makeUintConstant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(32), u, specConstant); } + Id makeInt64Constant(long long i, bool specConstant = false) + { return makeInt64Constant(makeIntType(64), (unsigned long long)i, specConstant); } + Id makeUint64Constant(unsigned long long u, bool specConstant = false) + { return makeInt64Constant(makeUintType(64), u, specConstant); } + Id makeFloatConstant(float f, bool specConstant = false); + Id makeDoubleConstant(double d, bool specConstant = false); + Id makeFloat16Constant(float f16, bool specConstant = false); + Id makeFpConstant(Id type, double d, bool specConstant = false); + + // Turn the array of constants into a proper spv constant of the requested type. + Id makeCompositeConstant(Id type, const std::vector& comps, bool specConst = false); + + // Methods for adding information outside the CFG. + Instruction* addEntryPoint(ExecutionModel, Function*, const char* name); + void addExecutionMode(Function*, ExecutionMode mode, int value1 = -1, int value2 = -1, int value3 = -1); + void addName(Id, const char* name); + void addMemberName(Id, int member, const char* name); + void addDecoration(Id, Decoration, int num = -1); + void addDecoration(Id, Decoration, const char*); + void addDecorationId(Id id, Decoration, Id idDecoration); + void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1); + void addMemberDecoration(Id, unsigned int member, Decoration, const char*); + + // At the end of what block do the next create*() instructions go? + void setBuildPoint(Block* bp) { buildPoint = bp; } + Block* getBuildPoint() const { return buildPoint; } + + // Make the entry-point function. The returned pointer is only valid + // for the lifetime of this builder. + Function* makeEntryPoint(const char*); + + // Make a shader-style function, and create its entry block if entry is non-zero. + // Return the function, pass back the entry. + // The returned pointer is only valid for the lifetime of this builder. + Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, + const std::vector& paramTypes, const std::vector>& precisions, Block **entry = 0); + + // Create a return. An 'implicit' return is one not appearing in the source + // code. In the case of an implicit return, no post-return block is inserted. + void makeReturn(bool implicit, Id retVal = 0); + + // Generate all the code needed to finish up a function. + void leaveFunction(); + + // Create a discard. + void makeDiscard(); + + // Create a global or function local or IO variable. + Id createVariable(StorageClass, Id type, const char* name = 0, Id initializer = NoResult); + + // Create an intermediate with an undefined value. + Id createUndefined(Id type); + + // Store into an Id and return the l-value + void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + + // Load from an Id and return it + Id createLoad(Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + + // Create an OpAccessChain instruction + Id createAccessChain(StorageClass, Id base, const std::vector& offsets); + + // Create an OpArrayLength instruction + Id createArrayLength(Id base, unsigned int member); + + // Create an OpCooperativeMatrixLengthNV instruction + Id createCooperativeMatrixLength(Id type); + + // Create an OpCompositeExtract instruction + Id createCompositeExtract(Id composite, Id typeId, unsigned index); + Id createCompositeExtract(Id composite, Id typeId, const std::vector& indexes); + Id createCompositeInsert(Id object, Id composite, Id typeId, unsigned index); + Id createCompositeInsert(Id object, Id composite, Id typeId, const std::vector& indexes); + + Id createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex); + Id createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex); + + void createNoResultOp(Op); + void createNoResultOp(Op, Id operand); + void createNoResultOp(Op, const std::vector& operands); + void createNoResultOp(Op, const std::vector& operands); + void createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask); + void createMemoryBarrier(unsigned executionScope, unsigned memorySemantics); + Id createUnaryOp(Op, Id typeId, Id operand); + Id createBinOp(Op, Id typeId, Id operand1, Id operand2); + Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3); + Id createOp(Op, Id typeId, const std::vector& operands); + Id createOp(Op, Id typeId, const std::vector& operands); + Id createFunctionCall(spv::Function*, const std::vector&); + Id createSpecConstantOp(Op, Id typeId, const std::vector& operands, const std::vector& literals); + + // Take an rvalue (source) and a set of channels to extract from it to + // make a new rvalue, which is returned. + Id createRvalueSwizzle(Decoration precision, Id typeId, Id source, const std::vector& channels); + + // Take a copy of an lvalue (target) and a source of components, and set the + // source components into the lvalue where the 'channels' say to put them. + // An updated version of the target is returned. + // (No true lvalue or stores are used.) + Id createLvalueSwizzle(Id typeId, Id target, Id source, const std::vector& channels); + + // If both the id and precision are valid, the id + // gets tagged with the requested precision. + // The passed in id is always the returned id, to simplify use patterns. + Id setPrecision(Id id, Decoration precision) + { + if (precision != NoPrecision && id != NoResult) + addDecoration(id, precision); + + return id; + } + + // Can smear a scalar to a vector for the following forms: + // - promoteScalar(scalar, vector) // smear scalar to width of vector + // - promoteScalar(vector, scalar) // smear scalar to width of vector + // - promoteScalar(pointer, scalar) // smear scalar to width of what pointer points to + // - promoteScalar(scalar, scalar) // do nothing + // Other forms are not allowed. + // + // Generally, the type of 'scalar' does not need to be the same type as the components in 'vector'. + // The type of the created vector is a vector of components of the same type as the scalar. + // + // Note: One of the arguments will change, with the result coming back that way rather than + // through the return value. + void promoteScalar(Decoration precision, Id& left, Id& right); + + // Make a value by smearing the scalar to fill the type. + // vectorType should be the correct type for making a vector of scalarVal. + // (No conversions are done.) + Id smearScalar(Decoration precision, Id scalarVal, Id vectorType); + + // Create a call to a built-in function. + Id createBuiltinCall(Id resultType, Id builtins, int entryPoint, const std::vector& args); + + // List of parameters used to create a texture operation + struct TextureParameters { + Id sampler; + Id coords; + Id bias; + Id lod; + Id Dref; + Id offset; + Id offsets; + Id gradX; + Id gradY; + Id sample; + Id component; + Id texelOut; + Id lodClamp; + Id granularity; + Id coarse; + bool nonprivate; + bool volatil; + }; + + // Select the correct texture operation based on all inputs, and emit the correct instruction + Id createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, + bool noImplicit, const TextureParameters&, ImageOperandsMask); + + // Emit the OpTextureQuery* instruction that was passed in. + // Figure out the right return value and type, and return it. + Id createTextureQueryCall(Op, const TextureParameters&, bool isUnsignedResult); + + Id createSamplePositionCall(Decoration precision, Id, Id); + + Id createBitFieldExtractCall(Decoration precision, Id, Id, Id, bool isSigned); + Id createBitFieldInsertCall(Decoration precision, Id, Id, Id, Id); + + // Reduction comparison for composites: For equal and not-equal resulting in a scalar. + Id createCompositeCompare(Decoration precision, Id, Id, bool /* true if for equal, false if for not-equal */); + + // OpCompositeConstruct + Id createCompositeConstruct(Id typeId, const std::vector& constituents); + + // vector or scalar constructor + Id createConstructor(Decoration precision, const std::vector& sources, Id resultTypeId); + + // matrix constructor + Id createMatrixConstructor(Decoration precision, const std::vector& sources, Id constructee); + + // Helper to use for building nested control flow with if-then-else. + class If { + public: + If(Id condition, unsigned int ctrl, Builder& builder); + ~If() {} + + void makeBeginElse(); + void makeEndIf(); + + private: + If(const If&); + If& operator=(If&); + + Builder& builder; + Id condition; + unsigned int control; + Function* function; + Block* headerBlock; + Block* thenBlock; + Block* elseBlock; + Block* mergeBlock; + }; + + // Make a switch statement. A switch has 'numSegments' of pieces of code, not containing + // any case/default labels, all separated by one or more case/default labels. Each possible + // case value v is a jump to the caseValues[v] segment. The defaultSegment is also in this + // number space. How to compute the value is given by 'condition', as in switch(condition). + // + // The SPIR-V Builder will maintain the stack of post-switch merge blocks for nested switches. + // + // Use a defaultSegment < 0 if there is no default segment (to branch to post switch). + // + // Returns the right set of basic blocks to start each code segment with, so that the caller's + // recursion stack can hold the memory for it. + // + void makeSwitch(Id condition, unsigned int control, int numSegments, const std::vector& caseValues, + const std::vector& valueToSegment, int defaultSegment, std::vector& segmentBB); + + // Add a branch to the innermost switch's merge block. + void addSwitchBreak(); + + // Move to the next code segment, passing in the return argument in makeSwitch() + void nextSwitchSegment(std::vector& segmentBB, int segment); + + // Finish off the innermost switch. + void endSwitch(std::vector& segmentBB); + + struct LoopBlocks { + LoopBlocks(Block& head, Block& body, Block& merge, Block& continue_target) : + head(head), body(body), merge(merge), continue_target(continue_target) { } + Block &head, &body, &merge, &continue_target; + private: + LoopBlocks(); + LoopBlocks& operator=(const LoopBlocks&) = delete; + }; + + // Start a new loop and prepare the builder to generate code for it. Until + // closeLoop() is called for this loop, createLoopContinue() and + // createLoopExit() will target its corresponding blocks. + LoopBlocks& makeNewLoop(); + + // Create a new block in the function containing the build point. Memory is + // owned by the function object. + Block& makeNewBlock(); + + // Add a branch to the continue_target of the current (innermost) loop. + void createLoopContinue(); + + // Add an exit (e.g. "break") from the innermost loop that we're currently + // in. + void createLoopExit(); + + // Close the innermost loop that you're in + void closeLoop(); + + // + // Access chain design for an R-Value vs. L-Value: + // + // There is a single access chain the builder is building at + // any particular time. Such a chain can be used to either to a load or + // a store, when desired. + // + // Expressions can be r-values, l-values, or both, or only r-values: + // a[b.c].d = .... // l-value + // ... = a[b.c].d; // r-value, that also looks like an l-value + // ++a[b.c].d; // r-value and l-value + // (x + y)[2]; // r-value only, can't possibly be l-value + // + // Computing an r-value means generating code. Hence, + // r-values should only be computed when they are needed, not speculatively. + // + // Computing an l-value means saving away information for later use in the compiler, + // no code is generated until the l-value is later dereferenced. It is okay + // to speculatively generate an l-value, just not okay to speculatively dereference it. + // + // The base of the access chain (the left-most variable or expression + // from which everything is based) can be set either as an l-value + // or as an r-value. Most efficient would be to set an l-value if one + // is available. If an expression was evaluated, the resulting r-value + // can be set as the chain base. + // + // The users of this single access chain can save and restore if they + // want to nest or manage multiple chains. + // + + struct AccessChain { + Id base; // for l-values, pointer to the base object, for r-values, the base object + std::vector indexChain; + Id instr; // cache the instruction that generates this access chain + std::vector swizzle; // each std::vector element selects the next GLSL component number + Id component; // a dynamic component index, can coexist with a swizzle, + // done after the swizzle, NoResult if not present + Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied; + // NoType unless a swizzle or component is present + bool isRValue; // true if 'base' is an r-value, otherwise, base is an l-value + unsigned int alignment; // bitwise OR of alignment values passed in. Accumulates worst alignment. + // Only tracks base and (optional) component selection alignment. + + // Accumulate whether anything in the chain of structures has coherent decorations. + struct CoherentFlags { + CoherentFlags() { clear(); } +#ifdef GLSLANG_WEB + void clear() { } + bool isVolatile() const { return false; } + CoherentFlags operator |=(const CoherentFlags &other) { return *this; } +#else + bool isVolatile() const { return volatil; } + bool anyCoherent() const { + return coherent || devicecoherent || queuefamilycoherent || workgroupcoherent || + subgroupcoherent || shadercallcoherent; + } + + unsigned coherent : 1; + unsigned devicecoherent : 1; + unsigned queuefamilycoherent : 1; + unsigned workgroupcoherent : 1; + unsigned subgroupcoherent : 1; + unsigned shadercallcoherent : 1; + unsigned nonprivate : 1; + unsigned volatil : 1; + unsigned isImage : 1; + + void clear() { + coherent = 0; + devicecoherent = 0; + queuefamilycoherent = 0; + workgroupcoherent = 0; + subgroupcoherent = 0; + shadercallcoherent = 0; + nonprivate = 0; + volatil = 0; + isImage = 0; + } + + CoherentFlags operator |=(const CoherentFlags &other) { + coherent |= other.coherent; + devicecoherent |= other.devicecoherent; + queuefamilycoherent |= other.queuefamilycoherent; + workgroupcoherent |= other.workgroupcoherent; + subgroupcoherent |= other.subgroupcoherent; + shadercallcoherent |= other.shadercallcoherent; + nonprivate |= other.nonprivate; + volatil |= other.volatil; + isImage |= other.isImage; + return *this; + } +#endif + }; + CoherentFlags coherentFlags; + }; + + // + // the SPIR-V builder maintains a single active chain that + // the following methods operate on + // + + // for external save and restore + AccessChain getAccessChain() { return accessChain; } + void setAccessChain(AccessChain newChain) { accessChain = newChain; } + + // clear accessChain + void clearAccessChain(); + + // set new base as an l-value base + void setAccessChainLValue(Id lValue) + { + assert(isPointer(lValue)); + accessChain.base = lValue; + } + + // set new base value as an r-value + void setAccessChainRValue(Id rValue) + { + accessChain.isRValue = true; + accessChain.base = rValue; + } + + // push offset onto the end of the chain + void accessChainPush(Id offset, AccessChain::CoherentFlags coherentFlags, unsigned int alignment) + { + accessChain.indexChain.push_back(offset); + accessChain.coherentFlags |= coherentFlags; + accessChain.alignment |= alignment; + } + + // push new swizzle onto the end of any existing swizzle, merging into a single swizzle + void accessChainPushSwizzle(std::vector& swizzle, Id preSwizzleBaseType, + AccessChain::CoherentFlags coherentFlags, unsigned int alignment); + + // push a dynamic component selection onto the access chain, only applicable with a + // non-trivial swizzle or no swizzle + void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, + unsigned int alignment) + { + if (accessChain.swizzle.size() != 1) { + accessChain.component = component; + if (accessChain.preSwizzleBaseType == NoType) + accessChain.preSwizzleBaseType = preSwizzleBaseType; + } + accessChain.coherentFlags |= coherentFlags; + accessChain.alignment |= alignment; + } + + // use accessChain and swizzle to store value + void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + + // use accessChain and swizzle to load an r-value + Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType, + spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, + unsigned int alignment = 0); + + // Return whether or not the access chain can be represented in SPIR-V + // as an l-value. + // E.g., a[3].yx cannot be, while a[3].y and a[3].y[x] can be. + bool isSpvLvalue() const { return accessChain.swizzle.size() <= 1; } + + // get the direct pointer for an l-value + Id accessChainGetLValue(); + + // Get the inferred SPIR-V type of the result of the current access chain, + // based on the type of the base and the chain of dereferences. + Id accessChainGetInferredType(); + + // Add capabilities, extensions, remove unneeded decorations, etc., + // based on the resulting SPIR-V. + void postProcess(); + + // Prune unreachable blocks in the CFG and remove unneeded decorations. + void postProcessCFG(); + +#ifndef GLSLANG_WEB + // Add capabilities, extensions based on instructions in the module. + void postProcessFeatures(); + // Hook to visit each instruction in a block in a function + void postProcess(Instruction&); + // Hook to visit each non-32-bit sized float/int operation in a block. + void postProcessType(const Instruction&, spv::Id typeId); +#endif + + void dump(std::vector&) const; + + void createBranch(Block* block); + void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock); + void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, + const std::vector& operands); + + // Sets to generate opcode for specialization constants. + void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; } + // Sets to generate opcode for non-specialization constants (normal mode). + void setToNormalCodeGenMode() { generatingOpCodeForSpecConst = false; } + // Check if the builder is generating code for spec constants. + bool isInSpecConstCodeGenMode() { return generatingOpCodeForSpecConst; } + + protected: + Id makeIntConstant(Id typeId, unsigned value, bool specConstant); + Id makeInt64Constant(Id typeId, unsigned long long value, bool specConstant); + Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value); + Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2); + Id findCompositeConstant(Op typeClass, Id typeId, const std::vector& comps); + Id findStructConstant(Id typeId, const std::vector& comps); + Id collapseAccessChain(); + void remapDynamicSwizzle(); + void transferAccessChainSwizzle(bool dynamic); + void simplifyAccessChainSwizzle(); + void createAndSetNoPredecessorBlock(const char*); + void createSelectionMerge(Block* mergeBlock, unsigned int control); + void dumpSourceInstructions(std::vector&) const; + void dumpSourceInstructions(const spv::Id fileId, const std::string& text, std::vector&) const; + void dumpInstructions(std::vector&, const std::vector >&) const; + void dumpModuleProcesses(std::vector&) const; + spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) + const; + + unsigned int spvVersion; // the version of SPIR-V to emit in the header + SourceLanguage source; + int sourceVersion; + spv::Id sourceFileStringId; + std::string sourceText; + int currentLine; + const char* currentFile; + bool emitOpLines; + std::set extensions; + std::vector sourceExtensions; + std::vector moduleProcesses; + AddressingModel addressModel; + MemoryModel memoryModel; + std::set capabilities; + int builderNumber; + Module module; + Block* buildPoint; + Id uniqueId; + Function* entryPointFunction; + bool generatingOpCodeForSpecConst; + AccessChain accessChain; + + // special blocks of instructions for output + std::vector > strings; + std::vector > imports; + std::vector > entryPoints; + std::vector > executionModes; + std::vector > names; + std::vector > decorations; + std::vector > constantsTypesGlobals; + std::vector > externals; + std::vector > functions; + + // not output, internally used for quick & dirty canonical (unique) creation + + // map type opcodes to constant inst. + std::unordered_map> groupedConstants; + // map struct-id to constant instructions + std::unordered_map> groupedStructConstants; + // map type opcodes to type instructions + std::unordered_map> groupedTypes; + + // stack of switches + std::stack switchMerges; + + // Our loop stack. + std::stack loops; + + // map from strings to their string ids + std::unordered_map stringIds; + + // map from include file name ids to their contents + std::map includeFiles; + + // The stream for outputting warnings and errors. + SpvBuildLogger* logger; +}; // end Builder class + +}; // end spv namespace + +#endif // SpvBuilder_H diff --git a/android/x86/include/SPIRV/SpvTools.h b/android/x86/include/SPIRV/SpvTools.h new file mode 100644 index 00000000..59c914da --- /dev/null +++ b/android/x86/include/SPIRV/SpvTools.h @@ -0,0 +1,82 @@ +// +// Copyright (C) 2014-2016 LunarG, Inc. +// Copyright (C) 2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Call into SPIRV-Tools to disassemble, validate, and optimize. +// + +#pragma once +#ifndef GLSLANG_SPV_TOOLS_H +#define GLSLANG_SPV_TOOLS_H + +#ifdef ENABLE_OPT +#include +#include +#endif + +#include "glslang/MachineIndependent/localintermediate.h" +#include "Logger.h" + +namespace glslang { + +struct SpvOptions { + SpvOptions() : generateDebugInfo(false), disableOptimizer(true), + optimizeSize(false), disassemble(false), validate(false) { } + bool generateDebugInfo; + bool disableOptimizer; + bool optimizeSize; + bool disassemble; + bool validate; +}; + +#ifdef ENABLE_OPT + +// Use the SPIRV-Tools disassembler to print SPIR-V. +void SpirvToolsDisassemble(std::ostream& out, const std::vector& spirv); + +// Apply the SPIRV-Tools validator to generated SPIR-V. +void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger*, bool prelegalization); + +// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of +// legalizing HLSL SPIR-V. +void SpirvToolsLegalize(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger*, const SpvOptions*); + +#endif + +} // end namespace glslang + +#endif // GLSLANG_SPV_TOOLS_H diff --git a/android/x86/include/SPIRV/bitutils.h b/android/x86/include/SPIRV/bitutils.h new file mode 100644 index 00000000..22e44cec --- /dev/null +++ b/android/x86/include/SPIRV/bitutils.h @@ -0,0 +1,81 @@ +// Copyright (c) 2015-2016 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef LIBSPIRV_UTIL_BITUTILS_H_ +#define LIBSPIRV_UTIL_BITUTILS_H_ + +#include +#include + +namespace spvutils { + +// Performs a bitwise copy of source to the destination type Dest. +template +Dest BitwiseCast(Src source) { + Dest dest; + static_assert(sizeof(source) == sizeof(dest), + "BitwiseCast: Source and destination must have the same size"); + std::memcpy(static_cast(&dest), &source, sizeof(dest)); + return dest; +} + +// SetBits returns an integer of type with bits set +// for position through , counting from the least +// significant bit. In particular when Num == 0, no positions are set to 1. +// A static assert will be triggered if First + Num > sizeof(T) * 8, that is, +// a bit that will not fit in the underlying type is set. +template +struct SetBits { + static_assert(First < sizeof(T) * 8, + "Tried to set a bit that is shifted too far."); + const static T get = (T(1) << First) | SetBits::get; +}; + +template +struct SetBits { + const static T get = T(0); +}; + +// This is all compile-time so we can put our tests right here. +static_assert(SetBits::get == uint32_t(0x00000000), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x00000001), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x80000000), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x00000006), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0xc0000000), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x7FFFFFFF), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0xFFFFFFFF), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0xFFFF0000), + "SetBits failed"); + +static_assert(SetBits::get == uint64_t(0x0000000000000001LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0x8000000000000000LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0xc000000000000000LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0x0000000080000000LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0x00000000FFFF0000LL), + "SetBits failed"); + +} // namespace spvutils + +#endif // LIBSPIRV_UTIL_BITUTILS_H_ diff --git a/android/x86/include/SPIRV/disassemble.h b/android/x86/include/SPIRV/disassemble.h new file mode 100644 index 00000000..b6a46357 --- /dev/null +++ b/android/x86/include/SPIRV/disassemble.h @@ -0,0 +1,53 @@ +// +// Copyright (C) 2014-2015 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Disassembler for SPIR-V. +// + +#pragma once +#ifndef disassembler_H +#define disassembler_H + +#include +#include + +namespace spv { + + // disassemble with glslang custom disassembler + void Disassemble(std::ostream& out, const std::vector&); + +} // end namespace spv + +#endif // disassembler_H diff --git a/android/x86/include/SPIRV/doc.h b/android/x86/include/SPIRV/doc.h new file mode 100644 index 00000000..293256a2 --- /dev/null +++ b/android/x86/include/SPIRV/doc.h @@ -0,0 +1,258 @@ +// +// Copyright (C) 2014-2015 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Parameterize the SPIR-V enumerants. +// + +#pragma once + +#include "spirv.hpp" + +#include + +namespace spv { + +// Fill in all the parameters +void Parameterize(); + +// Return the English names of all the enums. +const char* SourceString(int); +const char* AddressingString(int); +const char* MemoryString(int); +const char* ExecutionModelString(int); +const char* ExecutionModeString(int); +const char* StorageClassString(int); +const char* DecorationString(int); +const char* BuiltInString(int); +const char* DimensionString(int); +const char* SelectControlString(int); +const char* LoopControlString(int); +const char* FunctionControlString(int); +const char* SamplerAddressingModeString(int); +const char* SamplerFilterModeString(int); +const char* ImageFormatString(int); +const char* ImageChannelOrderString(int); +const char* ImageChannelTypeString(int); +const char* ImageChannelDataTypeString(int type); +const char* ImageOperandsString(int format); +const char* ImageOperands(int); +const char* FPFastMathString(int); +const char* FPRoundingModeString(int); +const char* LinkageTypeString(int); +const char* FuncParamAttrString(int); +const char* AccessQualifierString(int); +const char* MemorySemanticsString(int); +const char* MemoryAccessString(int); +const char* ExecutionScopeString(int); +const char* GroupOperationString(int); +const char* KernelEnqueueFlagsString(int); +const char* KernelProfilingInfoString(int); +const char* CapabilityString(int); +const char* OpcodeString(int); +const char* ScopeString(int mem); + +// For grouping opcodes into subsections +enum OpcodeClass { + OpClassMisc, + OpClassDebug, + OpClassAnnotate, + OpClassExtension, + OpClassMode, + OpClassType, + OpClassConstant, + OpClassMemory, + OpClassFunction, + OpClassImage, + OpClassConvert, + OpClassComposite, + OpClassArithmetic, + OpClassBit, + OpClassRelationalLogical, + OpClassDerivative, + OpClassFlowControl, + OpClassAtomic, + OpClassPrimitive, + OpClassBarrier, + OpClassGroup, + OpClassDeviceSideEnqueue, + OpClassPipe, + + OpClassCount, + OpClassMissing // all instructions start out as missing +}; + +// For parameterizing operands. +enum OperandClass { + OperandNone, + OperandId, + OperandVariableIds, + OperandOptionalLiteral, + OperandOptionalLiteralString, + OperandVariableLiterals, + OperandVariableIdLiteral, + OperandVariableLiteralId, + OperandLiteralNumber, + OperandLiteralString, + OperandSource, + OperandExecutionModel, + OperandAddressing, + OperandMemory, + OperandExecutionMode, + OperandStorage, + OperandDimensionality, + OperandSamplerAddressingMode, + OperandSamplerFilterMode, + OperandSamplerImageFormat, + OperandImageChannelOrder, + OperandImageChannelDataType, + OperandImageOperands, + OperandFPFastMath, + OperandFPRoundingMode, + OperandLinkageType, + OperandAccessQualifier, + OperandFuncParamAttr, + OperandDecoration, + OperandBuiltIn, + OperandSelect, + OperandLoop, + OperandFunction, + OperandMemorySemantics, + OperandMemoryAccess, + OperandScope, + OperandGroupOperation, + OperandKernelEnqueueFlags, + OperandKernelProfilingInfo, + OperandCapability, + + OperandOpcode, + + OperandCount +}; + +// Any specific enum can have a set of capabilities that allow it: +typedef std::vector EnumCaps; + +// Parameterize a set of operands with their OperandClass(es) and descriptions. +class OperandParameters { +public: + OperandParameters() { } + void push(OperandClass oc, const char* d, bool opt = false) + { + opClass.push_back(oc); + desc.push_back(d); + optional.push_back(opt); + } + void setOptional(); + OperandClass getClass(int op) const { return opClass[op]; } + const char* getDesc(int op) const { return desc[op]; } + bool isOptional(int op) const { return optional[op]; } + int getNum() const { return (int)opClass.size(); } + +protected: + std::vector opClass; + std::vector desc; + std::vector optional; +}; + +// Parameterize an enumerant +class EnumParameters { +public: + EnumParameters() : desc(0) { } + const char* desc; +}; + +// Parameterize a set of enumerants that form an enum +class EnumDefinition : public EnumParameters { +public: + EnumDefinition() : + ceiling(0), bitmask(false), getName(0), enumParams(0), operandParams(0) { } + void set(int ceil, const char* (*name)(int), EnumParameters* ep, bool mask = false) + { + ceiling = ceil; + getName = name; + bitmask = mask; + enumParams = ep; + } + void setOperands(OperandParameters* op) { operandParams = op; } + int ceiling; // ceiling of enumerants + bool bitmask; // true if these enumerants combine into a bitmask + const char* (*getName)(int); // a function that returns the name for each enumerant value (or shift) + EnumParameters* enumParams; // parameters for each individual enumerant + OperandParameters* operandParams; // sets of operands +}; + +// Parameterize an instruction's logical format, including its known set of operands, +// per OperandParameters above. +class InstructionParameters { +public: + InstructionParameters() : + opDesc("TBD"), + opClass(OpClassMissing), + typePresent(true), // most normal, only exceptions have to be spelled out + resultPresent(true) // most normal, only exceptions have to be spelled out + { } + + void setResultAndType(bool r, bool t) + { + resultPresent = r; + typePresent = t; + } + + bool hasResult() const { return resultPresent != 0; } + bool hasType() const { return typePresent != 0; } + + const char* opDesc; + OpcodeClass opClass; + OperandParameters operands; + +protected: + int typePresent : 1; + int resultPresent : 1; +}; + +// The set of objects that hold all the instruction/operand +// parameterization information. +extern InstructionParameters InstructionDesc[]; + +// These hold definitions of the enumerants used for operands +extern EnumDefinition OperandClassParams[]; + +const char* GetOperandDesc(OperandClass operand); +void PrintImmediateRow(int imm, const char* name, const EnumParameters* enumParams, bool caps, bool hex = false); +const char* AccessQualifierString(int attr); + +void PrintOperands(const OperandParameters& operands, int reservedOperands); + +} // end namespace spv diff --git a/android/x86/include/SPIRV/hex_float.h b/android/x86/include/SPIRV/hex_float.h new file mode 100644 index 00000000..8be8e9f7 --- /dev/null +++ b/android/x86/include/SPIRV/hex_float.h @@ -0,0 +1,1078 @@ +// Copyright (c) 2015-2016 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef LIBSPIRV_UTIL_HEX_FLOAT_H_ +#define LIBSPIRV_UTIL_HEX_FLOAT_H_ + +#include +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) && _MSC_VER < 1800 +namespace std { +bool isnan(double f) +{ + return ::_isnan(f) != 0; +} +bool isinf(double f) +{ + return ::_finite(f) == 0; +} +} +#endif + +#include "bitutils.h" + +namespace spvutils { + +class Float16 { + public: + Float16(uint16_t v) : val(v) {} + Float16() {} + static bool isNan(const Float16& val) { + return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) != 0); + } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(const Float16& val) { + return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) == 0); + } + Float16(const Float16& other) { val = other.val; } + uint16_t get_value() const { return val; } + + // Returns the maximum normal value. + static Float16 max() { return Float16(0x7bff); } + // Returns the lowest normal value. + static Float16 lowest() { return Float16(0xfbff); } + + private: + uint16_t val; +}; + +// To specialize this type, you must override uint_type to define +// an unsigned integer that can fit your floating point type. +// You must also add a isNan function that returns true if +// a value is Nan. +template +struct FloatProxyTraits { + typedef void uint_type; +}; + +template <> +struct FloatProxyTraits { + typedef uint32_t uint_type; + static bool isNan(float f) { return std::isnan(f); } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(float f) { return std::isinf(f); } + // Returns the maximum normal value. + static float max() { return std::numeric_limits::max(); } + // Returns the lowest normal value. + static float lowest() { return std::numeric_limits::lowest(); } +}; + +template <> +struct FloatProxyTraits { + typedef uint64_t uint_type; + static bool isNan(double f) { return std::isnan(f); } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(double f) { return std::isinf(f); } + // Returns the maximum normal value. + static double max() { return std::numeric_limits::max(); } + // Returns the lowest normal value. + static double lowest() { return std::numeric_limits::lowest(); } +}; + +template <> +struct FloatProxyTraits { + typedef uint16_t uint_type; + static bool isNan(Float16 f) { return Float16::isNan(f); } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(Float16 f) { return Float16::isInfinity(f); } + // Returns the maximum normal value. + static Float16 max() { return Float16::max(); } + // Returns the lowest normal value. + static Float16 lowest() { return Float16::lowest(); } +}; + +// Since copying a floating point number (especially if it is NaN) +// does not guarantee that bits are preserved, this class lets us +// store the type and use it as a float when necessary. +template +class FloatProxy { + public: + typedef typename FloatProxyTraits::uint_type uint_type; + + // Since this is to act similar to the normal floats, + // do not initialize the data by default. + FloatProxy() {} + + // Intentionally non-explicit. This is a proxy type so + // implicit conversions allow us to use it more transparently. + FloatProxy(T val) { data_ = BitwiseCast(val); } + + // Intentionally non-explicit. This is a proxy type so + // implicit conversions allow us to use it more transparently. + FloatProxy(uint_type val) { data_ = val; } + + // This is helpful to have and is guaranteed not to stomp bits. + FloatProxy operator-() const { + return static_cast(data_ ^ + (uint_type(0x1) << (sizeof(T) * 8 - 1))); + } + + // Returns the data as a floating point value. + T getAsFloat() const { return BitwiseCast(data_); } + + // Returns the raw data. + uint_type data() const { return data_; } + + // Returns true if the value represents any type of NaN. + bool isNan() { return FloatProxyTraits::isNan(getAsFloat()); } + // Returns true if the value represents any type of infinity. + bool isInfinity() { return FloatProxyTraits::isInfinity(getAsFloat()); } + + // Returns the maximum normal value. + static FloatProxy max() { + return FloatProxy(FloatProxyTraits::max()); + } + // Returns the lowest normal value. + static FloatProxy lowest() { + return FloatProxy(FloatProxyTraits::lowest()); + } + + private: + uint_type data_; +}; + +template +bool operator==(const FloatProxy& first, const FloatProxy& second) { + return first.data() == second.data(); +} + +// Reads a FloatProxy value as a normal float from a stream. +template +std::istream& operator>>(std::istream& is, FloatProxy& value) { + T float_val; + is >> float_val; + value = FloatProxy(float_val); + return is; +} + +// This is an example traits. It is not meant to be used in practice, but will +// be the default for any non-specialized type. +template +struct HexFloatTraits { + // Integer type that can store this hex-float. + typedef void uint_type; + // Signed integer type that can store this hex-float. + typedef void int_type; + // The numerical type that this HexFloat represents. + typedef void underlying_type; + // The type needed to construct the underlying type. + typedef void native_type; + // The number of bits that are actually relevant in the uint_type. + // This allows us to deal with, for example, 24-bit values in a 32-bit + // integer. + static const uint32_t num_used_bits = 0; + // Number of bits that represent the exponent. + static const uint32_t num_exponent_bits = 0; + // Number of bits that represent the fractional part. + static const uint32_t num_fraction_bits = 0; + // The bias of the exponent. (How much we need to subtract from the stored + // value to get the correct value.) + static const uint32_t exponent_bias = 0; +}; + +// Traits for IEEE float. +// 1 sign bit, 8 exponent bits, 23 fractional bits. +template <> +struct HexFloatTraits> { + typedef uint32_t uint_type; + typedef int32_t int_type; + typedef FloatProxy underlying_type; + typedef float native_type; + static const uint_type num_used_bits = 32; + static const uint_type num_exponent_bits = 8; + static const uint_type num_fraction_bits = 23; + static const uint_type exponent_bias = 127; +}; + +// Traits for IEEE double. +// 1 sign bit, 11 exponent bits, 52 fractional bits. +template <> +struct HexFloatTraits> { + typedef uint64_t uint_type; + typedef int64_t int_type; + typedef FloatProxy underlying_type; + typedef double native_type; + static const uint_type num_used_bits = 64; + static const uint_type num_exponent_bits = 11; + static const uint_type num_fraction_bits = 52; + static const uint_type exponent_bias = 1023; +}; + +// Traits for IEEE half. +// 1 sign bit, 5 exponent bits, 10 fractional bits. +template <> +struct HexFloatTraits> { + typedef uint16_t uint_type; + typedef int16_t int_type; + typedef uint16_t underlying_type; + typedef uint16_t native_type; + static const uint_type num_used_bits = 16; + static const uint_type num_exponent_bits = 5; + static const uint_type num_fraction_bits = 10; + static const uint_type exponent_bias = 15; +}; + +enum round_direction { + kRoundToZero, + kRoundToNearestEven, + kRoundToPositiveInfinity, + kRoundToNegativeInfinity +}; + +// Template class that houses a floating pointer number. +// It exposes a number of constants based on the provided traits to +// assist in interpreting the bits of the value. +template > +class HexFloat { + public: + typedef typename Traits::uint_type uint_type; + typedef typename Traits::int_type int_type; + typedef typename Traits::underlying_type underlying_type; + typedef typename Traits::native_type native_type; + + explicit HexFloat(T f) : value_(f) {} + + T value() const { return value_; } + void set_value(T f) { value_ = f; } + + // These are all written like this because it is convenient to have + // compile-time constants for all of these values. + + // Pass-through values to save typing. + static const uint32_t num_used_bits = Traits::num_used_bits; + static const uint32_t exponent_bias = Traits::exponent_bias; + static const uint32_t num_exponent_bits = Traits::num_exponent_bits; + static const uint32_t num_fraction_bits = Traits::num_fraction_bits; + + // Number of bits to shift left to set the highest relevant bit. + static const uint32_t top_bit_left_shift = num_used_bits - 1; + // How many nibbles (hex characters) the fractional part takes up. + static const uint32_t fraction_nibbles = (num_fraction_bits + 3) / 4; + // If the fractional part does not fit evenly into a hex character (4-bits) + // then we have to left-shift to get rid of leading 0s. This is the amount + // we have to shift (might be 0). + static const uint32_t num_overflow_bits = + fraction_nibbles * 4 - num_fraction_bits; + + // The representation of the fraction, not the actual bits. This + // includes the leading bit that is usually implicit. + static const uint_type fraction_represent_mask = + spvutils::SetBits::get; + + // The topmost bit in the nibble-aligned fraction. + static const uint_type fraction_top_bit = + uint_type(1) << (num_fraction_bits + num_overflow_bits - 1); + + // The least significant bit in the exponent, which is also the bit + // immediately to the left of the significand. + static const uint_type first_exponent_bit = uint_type(1) + << (num_fraction_bits); + + // The mask for the encoded fraction. It does not include the + // implicit bit. + static const uint_type fraction_encode_mask = + spvutils::SetBits::get; + + // The bit that is used as a sign. + static const uint_type sign_mask = uint_type(1) << top_bit_left_shift; + + // The bits that represent the exponent. + static const uint_type exponent_mask = + spvutils::SetBits::get; + + // How far left the exponent is shifted. + static const uint32_t exponent_left_shift = num_fraction_bits; + + // How far from the right edge the fraction is shifted. + static const uint32_t fraction_right_shift = + static_cast(sizeof(uint_type) * 8) - num_fraction_bits; + + // The maximum representable unbiased exponent. + static const int_type max_exponent = + (exponent_mask >> num_fraction_bits) - exponent_bias; + // The minimum representable exponent for normalized numbers. + static const int_type min_exponent = -static_cast(exponent_bias); + + // Returns the bits associated with the value. + uint_type getBits() const { return spvutils::BitwiseCast(value_); } + + // Returns the bits associated with the value, without the leading sign bit. + uint_type getUnsignedBits() const { + return static_cast(spvutils::BitwiseCast(value_) & + ~sign_mask); + } + + // Returns the bits associated with the exponent, shifted to start at the + // lsb of the type. + const uint_type getExponentBits() const { + return static_cast((getBits() & exponent_mask) >> + num_fraction_bits); + } + + // Returns the exponent in unbiased form. This is the exponent in the + // human-friendly form. + const int_type getUnbiasedExponent() const { + return static_cast(getExponentBits() - exponent_bias); + } + + // Returns just the significand bits from the value. + const uint_type getSignificandBits() const { + return getBits() & fraction_encode_mask; + } + + // If the number was normalized, returns the unbiased exponent. + // If the number was denormal, normalize the exponent first. + const int_type getUnbiasedNormalizedExponent() const { + if ((getBits() & ~sign_mask) == 0) { // special case if everything is 0 + return 0; + } + int_type exp = getUnbiasedExponent(); + if (exp == min_exponent) { // We are in denorm land. + uint_type significand_bits = getSignificandBits(); + while ((significand_bits & (first_exponent_bit >> 1)) == 0) { + significand_bits = static_cast(significand_bits << 1); + exp = static_cast(exp - 1); + } + significand_bits &= fraction_encode_mask; + } + return exp; + } + + // Returns the signficand after it has been normalized. + const uint_type getNormalizedSignificand() const { + int_type unbiased_exponent = getUnbiasedNormalizedExponent(); + uint_type significand = getSignificandBits(); + for (int_type i = unbiased_exponent; i <= min_exponent; ++i) { + significand = static_cast(significand << 1); + } + significand &= fraction_encode_mask; + return significand; + } + + // Returns true if this number represents a negative value. + bool isNegative() const { return (getBits() & sign_mask) != 0; } + + // Sets this HexFloat from the individual components. + // Note this assumes EVERY significand is normalized, and has an implicit + // leading one. This means that the only way that this method will set 0, + // is if you set a number so denormalized that it underflows. + // Do not use this method with raw bits extracted from a subnormal number, + // since subnormals do not have an implicit leading 1 in the significand. + // The significand is also expected to be in the + // lowest-most num_fraction_bits of the uint_type. + // The exponent is expected to be unbiased, meaning an exponent of + // 0 actually means 0. + // If underflow_round_up is set, then on underflow, if a number is non-0 + // and would underflow, we round up to the smallest denorm. + void setFromSignUnbiasedExponentAndNormalizedSignificand( + bool negative, int_type exponent, uint_type significand, + bool round_denorm_up) { + bool significand_is_zero = significand == 0; + + if (exponent <= min_exponent) { + // If this was denormalized, then we have to shift the bit on, meaning + // the significand is not zero. + significand_is_zero = false; + significand |= first_exponent_bit; + significand = static_cast(significand >> 1); + } + + while (exponent < min_exponent) { + significand = static_cast(significand >> 1); + ++exponent; + } + + if (exponent == min_exponent) { + if (significand == 0 && !significand_is_zero && round_denorm_up) { + significand = static_cast(0x1); + } + } + + uint_type new_value = 0; + if (negative) { + new_value = static_cast(new_value | sign_mask); + } + exponent = static_cast(exponent + exponent_bias); + assert(exponent >= 0); + + // put it all together + exponent = static_cast((exponent << exponent_left_shift) & + exponent_mask); + significand = static_cast(significand & fraction_encode_mask); + new_value = static_cast(new_value | (exponent | significand)); + value_ = BitwiseCast(new_value); + } + + // Increments the significand of this number by the given amount. + // If this would spill the significand into the implicit bit, + // carry is set to true and the significand is shifted to fit into + // the correct location, otherwise carry is set to false. + // All significands and to_increment are assumed to be within the bounds + // for a valid significand. + static uint_type incrementSignificand(uint_type significand, + uint_type to_increment, bool* carry) { + significand = static_cast(significand + to_increment); + *carry = false; + if (significand & first_exponent_bit) { + *carry = true; + // The implicit 1-bit will have carried, so we should zero-out the + // top bit and shift back. + significand = static_cast(significand & ~first_exponent_bit); + significand = static_cast(significand >> 1); + } + return significand; + } + + // These exist because MSVC throws warnings on negative right-shifts + // even if they are not going to be executed. Eg: + // constant_number < 0? 0: constant_number + // These convert the negative left-shifts into right shifts. + + template + uint_type negatable_left_shift(int_type N, uint_type val) + { + if(N >= 0) + return val << N; + + return val >> -N; + } + + template + uint_type negatable_right_shift(int_type N, uint_type val) + { + if(N >= 0) + return val >> N; + + return val << -N; + } + + // Returns the significand, rounded to fit in a significand in + // other_T. This is shifted so that the most significant + // bit of the rounded number lines up with the most significant bit + // of the returned significand. + template + typename other_T::uint_type getRoundedNormalizedSignificand( + round_direction dir, bool* carry_bit) { + typedef typename other_T::uint_type other_uint_type; + static const int_type num_throwaway_bits = + static_cast(num_fraction_bits) - + static_cast(other_T::num_fraction_bits); + + static const uint_type last_significant_bit = + (num_throwaway_bits < 0) + ? 0 + : negatable_left_shift(num_throwaway_bits, 1u); + static const uint_type first_rounded_bit = + (num_throwaway_bits < 1) + ? 0 + : negatable_left_shift(num_throwaway_bits - 1, 1u); + + static const uint_type throwaway_mask_bits = + num_throwaway_bits > 0 ? num_throwaway_bits : 0; + static const uint_type throwaway_mask = + spvutils::SetBits::get; + + *carry_bit = false; + other_uint_type out_val = 0; + uint_type significand = getNormalizedSignificand(); + // If we are up-casting, then we just have to shift to the right location. + if (num_throwaway_bits <= 0) { + out_val = static_cast(significand); + uint_type shift_amount = static_cast(-num_throwaway_bits); + out_val = static_cast(out_val << shift_amount); + return out_val; + } + + // If every non-representable bit is 0, then we don't have any casting to + // do. + if ((significand & throwaway_mask) == 0) { + return static_cast( + negatable_right_shift(num_throwaway_bits, significand)); + } + + bool round_away_from_zero = false; + // We actually have to narrow the significand here, so we have to follow the + // rounding rules. + switch (dir) { + case kRoundToZero: + break; + case kRoundToPositiveInfinity: + round_away_from_zero = !isNegative(); + break; + case kRoundToNegativeInfinity: + round_away_from_zero = isNegative(); + break; + case kRoundToNearestEven: + // Have to round down, round bit is 0 + if ((first_rounded_bit & significand) == 0) { + break; + } + if (((significand & throwaway_mask) & ~first_rounded_bit) != 0) { + // If any subsequent bit of the rounded portion is non-0 then we round + // up. + round_away_from_zero = true; + break; + } + // We are exactly half-way between 2 numbers, pick even. + if ((significand & last_significant_bit) != 0) { + // 1 for our last bit, round up. + round_away_from_zero = true; + break; + } + break; + } + + if (round_away_from_zero) { + return static_cast( + negatable_right_shift(num_throwaway_bits, incrementSignificand( + significand, last_significant_bit, carry_bit))); + } else { + return static_cast( + negatable_right_shift(num_throwaway_bits, significand)); + } + } + + // Casts this value to another HexFloat. If the cast is widening, + // then round_dir is ignored. If the cast is narrowing, then + // the result is rounded in the direction specified. + // This number will retain Nan and Inf values. + // It will also saturate to Inf if the number overflows, and + // underflow to (0 or min depending on rounding) if the number underflows. + template + void castTo(other_T& other, round_direction round_dir) { + other = other_T(static_cast(0)); + bool negate = isNegative(); + if (getUnsignedBits() == 0) { + if (negate) { + other.set_value(-other.value()); + } + return; + } + uint_type significand = getSignificandBits(); + bool carried = false; + typename other_T::uint_type rounded_significand = + getRoundedNormalizedSignificand(round_dir, &carried); + + int_type exponent = getUnbiasedExponent(); + if (exponent == min_exponent) { + // If we are denormal, normalize the exponent, so that we can encode + // easily. + exponent = static_cast(exponent + 1); + for (uint_type check_bit = first_exponent_bit >> 1; check_bit != 0; + check_bit = static_cast(check_bit >> 1)) { + exponent = static_cast(exponent - 1); + if (check_bit & significand) break; + } + } + + bool is_nan = + (getBits() & exponent_mask) == exponent_mask && significand != 0; + bool is_inf = + !is_nan && + ((exponent + carried) > static_cast(other_T::exponent_bias) || + (significand == 0 && (getBits() & exponent_mask) == exponent_mask)); + + // If we are Nan or Inf we should pass that through. + if (is_inf) { + other.set_value(BitwiseCast( + static_cast( + (negate ? other_T::sign_mask : 0) | other_T::exponent_mask))); + return; + } + if (is_nan) { + typename other_T::uint_type shifted_significand; + shifted_significand = static_cast( + negatable_left_shift( + static_cast(other_T::num_fraction_bits) - + static_cast(num_fraction_bits), significand)); + + // We are some sort of Nan. We try to keep the bit-pattern of the Nan + // as close as possible. If we had to shift off bits so we are 0, then we + // just set the last bit. + other.set_value(BitwiseCast( + static_cast( + (negate ? other_T::sign_mask : 0) | other_T::exponent_mask | + (shifted_significand == 0 ? 0x1 : shifted_significand)))); + return; + } + + bool round_underflow_up = + isNegative() ? round_dir == kRoundToNegativeInfinity + : round_dir == kRoundToPositiveInfinity; + typedef typename other_T::int_type other_int_type; + // setFromSignUnbiasedExponentAndNormalizedSignificand will + // zero out any underflowing value (but retain the sign). + other.setFromSignUnbiasedExponentAndNormalizedSignificand( + negate, static_cast(exponent), rounded_significand, + round_underflow_up); + return; + } + + private: + T value_; + + static_assert(num_used_bits == + Traits::num_exponent_bits + Traits::num_fraction_bits + 1, + "The number of bits do not fit"); + static_assert(sizeof(T) == sizeof(uint_type), "The type sizes do not match"); +}; + +// Returns 4 bits represented by the hex character. +inline uint8_t get_nibble_from_character(int character) { + const char* dec = "0123456789"; + const char* lower = "abcdef"; + const char* upper = "ABCDEF"; + const char* p = nullptr; + if ((p = strchr(dec, character))) { + return static_cast(p - dec); + } else if ((p = strchr(lower, character))) { + return static_cast(p - lower + 0xa); + } else if ((p = strchr(upper, character))) { + return static_cast(p - upper + 0xa); + } + + assert(false && "This was called with a non-hex character"); + return 0; +} + +// Outputs the given HexFloat to the stream. +template +std::ostream& operator<<(std::ostream& os, const HexFloat& value) { + typedef HexFloat HF; + typedef typename HF::uint_type uint_type; + typedef typename HF::int_type int_type; + + static_assert(HF::num_used_bits != 0, + "num_used_bits must be non-zero for a valid float"); + static_assert(HF::num_exponent_bits != 0, + "num_exponent_bits must be non-zero for a valid float"); + static_assert(HF::num_fraction_bits != 0, + "num_fractin_bits must be non-zero for a valid float"); + + const uint_type bits = spvutils::BitwiseCast(value.value()); + const char* const sign = (bits & HF::sign_mask) ? "-" : ""; + const uint_type exponent = static_cast( + (bits & HF::exponent_mask) >> HF::num_fraction_bits); + + uint_type fraction = static_cast((bits & HF::fraction_encode_mask) + << HF::num_overflow_bits); + + const bool is_zero = exponent == 0 && fraction == 0; + const bool is_denorm = exponent == 0 && !is_zero; + + // exponent contains the biased exponent we have to convert it back into + // the normal range. + int_type int_exponent = static_cast(exponent - HF::exponent_bias); + // If the number is all zeros, then we actually have to NOT shift the + // exponent. + int_exponent = is_zero ? 0 : int_exponent; + + // If we are denorm, then start shifting, and decreasing the exponent until + // our leading bit is 1. + + if (is_denorm) { + while ((fraction & HF::fraction_top_bit) == 0) { + fraction = static_cast(fraction << 1); + int_exponent = static_cast(int_exponent - 1); + } + // Since this is denormalized, we have to consume the leading 1 since it + // will end up being implicit. + fraction = static_cast(fraction << 1); // eat the leading 1 + fraction &= HF::fraction_represent_mask; + } + + uint_type fraction_nibbles = HF::fraction_nibbles; + // We do not have to display any trailing 0s, since this represents the + // fractional part. + while (fraction_nibbles > 0 && (fraction & 0xF) == 0) { + // Shift off any trailing values; + fraction = static_cast(fraction >> 4); + --fraction_nibbles; + } + + const auto saved_flags = os.flags(); + const auto saved_fill = os.fill(); + + os << sign << "0x" << (is_zero ? '0' : '1'); + if (fraction_nibbles) { + // Make sure to keep the leading 0s in place, since this is the fractional + // part. + os << "." << std::setw(static_cast(fraction_nibbles)) + << std::setfill('0') << std::hex << fraction; + } + os << "p" << std::dec << (int_exponent >= 0 ? "+" : "") << int_exponent; + + os.flags(saved_flags); + os.fill(saved_fill); + + return os; +} + +// Returns true if negate_value is true and the next character on the +// input stream is a plus or minus sign. In that case we also set the fail bit +// on the stream and set the value to the zero value for its type. +template +inline bool RejectParseDueToLeadingSign(std::istream& is, bool negate_value, + HexFloat& value) { + if (negate_value) { + auto next_char = is.peek(); + if (next_char == '-' || next_char == '+') { + // Fail the parse. Emulate standard behaviour by setting the value to + // the zero value, and set the fail bit on the stream. + value = HexFloat(typename HexFloat::uint_type(0)); + is.setstate(std::ios_base::failbit); + return true; + } + } + return false; +} + +// Parses a floating point number from the given stream and stores it into the +// value parameter. +// If negate_value is true then the number may not have a leading minus or +// plus, and if it successfully parses, then the number is negated before +// being stored into the value parameter. +// If the value cannot be correctly parsed or overflows the target floating +// point type, then set the fail bit on the stream. +// TODO(dneto): Promise C++11 standard behavior in how the value is set in +// the error case, but only after all target platforms implement it correctly. +// In particular, the Microsoft C++ runtime appears to be out of spec. +template +inline std::istream& ParseNormalFloat(std::istream& is, bool negate_value, + HexFloat& value) { + if (RejectParseDueToLeadingSign(is, negate_value, value)) { + return is; + } + T val; + is >> val; + if (negate_value) { + val = -val; + } + value.set_value(val); + // In the failure case, map -0.0 to 0.0. + if (is.fail() && value.getUnsignedBits() == 0u) { + value = HexFloat(typename HexFloat::uint_type(0)); + } + if (val.isInfinity()) { + // Fail the parse. Emulate standard behaviour by setting the value to + // the closest normal value, and set the fail bit on the stream. + value.set_value((value.isNegative() || negate_value) ? T::lowest() + : T::max()); + is.setstate(std::ios_base::failbit); + } + return is; +} + +// Specialization of ParseNormalFloat for FloatProxy values. +// This will parse the float as it were a 32-bit floating point number, +// and then round it down to fit into a Float16 value. +// The number is rounded towards zero. +// If negate_value is true then the number may not have a leading minus or +// plus, and if it successfully parses, then the number is negated before +// being stored into the value parameter. +// If the value cannot be correctly parsed or overflows the target floating +// point type, then set the fail bit on the stream. +// TODO(dneto): Promise C++11 standard behavior in how the value is set in +// the error case, but only after all target platforms implement it correctly. +// In particular, the Microsoft C++ runtime appears to be out of spec. +template <> +inline std::istream& +ParseNormalFloat, HexFloatTraits>>( + std::istream& is, bool negate_value, + HexFloat, HexFloatTraits>>& value) { + // First parse as a 32-bit float. + HexFloat> float_val(0.0f); + ParseNormalFloat(is, negate_value, float_val); + + // Then convert to 16-bit float, saturating at infinities, and + // rounding toward zero. + float_val.castTo(value, kRoundToZero); + + // Overflow on 16-bit behaves the same as for 32- and 64-bit: set the + // fail bit and set the lowest or highest value. + if (Float16::isInfinity(value.value().getAsFloat())) { + value.set_value(value.isNegative() ? Float16::lowest() : Float16::max()); + is.setstate(std::ios_base::failbit); + } + return is; +} + +// Reads a HexFloat from the given stream. +// If the float is not encoded as a hex-float then it will be parsed +// as a regular float. +// This may fail if your stream does not support at least one unget. +// Nan values can be encoded with "0x1.p+exponent_bias". +// This would normally overflow a float and round to +// infinity but this special pattern is the exact representation for a NaN, +// and therefore is actually encoded as the correct NaN. To encode inf, +// either 0x0p+exponent_bias can be specified or any exponent greater than +// exponent_bias. +// Examples using IEEE 32-bit float encoding. +// 0x1.0p+128 (+inf) +// -0x1.0p-128 (-inf) +// +// 0x1.1p+128 (+Nan) +// -0x1.1p+128 (-Nan) +// +// 0x1p+129 (+inf) +// -0x1p+129 (-inf) +template +std::istream& operator>>(std::istream& is, HexFloat& value) { + using HF = HexFloat; + using uint_type = typename HF::uint_type; + using int_type = typename HF::int_type; + + value.set_value(static_cast(0.f)); + + if (is.flags() & std::ios::skipws) { + // If the user wants to skip whitespace , then we should obey that. + while (std::isspace(is.peek())) { + is.get(); + } + } + + auto next_char = is.peek(); + bool negate_value = false; + + if (next_char != '-' && next_char != '0') { + return ParseNormalFloat(is, negate_value, value); + } + + if (next_char == '-') { + negate_value = true; + is.get(); + next_char = is.peek(); + } + + if (next_char == '0') { + is.get(); // We may have to unget this. + auto maybe_hex_start = is.peek(); + if (maybe_hex_start != 'x' && maybe_hex_start != 'X') { + is.unget(); + return ParseNormalFloat(is, negate_value, value); + } else { + is.get(); // Throw away the 'x'; + } + } else { + return ParseNormalFloat(is, negate_value, value); + } + + // This "looks" like a hex-float so treat it as one. + bool seen_p = false; + bool seen_dot = false; + uint_type fraction_index = 0; + + uint_type fraction = 0; + int_type exponent = HF::exponent_bias; + + // Strip off leading zeros so we don't have to special-case them later. + while ((next_char = is.peek()) == '0') { + is.get(); + } + + bool is_denorm = + true; // Assume denorm "representation" until we hear otherwise. + // NB: This does not mean the value is actually denorm, + // it just means that it was written 0. + bool bits_written = false; // Stays false until we write a bit. + while (!seen_p && !seen_dot) { + // Handle characters that are left of the fractional part. + if (next_char == '.') { + seen_dot = true; + } else if (next_char == 'p') { + seen_p = true; + } else if (::isxdigit(next_char)) { + // We know this is not denormalized since we have stripped all leading + // zeroes and we are not a ".". + is_denorm = false; + int number = get_nibble_from_character(next_char); + for (int i = 0; i < 4; ++i, number <<= 1) { + uint_type write_bit = (number & 0x8) ? 0x1 : 0x0; + if (bits_written) { + // If we are here the bits represented belong in the fractional + // part of the float, and we have to adjust the exponent accordingly. + fraction = static_cast( + fraction | + static_cast( + write_bit << (HF::top_bit_left_shift - fraction_index++))); + exponent = static_cast(exponent + 1); + } + bits_written |= write_bit != 0; + } + } else { + // We have not found our exponent yet, so we have to fail. + is.setstate(std::ios::failbit); + return is; + } + is.get(); + next_char = is.peek(); + } + bits_written = false; + while (seen_dot && !seen_p) { + // Handle only fractional parts now. + if (next_char == 'p') { + seen_p = true; + } else if (::isxdigit(next_char)) { + int number = get_nibble_from_character(next_char); + for (int i = 0; i < 4; ++i, number <<= 1) { + uint_type write_bit = (number & 0x8) ? 0x01 : 0x00; + bits_written |= write_bit != 0; + if (is_denorm && !bits_written) { + // Handle modifying the exponent here this way we can handle + // an arbitrary number of hex values without overflowing our + // integer. + exponent = static_cast(exponent - 1); + } else { + fraction = static_cast( + fraction | + static_cast( + write_bit << (HF::top_bit_left_shift - fraction_index++))); + } + } + } else { + // We still have not found our 'p' exponent yet, so this is not a valid + // hex-float. + is.setstate(std::ios::failbit); + return is; + } + is.get(); + next_char = is.peek(); + } + + bool seen_sign = false; + int8_t exponent_sign = 1; + int_type written_exponent = 0; + while (true) { + if ((next_char == '-' || next_char == '+')) { + if (seen_sign) { + is.setstate(std::ios::failbit); + return is; + } + seen_sign = true; + exponent_sign = (next_char == '-') ? -1 : 1; + } else if (::isdigit(next_char)) { + // Hex-floats express their exponent as decimal. + written_exponent = static_cast(written_exponent * 10); + written_exponent = + static_cast(written_exponent + (next_char - '0')); + } else { + break; + } + is.get(); + next_char = is.peek(); + } + + written_exponent = static_cast(written_exponent * exponent_sign); + exponent = static_cast(exponent + written_exponent); + + bool is_zero = is_denorm && (fraction == 0); + if (is_denorm && !is_zero) { + fraction = static_cast(fraction << 1); + exponent = static_cast(exponent - 1); + } else if (is_zero) { + exponent = 0; + } + + if (exponent <= 0 && !is_zero) { + fraction = static_cast(fraction >> 1); + fraction |= static_cast(1) << HF::top_bit_left_shift; + } + + fraction = (fraction >> HF::fraction_right_shift) & HF::fraction_encode_mask; + + const int_type max_exponent = + SetBits::get; + + // Handle actual denorm numbers + while (exponent < 0 && !is_zero) { + fraction = static_cast(fraction >> 1); + exponent = static_cast(exponent + 1); + + fraction &= HF::fraction_encode_mask; + if (fraction == 0) { + // We have underflowed our fraction. We should clamp to zero. + is_zero = true; + exponent = 0; + } + } + + // We have overflowed so we should be inf/-inf. + if (exponent > max_exponent) { + exponent = max_exponent; + fraction = 0; + } + + uint_type output_bits = static_cast( + static_cast(negate_value ? 1 : 0) << HF::top_bit_left_shift); + output_bits |= fraction; + + uint_type shifted_exponent = static_cast( + static_cast(exponent << HF::exponent_left_shift) & + HF::exponent_mask); + output_bits |= shifted_exponent; + + T output_float = spvutils::BitwiseCast(output_bits); + value.set_value(output_float); + + return is; +} + +// Writes a FloatProxy value to a stream. +// Zero and normal numbers are printed in the usual notation, but with +// enough digits to fully reproduce the value. Other values (subnormal, +// NaN, and infinity) are printed as a hex float. +template +std::ostream& operator<<(std::ostream& os, const FloatProxy& value) { + auto float_val = value.getAsFloat(); + switch (std::fpclassify(float_val)) { + case FP_ZERO: + case FP_NORMAL: { + auto saved_precision = os.precision(); + os.precision(std::numeric_limits::digits10); + os << float_val; + os.precision(saved_precision); + } break; + default: + os << HexFloat>(value); + break; + } + return os; +} + +template <> +inline std::ostream& operator<<(std::ostream& os, + const FloatProxy& value) { + os << HexFloat>(value); + return os; +} +} + +#endif // LIBSPIRV_UTIL_HEX_FLOAT_H_ diff --git a/android/x86/include/SPIRV/spirv.hpp b/android/x86/include/SPIRV/spirv.hpp new file mode 100644 index 00000000..dae36cf2 --- /dev/null +++ b/android/x86/include/SPIRV/spirv.hpp @@ -0,0 +1,2114 @@ +// Copyright (c) 2014-2020 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and/or associated documentation files (the "Materials"), +// to deal in the Materials without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Materials, and to permit persons to whom the +// Materials are furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +// IN THE MATERIALS. + +// This header is automatically generated by the same tool that creates +// the Binary Section of the SPIR-V specification. + +// Enumeration tokens for SPIR-V, in various styles: +// C, C++, C++11, JSON, Lua, Python, C#, D +// +// - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL +// - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL +// - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL +// - Lua will use tables, e.g.: spv.SourceLanguage.GLSL +// - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] +// - C# will use enum classes in the Specification class located in the "Spv" namespace, +// e.g.: Spv.Specification.SourceLanguage.GLSL +// - D will have tokens under the "spv" module, e.g: spv.SourceLanguage.GLSL +// +// Some tokens act like mask values, which can be OR'd together, +// while others are mutually exclusive. The mask-like ones have +// "Mask" in their name, and a parallel enum that has the shift +// amount (1 << x) for each corresponding enumerant. + +#ifndef spirv_HPP +#define spirv_HPP + +namespace spv { + +typedef unsigned int Id; + +#define SPV_VERSION 0x10500 +#define SPV_REVISION 3 + +static const unsigned int MagicNumber = 0x07230203; +static const unsigned int Version = 0x00010500; +static const unsigned int Revision = 3; +static const unsigned int OpCodeMask = 0xffff; +static const unsigned int WordCountShift = 16; + +enum SourceLanguage { + SourceLanguageUnknown = 0, + SourceLanguageESSL = 1, + SourceLanguageGLSL = 2, + SourceLanguageOpenCL_C = 3, + SourceLanguageOpenCL_CPP = 4, + SourceLanguageHLSL = 5, + SourceLanguageMax = 0x7fffffff, +}; + +enum ExecutionModel { + ExecutionModelVertex = 0, + ExecutionModelTessellationControl = 1, + ExecutionModelTessellationEvaluation = 2, + ExecutionModelGeometry = 3, + ExecutionModelFragment = 4, + ExecutionModelGLCompute = 5, + ExecutionModelKernel = 6, + ExecutionModelTaskNV = 5267, + ExecutionModelMeshNV = 5268, + ExecutionModelRayGenerationKHR = 5313, + ExecutionModelRayGenerationNV = 5313, + ExecutionModelIntersectionKHR = 5314, + ExecutionModelIntersectionNV = 5314, + ExecutionModelAnyHitKHR = 5315, + ExecutionModelAnyHitNV = 5315, + ExecutionModelClosestHitKHR = 5316, + ExecutionModelClosestHitNV = 5316, + ExecutionModelMissKHR = 5317, + ExecutionModelMissNV = 5317, + ExecutionModelCallableKHR = 5318, + ExecutionModelCallableNV = 5318, + ExecutionModelMax = 0x7fffffff, +}; + +enum AddressingModel { + AddressingModelLogical = 0, + AddressingModelPhysical32 = 1, + AddressingModelPhysical64 = 2, + AddressingModelPhysicalStorageBuffer64 = 5348, + AddressingModelPhysicalStorageBuffer64EXT = 5348, + AddressingModelMax = 0x7fffffff, +}; + +enum MemoryModel { + MemoryModelSimple = 0, + MemoryModelGLSL450 = 1, + MemoryModelOpenCL = 2, + MemoryModelVulkan = 3, + MemoryModelVulkanKHR = 3, + MemoryModelMax = 0x7fffffff, +}; + +enum ExecutionMode { + ExecutionModeInvocations = 0, + ExecutionModeSpacingEqual = 1, + ExecutionModeSpacingFractionalEven = 2, + ExecutionModeSpacingFractionalOdd = 3, + ExecutionModeVertexOrderCw = 4, + ExecutionModeVertexOrderCcw = 5, + ExecutionModePixelCenterInteger = 6, + ExecutionModeOriginUpperLeft = 7, + ExecutionModeOriginLowerLeft = 8, + ExecutionModeEarlyFragmentTests = 9, + ExecutionModePointMode = 10, + ExecutionModeXfb = 11, + ExecutionModeDepthReplacing = 12, + ExecutionModeDepthGreater = 14, + ExecutionModeDepthLess = 15, + ExecutionModeDepthUnchanged = 16, + ExecutionModeLocalSize = 17, + ExecutionModeLocalSizeHint = 18, + ExecutionModeInputPoints = 19, + ExecutionModeInputLines = 20, + ExecutionModeInputLinesAdjacency = 21, + ExecutionModeTriangles = 22, + ExecutionModeInputTrianglesAdjacency = 23, + ExecutionModeQuads = 24, + ExecutionModeIsolines = 25, + ExecutionModeOutputVertices = 26, + ExecutionModeOutputPoints = 27, + ExecutionModeOutputLineStrip = 28, + ExecutionModeOutputTriangleStrip = 29, + ExecutionModeVecTypeHint = 30, + ExecutionModeContractionOff = 31, + ExecutionModeInitializer = 33, + ExecutionModeFinalizer = 34, + ExecutionModeSubgroupSize = 35, + ExecutionModeSubgroupsPerWorkgroup = 36, + ExecutionModeSubgroupsPerWorkgroupId = 37, + ExecutionModeLocalSizeId = 38, + ExecutionModeLocalSizeHintId = 39, + ExecutionModePostDepthCoverage = 4446, + ExecutionModeDenormPreserve = 4459, + ExecutionModeDenormFlushToZero = 4460, + ExecutionModeSignedZeroInfNanPreserve = 4461, + ExecutionModeRoundingModeRTE = 4462, + ExecutionModeRoundingModeRTZ = 4463, + ExecutionModeStencilRefReplacingEXT = 5027, + ExecutionModeOutputLinesNV = 5269, + ExecutionModeOutputPrimitivesNV = 5270, + ExecutionModeDerivativeGroupQuadsNV = 5289, + ExecutionModeDerivativeGroupLinearNV = 5290, + ExecutionModeOutputTrianglesNV = 5298, + ExecutionModePixelInterlockOrderedEXT = 5366, + ExecutionModePixelInterlockUnorderedEXT = 5367, + ExecutionModeSampleInterlockOrderedEXT = 5368, + ExecutionModeSampleInterlockUnorderedEXT = 5369, + ExecutionModeShadingRateInterlockOrderedEXT = 5370, + ExecutionModeShadingRateInterlockUnorderedEXT = 5371, + ExecutionModeMax = 0x7fffffff, +}; + +enum StorageClass { + StorageClassUniformConstant = 0, + StorageClassInput = 1, + StorageClassUniform = 2, + StorageClassOutput = 3, + StorageClassWorkgroup = 4, + StorageClassCrossWorkgroup = 5, + StorageClassPrivate = 6, + StorageClassFunction = 7, + StorageClassGeneric = 8, + StorageClassPushConstant = 9, + StorageClassAtomicCounter = 10, + StorageClassImage = 11, + StorageClassStorageBuffer = 12, + StorageClassCallableDataKHR = 5328, + StorageClassCallableDataNV = 5328, + StorageClassIncomingCallableDataKHR = 5329, + StorageClassIncomingCallableDataNV = 5329, + StorageClassRayPayloadKHR = 5338, + StorageClassRayPayloadNV = 5338, + StorageClassHitAttributeKHR = 5339, + StorageClassHitAttributeNV = 5339, + StorageClassIncomingRayPayloadKHR = 5342, + StorageClassIncomingRayPayloadNV = 5342, + StorageClassShaderRecordBufferKHR = 5343, + StorageClassShaderRecordBufferNV = 5343, + StorageClassPhysicalStorageBuffer = 5349, + StorageClassPhysicalStorageBufferEXT = 5349, + StorageClassMax = 0x7fffffff, +}; + +enum Dim { + Dim1D = 0, + Dim2D = 1, + Dim3D = 2, + DimCube = 3, + DimRect = 4, + DimBuffer = 5, + DimSubpassData = 6, + DimMax = 0x7fffffff, +}; + +enum SamplerAddressingMode { + SamplerAddressingModeNone = 0, + SamplerAddressingModeClampToEdge = 1, + SamplerAddressingModeClamp = 2, + SamplerAddressingModeRepeat = 3, + SamplerAddressingModeRepeatMirrored = 4, + SamplerAddressingModeMax = 0x7fffffff, +}; + +enum SamplerFilterMode { + SamplerFilterModeNearest = 0, + SamplerFilterModeLinear = 1, + SamplerFilterModeMax = 0x7fffffff, +}; + +enum ImageFormat { + ImageFormatUnknown = 0, + ImageFormatRgba32f = 1, + ImageFormatRgba16f = 2, + ImageFormatR32f = 3, + ImageFormatRgba8 = 4, + ImageFormatRgba8Snorm = 5, + ImageFormatRg32f = 6, + ImageFormatRg16f = 7, + ImageFormatR11fG11fB10f = 8, + ImageFormatR16f = 9, + ImageFormatRgba16 = 10, + ImageFormatRgb10A2 = 11, + ImageFormatRg16 = 12, + ImageFormatRg8 = 13, + ImageFormatR16 = 14, + ImageFormatR8 = 15, + ImageFormatRgba16Snorm = 16, + ImageFormatRg16Snorm = 17, + ImageFormatRg8Snorm = 18, + ImageFormatR16Snorm = 19, + ImageFormatR8Snorm = 20, + ImageFormatRgba32i = 21, + ImageFormatRgba16i = 22, + ImageFormatRgba8i = 23, + ImageFormatR32i = 24, + ImageFormatRg32i = 25, + ImageFormatRg16i = 26, + ImageFormatRg8i = 27, + ImageFormatR16i = 28, + ImageFormatR8i = 29, + ImageFormatRgba32ui = 30, + ImageFormatRgba16ui = 31, + ImageFormatRgba8ui = 32, + ImageFormatR32ui = 33, + ImageFormatRgb10a2ui = 34, + ImageFormatRg32ui = 35, + ImageFormatRg16ui = 36, + ImageFormatRg8ui = 37, + ImageFormatR16ui = 38, + ImageFormatR8ui = 39, + ImageFormatMax = 0x7fffffff, +}; + +enum ImageChannelOrder { + ImageChannelOrderR = 0, + ImageChannelOrderA = 1, + ImageChannelOrderRG = 2, + ImageChannelOrderRA = 3, + ImageChannelOrderRGB = 4, + ImageChannelOrderRGBA = 5, + ImageChannelOrderBGRA = 6, + ImageChannelOrderARGB = 7, + ImageChannelOrderIntensity = 8, + ImageChannelOrderLuminance = 9, + ImageChannelOrderRx = 10, + ImageChannelOrderRGx = 11, + ImageChannelOrderRGBx = 12, + ImageChannelOrderDepth = 13, + ImageChannelOrderDepthStencil = 14, + ImageChannelOrdersRGB = 15, + ImageChannelOrdersRGBx = 16, + ImageChannelOrdersRGBA = 17, + ImageChannelOrdersBGRA = 18, + ImageChannelOrderABGR = 19, + ImageChannelOrderMax = 0x7fffffff, +}; + +enum ImageChannelDataType { + ImageChannelDataTypeSnormInt8 = 0, + ImageChannelDataTypeSnormInt16 = 1, + ImageChannelDataTypeUnormInt8 = 2, + ImageChannelDataTypeUnormInt16 = 3, + ImageChannelDataTypeUnormShort565 = 4, + ImageChannelDataTypeUnormShort555 = 5, + ImageChannelDataTypeUnormInt101010 = 6, + ImageChannelDataTypeSignedInt8 = 7, + ImageChannelDataTypeSignedInt16 = 8, + ImageChannelDataTypeSignedInt32 = 9, + ImageChannelDataTypeUnsignedInt8 = 10, + ImageChannelDataTypeUnsignedInt16 = 11, + ImageChannelDataTypeUnsignedInt32 = 12, + ImageChannelDataTypeHalfFloat = 13, + ImageChannelDataTypeFloat = 14, + ImageChannelDataTypeUnormInt24 = 15, + ImageChannelDataTypeUnormInt101010_2 = 16, + ImageChannelDataTypeMax = 0x7fffffff, +}; + +enum ImageOperandsShift { + ImageOperandsBiasShift = 0, + ImageOperandsLodShift = 1, + ImageOperandsGradShift = 2, + ImageOperandsConstOffsetShift = 3, + ImageOperandsOffsetShift = 4, + ImageOperandsConstOffsetsShift = 5, + ImageOperandsSampleShift = 6, + ImageOperandsMinLodShift = 7, + ImageOperandsMakeTexelAvailableShift = 8, + ImageOperandsMakeTexelAvailableKHRShift = 8, + ImageOperandsMakeTexelVisibleShift = 9, + ImageOperandsMakeTexelVisibleKHRShift = 9, + ImageOperandsNonPrivateTexelShift = 10, + ImageOperandsNonPrivateTexelKHRShift = 10, + ImageOperandsVolatileTexelShift = 11, + ImageOperandsVolatileTexelKHRShift = 11, + ImageOperandsSignExtendShift = 12, + ImageOperandsZeroExtendShift = 13, + ImageOperandsMax = 0x7fffffff, +}; + +enum ImageOperandsMask { + ImageOperandsMaskNone = 0, + ImageOperandsBiasMask = 0x00000001, + ImageOperandsLodMask = 0x00000002, + ImageOperandsGradMask = 0x00000004, + ImageOperandsConstOffsetMask = 0x00000008, + ImageOperandsOffsetMask = 0x00000010, + ImageOperandsConstOffsetsMask = 0x00000020, + ImageOperandsSampleMask = 0x00000040, + ImageOperandsMinLodMask = 0x00000080, + ImageOperandsMakeTexelAvailableMask = 0x00000100, + ImageOperandsMakeTexelAvailableKHRMask = 0x00000100, + ImageOperandsMakeTexelVisibleMask = 0x00000200, + ImageOperandsMakeTexelVisibleKHRMask = 0x00000200, + ImageOperandsNonPrivateTexelMask = 0x00000400, + ImageOperandsNonPrivateTexelKHRMask = 0x00000400, + ImageOperandsVolatileTexelMask = 0x00000800, + ImageOperandsVolatileTexelKHRMask = 0x00000800, + ImageOperandsSignExtendMask = 0x00001000, + ImageOperandsZeroExtendMask = 0x00002000, +}; + +enum FPFastMathModeShift { + FPFastMathModeNotNaNShift = 0, + FPFastMathModeNotInfShift = 1, + FPFastMathModeNSZShift = 2, + FPFastMathModeAllowRecipShift = 3, + FPFastMathModeFastShift = 4, + FPFastMathModeMax = 0x7fffffff, +}; + +enum FPFastMathModeMask { + FPFastMathModeMaskNone = 0, + FPFastMathModeNotNaNMask = 0x00000001, + FPFastMathModeNotInfMask = 0x00000002, + FPFastMathModeNSZMask = 0x00000004, + FPFastMathModeAllowRecipMask = 0x00000008, + FPFastMathModeFastMask = 0x00000010, +}; + +enum FPRoundingMode { + FPRoundingModeRTE = 0, + FPRoundingModeRTZ = 1, + FPRoundingModeRTP = 2, + FPRoundingModeRTN = 3, + FPRoundingModeMax = 0x7fffffff, +}; + +enum LinkageType { + LinkageTypeExport = 0, + LinkageTypeImport = 1, + LinkageTypeMax = 0x7fffffff, +}; + +enum AccessQualifier { + AccessQualifierReadOnly = 0, + AccessQualifierWriteOnly = 1, + AccessQualifierReadWrite = 2, + AccessQualifierMax = 0x7fffffff, +}; + +enum FunctionParameterAttribute { + FunctionParameterAttributeZext = 0, + FunctionParameterAttributeSext = 1, + FunctionParameterAttributeByVal = 2, + FunctionParameterAttributeSret = 3, + FunctionParameterAttributeNoAlias = 4, + FunctionParameterAttributeNoCapture = 5, + FunctionParameterAttributeNoWrite = 6, + FunctionParameterAttributeNoReadWrite = 7, + FunctionParameterAttributeMax = 0x7fffffff, +}; + +enum Decoration { + DecorationRelaxedPrecision = 0, + DecorationSpecId = 1, + DecorationBlock = 2, + DecorationBufferBlock = 3, + DecorationRowMajor = 4, + DecorationColMajor = 5, + DecorationArrayStride = 6, + DecorationMatrixStride = 7, + DecorationGLSLShared = 8, + DecorationGLSLPacked = 9, + DecorationCPacked = 10, + DecorationBuiltIn = 11, + DecorationNoPerspective = 13, + DecorationFlat = 14, + DecorationPatch = 15, + DecorationCentroid = 16, + DecorationSample = 17, + DecorationInvariant = 18, + DecorationRestrict = 19, + DecorationAliased = 20, + DecorationVolatile = 21, + DecorationConstant = 22, + DecorationCoherent = 23, + DecorationNonWritable = 24, + DecorationNonReadable = 25, + DecorationUniform = 26, + DecorationUniformId = 27, + DecorationSaturatedConversion = 28, + DecorationStream = 29, + DecorationLocation = 30, + DecorationComponent = 31, + DecorationIndex = 32, + DecorationBinding = 33, + DecorationDescriptorSet = 34, + DecorationOffset = 35, + DecorationXfbBuffer = 36, + DecorationXfbStride = 37, + DecorationFuncParamAttr = 38, + DecorationFPRoundingMode = 39, + DecorationFPFastMathMode = 40, + DecorationLinkageAttributes = 41, + DecorationNoContraction = 42, + DecorationInputAttachmentIndex = 43, + DecorationAlignment = 44, + DecorationMaxByteOffset = 45, + DecorationAlignmentId = 46, + DecorationMaxByteOffsetId = 47, + DecorationNoSignedWrap = 4469, + DecorationNoUnsignedWrap = 4470, + DecorationExplicitInterpAMD = 4999, + DecorationOverrideCoverageNV = 5248, + DecorationPassthroughNV = 5250, + DecorationViewportRelativeNV = 5252, + DecorationSecondaryViewportRelativeNV = 5256, + DecorationPerPrimitiveNV = 5271, + DecorationPerViewNV = 5272, + DecorationPerTaskNV = 5273, + DecorationPerVertexNV = 5285, + DecorationNonUniform = 5300, + DecorationNonUniformEXT = 5300, + DecorationRestrictPointer = 5355, + DecorationRestrictPointerEXT = 5355, + DecorationAliasedPointer = 5356, + DecorationAliasedPointerEXT = 5356, + DecorationCounterBuffer = 5634, + DecorationHlslCounterBufferGOOGLE = 5634, + DecorationHlslSemanticGOOGLE = 5635, + DecorationUserSemantic = 5635, + DecorationUserTypeGOOGLE = 5636, + DecorationMax = 0x7fffffff, +}; + +enum BuiltIn { + BuiltInPosition = 0, + BuiltInPointSize = 1, + BuiltInClipDistance = 3, + BuiltInCullDistance = 4, + BuiltInVertexId = 5, + BuiltInInstanceId = 6, + BuiltInPrimitiveId = 7, + BuiltInInvocationId = 8, + BuiltInLayer = 9, + BuiltInViewportIndex = 10, + BuiltInTessLevelOuter = 11, + BuiltInTessLevelInner = 12, + BuiltInTessCoord = 13, + BuiltInPatchVertices = 14, + BuiltInFragCoord = 15, + BuiltInPointCoord = 16, + BuiltInFrontFacing = 17, + BuiltInSampleId = 18, + BuiltInSamplePosition = 19, + BuiltInSampleMask = 20, + BuiltInFragDepth = 22, + BuiltInHelperInvocation = 23, + BuiltInNumWorkgroups = 24, + BuiltInWorkgroupSize = 25, + BuiltInWorkgroupId = 26, + BuiltInLocalInvocationId = 27, + BuiltInGlobalInvocationId = 28, + BuiltInLocalInvocationIndex = 29, + BuiltInWorkDim = 30, + BuiltInGlobalSize = 31, + BuiltInEnqueuedWorkgroupSize = 32, + BuiltInGlobalOffset = 33, + BuiltInGlobalLinearId = 34, + BuiltInSubgroupSize = 36, + BuiltInSubgroupMaxSize = 37, + BuiltInNumSubgroups = 38, + BuiltInNumEnqueuedSubgroups = 39, + BuiltInSubgroupId = 40, + BuiltInSubgroupLocalInvocationId = 41, + BuiltInVertexIndex = 42, + BuiltInInstanceIndex = 43, + BuiltInSubgroupEqMask = 4416, + BuiltInSubgroupEqMaskKHR = 4416, + BuiltInSubgroupGeMask = 4417, + BuiltInSubgroupGeMaskKHR = 4417, + BuiltInSubgroupGtMask = 4418, + BuiltInSubgroupGtMaskKHR = 4418, + BuiltInSubgroupLeMask = 4419, + BuiltInSubgroupLeMaskKHR = 4419, + BuiltInSubgroupLtMask = 4420, + BuiltInSubgroupLtMaskKHR = 4420, + BuiltInBaseVertex = 4424, + BuiltInBaseInstance = 4425, + BuiltInDrawIndex = 4426, + BuiltInDeviceIndex = 4438, + BuiltInViewIndex = 4440, + BuiltInBaryCoordNoPerspAMD = 4992, + BuiltInBaryCoordNoPerspCentroidAMD = 4993, + BuiltInBaryCoordNoPerspSampleAMD = 4994, + BuiltInBaryCoordSmoothAMD = 4995, + BuiltInBaryCoordSmoothCentroidAMD = 4996, + BuiltInBaryCoordSmoothSampleAMD = 4997, + BuiltInBaryCoordPullModelAMD = 4998, + BuiltInFragStencilRefEXT = 5014, + BuiltInViewportMaskNV = 5253, + BuiltInSecondaryPositionNV = 5257, + BuiltInSecondaryViewportMaskNV = 5258, + BuiltInPositionPerViewNV = 5261, + BuiltInViewportMaskPerViewNV = 5262, + BuiltInFullyCoveredEXT = 5264, + BuiltInTaskCountNV = 5274, + BuiltInPrimitiveCountNV = 5275, + BuiltInPrimitiveIndicesNV = 5276, + BuiltInClipDistancePerViewNV = 5277, + BuiltInCullDistancePerViewNV = 5278, + BuiltInLayerPerViewNV = 5279, + BuiltInMeshViewCountNV = 5280, + BuiltInMeshViewIndicesNV = 5281, + BuiltInBaryCoordNV = 5286, + BuiltInBaryCoordNoPerspNV = 5287, + BuiltInFragSizeEXT = 5292, + BuiltInFragmentSizeNV = 5292, + BuiltInFragInvocationCountEXT = 5293, + BuiltInInvocationsPerPixelNV = 5293, + BuiltInLaunchIdKHR = 5319, + BuiltInLaunchIdNV = 5319, + BuiltInLaunchSizeKHR = 5320, + BuiltInLaunchSizeNV = 5320, + BuiltInWorldRayOriginKHR = 5321, + BuiltInWorldRayOriginNV = 5321, + BuiltInWorldRayDirectionKHR = 5322, + BuiltInWorldRayDirectionNV = 5322, + BuiltInObjectRayOriginKHR = 5323, + BuiltInObjectRayOriginNV = 5323, + BuiltInObjectRayDirectionKHR = 5324, + BuiltInObjectRayDirectionNV = 5324, + BuiltInRayTminKHR = 5325, + BuiltInRayTminNV = 5325, + BuiltInRayTmaxKHR = 5326, + BuiltInRayTmaxNV = 5326, + BuiltInInstanceCustomIndexKHR = 5327, + BuiltInInstanceCustomIndexNV = 5327, + BuiltInObjectToWorldKHR = 5330, + BuiltInObjectToWorldNV = 5330, + BuiltInWorldToObjectKHR = 5331, + BuiltInWorldToObjectNV = 5331, + BuiltInHitTKHR = 5332, + BuiltInHitTNV = 5332, + BuiltInHitKindKHR = 5333, + BuiltInHitKindNV = 5333, + BuiltInIncomingRayFlagsKHR = 5351, + BuiltInIncomingRayFlagsNV = 5351, + BuiltInRayGeometryIndexKHR = 5352, + BuiltInWarpsPerSMNV = 5374, + BuiltInSMCountNV = 5375, + BuiltInWarpIDNV = 5376, + BuiltInSMIDNV = 5377, + BuiltInMax = 0x7fffffff, +}; + +enum SelectionControlShift { + SelectionControlFlattenShift = 0, + SelectionControlDontFlattenShift = 1, + SelectionControlMax = 0x7fffffff, +}; + +enum SelectionControlMask { + SelectionControlMaskNone = 0, + SelectionControlFlattenMask = 0x00000001, + SelectionControlDontFlattenMask = 0x00000002, +}; + +enum LoopControlShift { + LoopControlUnrollShift = 0, + LoopControlDontUnrollShift = 1, + LoopControlDependencyInfiniteShift = 2, + LoopControlDependencyLengthShift = 3, + LoopControlMinIterationsShift = 4, + LoopControlMaxIterationsShift = 5, + LoopControlIterationMultipleShift = 6, + LoopControlPeelCountShift = 7, + LoopControlPartialCountShift = 8, + LoopControlMax = 0x7fffffff, +}; + +enum LoopControlMask { + LoopControlMaskNone = 0, + LoopControlUnrollMask = 0x00000001, + LoopControlDontUnrollMask = 0x00000002, + LoopControlDependencyInfiniteMask = 0x00000004, + LoopControlDependencyLengthMask = 0x00000008, + LoopControlMinIterationsMask = 0x00000010, + LoopControlMaxIterationsMask = 0x00000020, + LoopControlIterationMultipleMask = 0x00000040, + LoopControlPeelCountMask = 0x00000080, + LoopControlPartialCountMask = 0x00000100, +}; + +enum FunctionControlShift { + FunctionControlInlineShift = 0, + FunctionControlDontInlineShift = 1, + FunctionControlPureShift = 2, + FunctionControlConstShift = 3, + FunctionControlMax = 0x7fffffff, +}; + +enum FunctionControlMask { + FunctionControlMaskNone = 0, + FunctionControlInlineMask = 0x00000001, + FunctionControlDontInlineMask = 0x00000002, + FunctionControlPureMask = 0x00000004, + FunctionControlConstMask = 0x00000008, +}; + +enum MemorySemanticsShift { + MemorySemanticsAcquireShift = 1, + MemorySemanticsReleaseShift = 2, + MemorySemanticsAcquireReleaseShift = 3, + MemorySemanticsSequentiallyConsistentShift = 4, + MemorySemanticsUniformMemoryShift = 6, + MemorySemanticsSubgroupMemoryShift = 7, + MemorySemanticsWorkgroupMemoryShift = 8, + MemorySemanticsCrossWorkgroupMemoryShift = 9, + MemorySemanticsAtomicCounterMemoryShift = 10, + MemorySemanticsImageMemoryShift = 11, + MemorySemanticsOutputMemoryShift = 12, + MemorySemanticsOutputMemoryKHRShift = 12, + MemorySemanticsMakeAvailableShift = 13, + MemorySemanticsMakeAvailableKHRShift = 13, + MemorySemanticsMakeVisibleShift = 14, + MemorySemanticsMakeVisibleKHRShift = 14, + MemorySemanticsVolatileShift = 15, + MemorySemanticsMax = 0x7fffffff, +}; + +enum MemorySemanticsMask { + MemorySemanticsMaskNone = 0, + MemorySemanticsAcquireMask = 0x00000002, + MemorySemanticsReleaseMask = 0x00000004, + MemorySemanticsAcquireReleaseMask = 0x00000008, + MemorySemanticsSequentiallyConsistentMask = 0x00000010, + MemorySemanticsUniformMemoryMask = 0x00000040, + MemorySemanticsSubgroupMemoryMask = 0x00000080, + MemorySemanticsWorkgroupMemoryMask = 0x00000100, + MemorySemanticsCrossWorkgroupMemoryMask = 0x00000200, + MemorySemanticsAtomicCounterMemoryMask = 0x00000400, + MemorySemanticsImageMemoryMask = 0x00000800, + MemorySemanticsOutputMemoryMask = 0x00001000, + MemorySemanticsOutputMemoryKHRMask = 0x00001000, + MemorySemanticsMakeAvailableMask = 0x00002000, + MemorySemanticsMakeAvailableKHRMask = 0x00002000, + MemorySemanticsMakeVisibleMask = 0x00004000, + MemorySemanticsMakeVisibleKHRMask = 0x00004000, + MemorySemanticsVolatileMask = 0x00008000, +}; + +enum MemoryAccessShift { + MemoryAccessVolatileShift = 0, + MemoryAccessAlignedShift = 1, + MemoryAccessNontemporalShift = 2, + MemoryAccessMakePointerAvailableShift = 3, + MemoryAccessMakePointerAvailableKHRShift = 3, + MemoryAccessMakePointerVisibleShift = 4, + MemoryAccessMakePointerVisibleKHRShift = 4, + MemoryAccessNonPrivatePointerShift = 5, + MemoryAccessNonPrivatePointerKHRShift = 5, + MemoryAccessMax = 0x7fffffff, +}; + +enum MemoryAccessMask { + MemoryAccessMaskNone = 0, + MemoryAccessVolatileMask = 0x00000001, + MemoryAccessAlignedMask = 0x00000002, + MemoryAccessNontemporalMask = 0x00000004, + MemoryAccessMakePointerAvailableMask = 0x00000008, + MemoryAccessMakePointerAvailableKHRMask = 0x00000008, + MemoryAccessMakePointerVisibleMask = 0x00000010, + MemoryAccessMakePointerVisibleKHRMask = 0x00000010, + MemoryAccessNonPrivatePointerMask = 0x00000020, + MemoryAccessNonPrivatePointerKHRMask = 0x00000020, +}; + +enum Scope { + ScopeCrossDevice = 0, + ScopeDevice = 1, + ScopeWorkgroup = 2, + ScopeSubgroup = 3, + ScopeInvocation = 4, + ScopeQueueFamily = 5, + ScopeQueueFamilyKHR = 5, + ScopeShaderCallKHR = 6, + ScopeMax = 0x7fffffff, +}; + +enum GroupOperation { + GroupOperationReduce = 0, + GroupOperationInclusiveScan = 1, + GroupOperationExclusiveScan = 2, + GroupOperationClusteredReduce = 3, + GroupOperationPartitionedReduceNV = 6, + GroupOperationPartitionedInclusiveScanNV = 7, + GroupOperationPartitionedExclusiveScanNV = 8, + GroupOperationMax = 0x7fffffff, +}; + +enum KernelEnqueueFlags { + KernelEnqueueFlagsNoWait = 0, + KernelEnqueueFlagsWaitKernel = 1, + KernelEnqueueFlagsWaitWorkGroup = 2, + KernelEnqueueFlagsMax = 0x7fffffff, +}; + +enum KernelProfilingInfoShift { + KernelProfilingInfoCmdExecTimeShift = 0, + KernelProfilingInfoMax = 0x7fffffff, +}; + +enum KernelProfilingInfoMask { + KernelProfilingInfoMaskNone = 0, + KernelProfilingInfoCmdExecTimeMask = 0x00000001, +}; + +enum Capability { + CapabilityMatrix = 0, + CapabilityShader = 1, + CapabilityGeometry = 2, + CapabilityTessellation = 3, + CapabilityAddresses = 4, + CapabilityLinkage = 5, + CapabilityKernel = 6, + CapabilityVector16 = 7, + CapabilityFloat16Buffer = 8, + CapabilityFloat16 = 9, + CapabilityFloat64 = 10, + CapabilityInt64 = 11, + CapabilityInt64Atomics = 12, + CapabilityImageBasic = 13, + CapabilityImageReadWrite = 14, + CapabilityImageMipmap = 15, + CapabilityPipes = 17, + CapabilityGroups = 18, + CapabilityDeviceEnqueue = 19, + CapabilityLiteralSampler = 20, + CapabilityAtomicStorage = 21, + CapabilityInt16 = 22, + CapabilityTessellationPointSize = 23, + CapabilityGeometryPointSize = 24, + CapabilityImageGatherExtended = 25, + CapabilityStorageImageMultisample = 27, + CapabilityUniformBufferArrayDynamicIndexing = 28, + CapabilitySampledImageArrayDynamicIndexing = 29, + CapabilityStorageBufferArrayDynamicIndexing = 30, + CapabilityStorageImageArrayDynamicIndexing = 31, + CapabilityClipDistance = 32, + CapabilityCullDistance = 33, + CapabilityImageCubeArray = 34, + CapabilitySampleRateShading = 35, + CapabilityImageRect = 36, + CapabilitySampledRect = 37, + CapabilityGenericPointer = 38, + CapabilityInt8 = 39, + CapabilityInputAttachment = 40, + CapabilitySparseResidency = 41, + CapabilityMinLod = 42, + CapabilitySampled1D = 43, + CapabilityImage1D = 44, + CapabilitySampledCubeArray = 45, + CapabilitySampledBuffer = 46, + CapabilityImageBuffer = 47, + CapabilityImageMSArray = 48, + CapabilityStorageImageExtendedFormats = 49, + CapabilityImageQuery = 50, + CapabilityDerivativeControl = 51, + CapabilityInterpolationFunction = 52, + CapabilityTransformFeedback = 53, + CapabilityGeometryStreams = 54, + CapabilityStorageImageReadWithoutFormat = 55, + CapabilityStorageImageWriteWithoutFormat = 56, + CapabilityMultiViewport = 57, + CapabilitySubgroupDispatch = 58, + CapabilityNamedBarrier = 59, + CapabilityPipeStorage = 60, + CapabilityGroupNonUniform = 61, + CapabilityGroupNonUniformVote = 62, + CapabilityGroupNonUniformArithmetic = 63, + CapabilityGroupNonUniformBallot = 64, + CapabilityGroupNonUniformShuffle = 65, + CapabilityGroupNonUniformShuffleRelative = 66, + CapabilityGroupNonUniformClustered = 67, + CapabilityGroupNonUniformQuad = 68, + CapabilityShaderLayer = 69, + CapabilityShaderViewportIndex = 70, + CapabilitySubgroupBallotKHR = 4423, + CapabilityDrawParameters = 4427, + CapabilitySubgroupVoteKHR = 4431, + CapabilityStorageBuffer16BitAccess = 4433, + CapabilityStorageUniformBufferBlock16 = 4433, + CapabilityStorageUniform16 = 4434, + CapabilityUniformAndStorageBuffer16BitAccess = 4434, + CapabilityStoragePushConstant16 = 4435, + CapabilityStorageInputOutput16 = 4436, + CapabilityDeviceGroup = 4437, + CapabilityMultiView = 4439, + CapabilityVariablePointersStorageBuffer = 4441, + CapabilityVariablePointers = 4442, + CapabilityAtomicStorageOps = 4445, + CapabilitySampleMaskPostDepthCoverage = 4447, + CapabilityStorageBuffer8BitAccess = 4448, + CapabilityUniformAndStorageBuffer8BitAccess = 4449, + CapabilityStoragePushConstant8 = 4450, + CapabilityDenormPreserve = 4464, + CapabilityDenormFlushToZero = 4465, + CapabilitySignedZeroInfNanPreserve = 4466, + CapabilityRoundingModeRTE = 4467, + CapabilityRoundingModeRTZ = 4468, + CapabilityRayQueryProvisionalKHR = 4471, + CapabilityRayTraversalPrimitiveCullingProvisionalKHR = 4478, + CapabilityFloat16ImageAMD = 5008, + CapabilityImageGatherBiasLodAMD = 5009, + CapabilityFragmentMaskAMD = 5010, + CapabilityStencilExportEXT = 5013, + CapabilityImageReadWriteLodAMD = 5015, + CapabilityShaderClockKHR = 5055, + CapabilitySampleMaskOverrideCoverageNV = 5249, + CapabilityGeometryShaderPassthroughNV = 5251, + CapabilityShaderViewportIndexLayerEXT = 5254, + CapabilityShaderViewportIndexLayerNV = 5254, + CapabilityShaderViewportMaskNV = 5255, + CapabilityShaderStereoViewNV = 5259, + CapabilityPerViewAttributesNV = 5260, + CapabilityFragmentFullyCoveredEXT = 5265, + CapabilityMeshShadingNV = 5266, + CapabilityImageFootprintNV = 5282, + CapabilityFragmentBarycentricNV = 5284, + CapabilityComputeDerivativeGroupQuadsNV = 5288, + CapabilityFragmentDensityEXT = 5291, + CapabilityShadingRateNV = 5291, + CapabilityGroupNonUniformPartitionedNV = 5297, + CapabilityShaderNonUniform = 5301, + CapabilityShaderNonUniformEXT = 5301, + CapabilityRuntimeDescriptorArray = 5302, + CapabilityRuntimeDescriptorArrayEXT = 5302, + CapabilityInputAttachmentArrayDynamicIndexing = 5303, + CapabilityInputAttachmentArrayDynamicIndexingEXT = 5303, + CapabilityUniformTexelBufferArrayDynamicIndexing = 5304, + CapabilityUniformTexelBufferArrayDynamicIndexingEXT = 5304, + CapabilityStorageTexelBufferArrayDynamicIndexing = 5305, + CapabilityStorageTexelBufferArrayDynamicIndexingEXT = 5305, + CapabilityUniformBufferArrayNonUniformIndexing = 5306, + CapabilityUniformBufferArrayNonUniformIndexingEXT = 5306, + CapabilitySampledImageArrayNonUniformIndexing = 5307, + CapabilitySampledImageArrayNonUniformIndexingEXT = 5307, + CapabilityStorageBufferArrayNonUniformIndexing = 5308, + CapabilityStorageBufferArrayNonUniformIndexingEXT = 5308, + CapabilityStorageImageArrayNonUniformIndexing = 5309, + CapabilityStorageImageArrayNonUniformIndexingEXT = 5309, + CapabilityInputAttachmentArrayNonUniformIndexing = 5310, + CapabilityInputAttachmentArrayNonUniformIndexingEXT = 5310, + CapabilityUniformTexelBufferArrayNonUniformIndexing = 5311, + CapabilityUniformTexelBufferArrayNonUniformIndexingEXT = 5311, + CapabilityStorageTexelBufferArrayNonUniformIndexing = 5312, + CapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312, + CapabilityRayTracingNV = 5340, + CapabilityVulkanMemoryModel = 5345, + CapabilityVulkanMemoryModelKHR = 5345, + CapabilityVulkanMemoryModelDeviceScope = 5346, + CapabilityVulkanMemoryModelDeviceScopeKHR = 5346, + CapabilityPhysicalStorageBufferAddresses = 5347, + CapabilityPhysicalStorageBufferAddressesEXT = 5347, + CapabilityComputeDerivativeGroupLinearNV = 5350, + CapabilityRayTracingProvisionalKHR = 5353, + CapabilityCooperativeMatrixNV = 5357, + CapabilityFragmentShaderSampleInterlockEXT = 5363, + CapabilityFragmentShaderShadingRateInterlockEXT = 5372, + CapabilityShaderSMBuiltinsNV = 5373, + CapabilityFragmentShaderPixelInterlockEXT = 5378, + CapabilityDemoteToHelperInvocationEXT = 5379, + CapabilitySubgroupShuffleINTEL = 5568, + CapabilitySubgroupBufferBlockIOINTEL = 5569, + CapabilitySubgroupImageBlockIOINTEL = 5570, + CapabilitySubgroupImageMediaBlockIOINTEL = 5579, + CapabilityIntegerFunctions2INTEL = 5584, + CapabilitySubgroupAvcMotionEstimationINTEL = 5696, + CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697, + CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698, + CapabilityMax = 0x7fffffff, +}; + +enum RayFlagsShift { + RayFlagsOpaqueKHRShift = 0, + RayFlagsNoOpaqueKHRShift = 1, + RayFlagsTerminateOnFirstHitKHRShift = 2, + RayFlagsSkipClosestHitShaderKHRShift = 3, + RayFlagsCullBackFacingTrianglesKHRShift = 4, + RayFlagsCullFrontFacingTrianglesKHRShift = 5, + RayFlagsCullOpaqueKHRShift = 6, + RayFlagsCullNoOpaqueKHRShift = 7, + RayFlagsSkipTrianglesKHRShift = 8, + RayFlagsSkipAABBsKHRShift = 9, + RayFlagsMax = 0x7fffffff, +}; + +enum RayFlagsMask { + RayFlagsMaskNone = 0, + RayFlagsOpaqueKHRMask = 0x00000001, + RayFlagsNoOpaqueKHRMask = 0x00000002, + RayFlagsTerminateOnFirstHitKHRMask = 0x00000004, + RayFlagsSkipClosestHitShaderKHRMask = 0x00000008, + RayFlagsCullBackFacingTrianglesKHRMask = 0x00000010, + RayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020, + RayFlagsCullOpaqueKHRMask = 0x00000040, + RayFlagsCullNoOpaqueKHRMask = 0x00000080, + RayFlagsSkipTrianglesKHRMask = 0x00000100, + RayFlagsSkipAABBsKHRMask = 0x00000200, +}; + +enum RayQueryIntersection { + RayQueryIntersectionRayQueryCandidateIntersectionKHR = 0, + RayQueryIntersectionRayQueryCommittedIntersectionKHR = 1, + RayQueryIntersectionMax = 0x7fffffff, +}; + +enum RayQueryCommittedIntersectionType { + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR = 0, + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR = 1, + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR = 2, + RayQueryCommittedIntersectionTypeMax = 0x7fffffff, +}; + +enum RayQueryCandidateIntersectionType { + RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR = 0, + RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR = 1, + RayQueryCandidateIntersectionTypeMax = 0x7fffffff, +}; + +enum Op { + OpNop = 0, + OpUndef = 1, + OpSourceContinued = 2, + OpSource = 3, + OpSourceExtension = 4, + OpName = 5, + OpMemberName = 6, + OpString = 7, + OpLine = 8, + OpExtension = 10, + OpExtInstImport = 11, + OpExtInst = 12, + OpMemoryModel = 14, + OpEntryPoint = 15, + OpExecutionMode = 16, + OpCapability = 17, + OpTypeVoid = 19, + OpTypeBool = 20, + OpTypeInt = 21, + OpTypeFloat = 22, + OpTypeVector = 23, + OpTypeMatrix = 24, + OpTypeImage = 25, + OpTypeSampler = 26, + OpTypeSampledImage = 27, + OpTypeArray = 28, + OpTypeRuntimeArray = 29, + OpTypeStruct = 30, + OpTypeOpaque = 31, + OpTypePointer = 32, + OpTypeFunction = 33, + OpTypeEvent = 34, + OpTypeDeviceEvent = 35, + OpTypeReserveId = 36, + OpTypeQueue = 37, + OpTypePipe = 38, + OpTypeForwardPointer = 39, + OpConstantTrue = 41, + OpConstantFalse = 42, + OpConstant = 43, + OpConstantComposite = 44, + OpConstantSampler = 45, + OpConstantNull = 46, + OpSpecConstantTrue = 48, + OpSpecConstantFalse = 49, + OpSpecConstant = 50, + OpSpecConstantComposite = 51, + OpSpecConstantOp = 52, + OpFunction = 54, + OpFunctionParameter = 55, + OpFunctionEnd = 56, + OpFunctionCall = 57, + OpVariable = 59, + OpImageTexelPointer = 60, + OpLoad = 61, + OpStore = 62, + OpCopyMemory = 63, + OpCopyMemorySized = 64, + OpAccessChain = 65, + OpInBoundsAccessChain = 66, + OpPtrAccessChain = 67, + OpArrayLength = 68, + OpGenericPtrMemSemantics = 69, + OpInBoundsPtrAccessChain = 70, + OpDecorate = 71, + OpMemberDecorate = 72, + OpDecorationGroup = 73, + OpGroupDecorate = 74, + OpGroupMemberDecorate = 75, + OpVectorExtractDynamic = 77, + OpVectorInsertDynamic = 78, + OpVectorShuffle = 79, + OpCompositeConstruct = 80, + OpCompositeExtract = 81, + OpCompositeInsert = 82, + OpCopyObject = 83, + OpTranspose = 84, + OpSampledImage = 86, + OpImageSampleImplicitLod = 87, + OpImageSampleExplicitLod = 88, + OpImageSampleDrefImplicitLod = 89, + OpImageSampleDrefExplicitLod = 90, + OpImageSampleProjImplicitLod = 91, + OpImageSampleProjExplicitLod = 92, + OpImageSampleProjDrefImplicitLod = 93, + OpImageSampleProjDrefExplicitLod = 94, + OpImageFetch = 95, + OpImageGather = 96, + OpImageDrefGather = 97, + OpImageRead = 98, + OpImageWrite = 99, + OpImage = 100, + OpImageQueryFormat = 101, + OpImageQueryOrder = 102, + OpImageQuerySizeLod = 103, + OpImageQuerySize = 104, + OpImageQueryLod = 105, + OpImageQueryLevels = 106, + OpImageQuerySamples = 107, + OpConvertFToU = 109, + OpConvertFToS = 110, + OpConvertSToF = 111, + OpConvertUToF = 112, + OpUConvert = 113, + OpSConvert = 114, + OpFConvert = 115, + OpQuantizeToF16 = 116, + OpConvertPtrToU = 117, + OpSatConvertSToU = 118, + OpSatConvertUToS = 119, + OpConvertUToPtr = 120, + OpPtrCastToGeneric = 121, + OpGenericCastToPtr = 122, + OpGenericCastToPtrExplicit = 123, + OpBitcast = 124, + OpSNegate = 126, + OpFNegate = 127, + OpIAdd = 128, + OpFAdd = 129, + OpISub = 130, + OpFSub = 131, + OpIMul = 132, + OpFMul = 133, + OpUDiv = 134, + OpSDiv = 135, + OpFDiv = 136, + OpUMod = 137, + OpSRem = 138, + OpSMod = 139, + OpFRem = 140, + OpFMod = 141, + OpVectorTimesScalar = 142, + OpMatrixTimesScalar = 143, + OpVectorTimesMatrix = 144, + OpMatrixTimesVector = 145, + OpMatrixTimesMatrix = 146, + OpOuterProduct = 147, + OpDot = 148, + OpIAddCarry = 149, + OpISubBorrow = 150, + OpUMulExtended = 151, + OpSMulExtended = 152, + OpAny = 154, + OpAll = 155, + OpIsNan = 156, + OpIsInf = 157, + OpIsFinite = 158, + OpIsNormal = 159, + OpSignBitSet = 160, + OpLessOrGreater = 161, + OpOrdered = 162, + OpUnordered = 163, + OpLogicalEqual = 164, + OpLogicalNotEqual = 165, + OpLogicalOr = 166, + OpLogicalAnd = 167, + OpLogicalNot = 168, + OpSelect = 169, + OpIEqual = 170, + OpINotEqual = 171, + OpUGreaterThan = 172, + OpSGreaterThan = 173, + OpUGreaterThanEqual = 174, + OpSGreaterThanEqual = 175, + OpULessThan = 176, + OpSLessThan = 177, + OpULessThanEqual = 178, + OpSLessThanEqual = 179, + OpFOrdEqual = 180, + OpFUnordEqual = 181, + OpFOrdNotEqual = 182, + OpFUnordNotEqual = 183, + OpFOrdLessThan = 184, + OpFUnordLessThan = 185, + OpFOrdGreaterThan = 186, + OpFUnordGreaterThan = 187, + OpFOrdLessThanEqual = 188, + OpFUnordLessThanEqual = 189, + OpFOrdGreaterThanEqual = 190, + OpFUnordGreaterThanEqual = 191, + OpShiftRightLogical = 194, + OpShiftRightArithmetic = 195, + OpShiftLeftLogical = 196, + OpBitwiseOr = 197, + OpBitwiseXor = 198, + OpBitwiseAnd = 199, + OpNot = 200, + OpBitFieldInsert = 201, + OpBitFieldSExtract = 202, + OpBitFieldUExtract = 203, + OpBitReverse = 204, + OpBitCount = 205, + OpDPdx = 207, + OpDPdy = 208, + OpFwidth = 209, + OpDPdxFine = 210, + OpDPdyFine = 211, + OpFwidthFine = 212, + OpDPdxCoarse = 213, + OpDPdyCoarse = 214, + OpFwidthCoarse = 215, + OpEmitVertex = 218, + OpEndPrimitive = 219, + OpEmitStreamVertex = 220, + OpEndStreamPrimitive = 221, + OpControlBarrier = 224, + OpMemoryBarrier = 225, + OpAtomicLoad = 227, + OpAtomicStore = 228, + OpAtomicExchange = 229, + OpAtomicCompareExchange = 230, + OpAtomicCompareExchangeWeak = 231, + OpAtomicIIncrement = 232, + OpAtomicIDecrement = 233, + OpAtomicIAdd = 234, + OpAtomicISub = 235, + OpAtomicSMin = 236, + OpAtomicUMin = 237, + OpAtomicSMax = 238, + OpAtomicUMax = 239, + OpAtomicAnd = 240, + OpAtomicOr = 241, + OpAtomicXor = 242, + OpPhi = 245, + OpLoopMerge = 246, + OpSelectionMerge = 247, + OpLabel = 248, + OpBranch = 249, + OpBranchConditional = 250, + OpSwitch = 251, + OpKill = 252, + OpReturn = 253, + OpReturnValue = 254, + OpUnreachable = 255, + OpLifetimeStart = 256, + OpLifetimeStop = 257, + OpGroupAsyncCopy = 259, + OpGroupWaitEvents = 260, + OpGroupAll = 261, + OpGroupAny = 262, + OpGroupBroadcast = 263, + OpGroupIAdd = 264, + OpGroupFAdd = 265, + OpGroupFMin = 266, + OpGroupUMin = 267, + OpGroupSMin = 268, + OpGroupFMax = 269, + OpGroupUMax = 270, + OpGroupSMax = 271, + OpReadPipe = 274, + OpWritePipe = 275, + OpReservedReadPipe = 276, + OpReservedWritePipe = 277, + OpReserveReadPipePackets = 278, + OpReserveWritePipePackets = 279, + OpCommitReadPipe = 280, + OpCommitWritePipe = 281, + OpIsValidReserveId = 282, + OpGetNumPipePackets = 283, + OpGetMaxPipePackets = 284, + OpGroupReserveReadPipePackets = 285, + OpGroupReserveWritePipePackets = 286, + OpGroupCommitReadPipe = 287, + OpGroupCommitWritePipe = 288, + OpEnqueueMarker = 291, + OpEnqueueKernel = 292, + OpGetKernelNDrangeSubGroupCount = 293, + OpGetKernelNDrangeMaxSubGroupSize = 294, + OpGetKernelWorkGroupSize = 295, + OpGetKernelPreferredWorkGroupSizeMultiple = 296, + OpRetainEvent = 297, + OpReleaseEvent = 298, + OpCreateUserEvent = 299, + OpIsValidEvent = 300, + OpSetUserEventStatus = 301, + OpCaptureEventProfilingInfo = 302, + OpGetDefaultQueue = 303, + OpBuildNDRange = 304, + OpImageSparseSampleImplicitLod = 305, + OpImageSparseSampleExplicitLod = 306, + OpImageSparseSampleDrefImplicitLod = 307, + OpImageSparseSampleDrefExplicitLod = 308, + OpImageSparseSampleProjImplicitLod = 309, + OpImageSparseSampleProjExplicitLod = 310, + OpImageSparseSampleProjDrefImplicitLod = 311, + OpImageSparseSampleProjDrefExplicitLod = 312, + OpImageSparseFetch = 313, + OpImageSparseGather = 314, + OpImageSparseDrefGather = 315, + OpImageSparseTexelsResident = 316, + OpNoLine = 317, + OpAtomicFlagTestAndSet = 318, + OpAtomicFlagClear = 319, + OpImageSparseRead = 320, + OpSizeOf = 321, + OpTypePipeStorage = 322, + OpConstantPipeStorage = 323, + OpCreatePipeFromPipeStorage = 324, + OpGetKernelLocalSizeForSubgroupCount = 325, + OpGetKernelMaxNumSubgroups = 326, + OpTypeNamedBarrier = 327, + OpNamedBarrierInitialize = 328, + OpMemoryNamedBarrier = 329, + OpModuleProcessed = 330, + OpExecutionModeId = 331, + OpDecorateId = 332, + OpGroupNonUniformElect = 333, + OpGroupNonUniformAll = 334, + OpGroupNonUniformAny = 335, + OpGroupNonUniformAllEqual = 336, + OpGroupNonUniformBroadcast = 337, + OpGroupNonUniformBroadcastFirst = 338, + OpGroupNonUniformBallot = 339, + OpGroupNonUniformInverseBallot = 340, + OpGroupNonUniformBallotBitExtract = 341, + OpGroupNonUniformBallotBitCount = 342, + OpGroupNonUniformBallotFindLSB = 343, + OpGroupNonUniformBallotFindMSB = 344, + OpGroupNonUniformShuffle = 345, + OpGroupNonUniformShuffleXor = 346, + OpGroupNonUniformShuffleUp = 347, + OpGroupNonUniformShuffleDown = 348, + OpGroupNonUniformIAdd = 349, + OpGroupNonUniformFAdd = 350, + OpGroupNonUniformIMul = 351, + OpGroupNonUniformFMul = 352, + OpGroupNonUniformSMin = 353, + OpGroupNonUniformUMin = 354, + OpGroupNonUniformFMin = 355, + OpGroupNonUniformSMax = 356, + OpGroupNonUniformUMax = 357, + OpGroupNonUniformFMax = 358, + OpGroupNonUniformBitwiseAnd = 359, + OpGroupNonUniformBitwiseOr = 360, + OpGroupNonUniformBitwiseXor = 361, + OpGroupNonUniformLogicalAnd = 362, + OpGroupNonUniformLogicalOr = 363, + OpGroupNonUniformLogicalXor = 364, + OpGroupNonUniformQuadBroadcast = 365, + OpGroupNonUniformQuadSwap = 366, + OpCopyLogical = 400, + OpPtrEqual = 401, + OpPtrNotEqual = 402, + OpPtrDiff = 403, + OpSubgroupBallotKHR = 4421, + OpSubgroupFirstInvocationKHR = 4422, + OpSubgroupAllKHR = 4428, + OpSubgroupAnyKHR = 4429, + OpSubgroupAllEqualKHR = 4430, + OpSubgroupReadInvocationKHR = 4432, + OpTypeRayQueryProvisionalKHR = 4472, + OpRayQueryInitializeKHR = 4473, + OpRayQueryTerminateKHR = 4474, + OpRayQueryGenerateIntersectionKHR = 4475, + OpRayQueryConfirmIntersectionKHR = 4476, + OpRayQueryProceedKHR = 4477, + OpRayQueryGetIntersectionTypeKHR = 4479, + OpGroupIAddNonUniformAMD = 5000, + OpGroupFAddNonUniformAMD = 5001, + OpGroupFMinNonUniformAMD = 5002, + OpGroupUMinNonUniformAMD = 5003, + OpGroupSMinNonUniformAMD = 5004, + OpGroupFMaxNonUniformAMD = 5005, + OpGroupUMaxNonUniformAMD = 5006, + OpGroupSMaxNonUniformAMD = 5007, + OpFragmentMaskFetchAMD = 5011, + OpFragmentFetchAMD = 5012, + OpReadClockKHR = 5056, + OpImageSampleFootprintNV = 5283, + OpGroupNonUniformPartitionNV = 5296, + OpWritePackedPrimitiveIndices4x8NV = 5299, + OpReportIntersectionKHR = 5334, + OpReportIntersectionNV = 5334, + OpIgnoreIntersectionKHR = 5335, + OpIgnoreIntersectionNV = 5335, + OpTerminateRayKHR = 5336, + OpTerminateRayNV = 5336, + OpTraceNV = 5337, + OpTraceRayKHR = 5337, + OpTypeAccelerationStructureKHR = 5341, + OpTypeAccelerationStructureNV = 5341, + OpExecuteCallableKHR = 5344, + OpExecuteCallableNV = 5344, + OpTypeCooperativeMatrixNV = 5358, + OpCooperativeMatrixLoadNV = 5359, + OpCooperativeMatrixStoreNV = 5360, + OpCooperativeMatrixMulAddNV = 5361, + OpCooperativeMatrixLengthNV = 5362, + OpBeginInvocationInterlockEXT = 5364, + OpEndInvocationInterlockEXT = 5365, + OpDemoteToHelperInvocationEXT = 5380, + OpIsHelperInvocationEXT = 5381, + OpSubgroupShuffleINTEL = 5571, + OpSubgroupShuffleDownINTEL = 5572, + OpSubgroupShuffleUpINTEL = 5573, + OpSubgroupShuffleXorINTEL = 5574, + OpSubgroupBlockReadINTEL = 5575, + OpSubgroupBlockWriteINTEL = 5576, + OpSubgroupImageBlockReadINTEL = 5577, + OpSubgroupImageBlockWriteINTEL = 5578, + OpSubgroupImageMediaBlockReadINTEL = 5580, + OpSubgroupImageMediaBlockWriteINTEL = 5581, + OpUCountLeadingZerosINTEL = 5585, + OpUCountTrailingZerosINTEL = 5586, + OpAbsISubINTEL = 5587, + OpAbsUSubINTEL = 5588, + OpIAddSatINTEL = 5589, + OpUAddSatINTEL = 5590, + OpIAverageINTEL = 5591, + OpUAverageINTEL = 5592, + OpIAverageRoundedINTEL = 5593, + OpUAverageRoundedINTEL = 5594, + OpISubSatINTEL = 5595, + OpUSubSatINTEL = 5596, + OpIMul32x16INTEL = 5597, + OpUMul32x16INTEL = 5598, + OpDecorateString = 5632, + OpDecorateStringGOOGLE = 5632, + OpMemberDecorateString = 5633, + OpMemberDecorateStringGOOGLE = 5633, + OpVmeImageINTEL = 5699, + OpTypeVmeImageINTEL = 5700, + OpTypeAvcImePayloadINTEL = 5701, + OpTypeAvcRefPayloadINTEL = 5702, + OpTypeAvcSicPayloadINTEL = 5703, + OpTypeAvcMcePayloadINTEL = 5704, + OpTypeAvcMceResultINTEL = 5705, + OpTypeAvcImeResultINTEL = 5706, + OpTypeAvcImeResultSingleReferenceStreamoutINTEL = 5707, + OpTypeAvcImeResultDualReferenceStreamoutINTEL = 5708, + OpTypeAvcImeSingleReferenceStreaminINTEL = 5709, + OpTypeAvcImeDualReferenceStreaminINTEL = 5710, + OpTypeAvcRefResultINTEL = 5711, + OpTypeAvcSicResultINTEL = 5712, + OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL = 5713, + OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL = 5714, + OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL = 5715, + OpSubgroupAvcMceSetInterShapePenaltyINTEL = 5716, + OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL = 5717, + OpSubgroupAvcMceSetInterDirectionPenaltyINTEL = 5718, + OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL = 5719, + OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL = 5720, + OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL = 5721, + OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL = 5722, + OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL = 5723, + OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL = 5724, + OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL = 5725, + OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL = 5726, + OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL = 5727, + OpSubgroupAvcMceSetAcOnlyHaarINTEL = 5728, + OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL = 5729, + OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL = 5730, + OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL = 5731, + OpSubgroupAvcMceConvertToImePayloadINTEL = 5732, + OpSubgroupAvcMceConvertToImeResultINTEL = 5733, + OpSubgroupAvcMceConvertToRefPayloadINTEL = 5734, + OpSubgroupAvcMceConvertToRefResultINTEL = 5735, + OpSubgroupAvcMceConvertToSicPayloadINTEL = 5736, + OpSubgroupAvcMceConvertToSicResultINTEL = 5737, + OpSubgroupAvcMceGetMotionVectorsINTEL = 5738, + OpSubgroupAvcMceGetInterDistortionsINTEL = 5739, + OpSubgroupAvcMceGetBestInterDistortionsINTEL = 5740, + OpSubgroupAvcMceGetInterMajorShapeINTEL = 5741, + OpSubgroupAvcMceGetInterMinorShapeINTEL = 5742, + OpSubgroupAvcMceGetInterDirectionsINTEL = 5743, + OpSubgroupAvcMceGetInterMotionVectorCountINTEL = 5744, + OpSubgroupAvcMceGetInterReferenceIdsINTEL = 5745, + OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL = 5746, + OpSubgroupAvcImeInitializeINTEL = 5747, + OpSubgroupAvcImeSetSingleReferenceINTEL = 5748, + OpSubgroupAvcImeSetDualReferenceINTEL = 5749, + OpSubgroupAvcImeRefWindowSizeINTEL = 5750, + OpSubgroupAvcImeAdjustRefOffsetINTEL = 5751, + OpSubgroupAvcImeConvertToMcePayloadINTEL = 5752, + OpSubgroupAvcImeSetMaxMotionVectorCountINTEL = 5753, + OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL = 5754, + OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL = 5755, + OpSubgroupAvcImeSetWeightedSadINTEL = 5756, + OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL = 5757, + OpSubgroupAvcImeEvaluateWithDualReferenceINTEL = 5758, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL = 5759, + OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL = 5760, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL = 5761, + OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL = 5762, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL = 5763, + OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL = 5764, + OpSubgroupAvcImeConvertToMceResultINTEL = 5765, + OpSubgroupAvcImeGetSingleReferenceStreaminINTEL = 5766, + OpSubgroupAvcImeGetDualReferenceStreaminINTEL = 5767, + OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL = 5768, + OpSubgroupAvcImeStripDualReferenceStreamoutINTEL = 5769, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL = 5770, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL = 5771, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL = 5772, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL = 5773, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL = 5774, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL = 5775, + OpSubgroupAvcImeGetBorderReachedINTEL = 5776, + OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL = 5777, + OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL = 5778, + OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL = 5779, + OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL = 5780, + OpSubgroupAvcFmeInitializeINTEL = 5781, + OpSubgroupAvcBmeInitializeINTEL = 5782, + OpSubgroupAvcRefConvertToMcePayloadINTEL = 5783, + OpSubgroupAvcRefSetBidirectionalMixDisableINTEL = 5784, + OpSubgroupAvcRefSetBilinearFilterEnableINTEL = 5785, + OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL = 5786, + OpSubgroupAvcRefEvaluateWithDualReferenceINTEL = 5787, + OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL = 5788, + OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL = 5789, + OpSubgroupAvcRefConvertToMceResultINTEL = 5790, + OpSubgroupAvcSicInitializeINTEL = 5791, + OpSubgroupAvcSicConfigureSkcINTEL = 5792, + OpSubgroupAvcSicConfigureIpeLumaINTEL = 5793, + OpSubgroupAvcSicConfigureIpeLumaChromaINTEL = 5794, + OpSubgroupAvcSicGetMotionVectorMaskINTEL = 5795, + OpSubgroupAvcSicConvertToMcePayloadINTEL = 5796, + OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL = 5797, + OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL = 5798, + OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL = 5799, + OpSubgroupAvcSicSetBilinearFilterEnableINTEL = 5800, + OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL = 5801, + OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL = 5802, + OpSubgroupAvcSicEvaluateIpeINTEL = 5803, + OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL = 5804, + OpSubgroupAvcSicEvaluateWithDualReferenceINTEL = 5805, + OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL = 5806, + OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL = 5807, + OpSubgroupAvcSicConvertToMceResultINTEL = 5808, + OpSubgroupAvcSicGetIpeLumaShapeINTEL = 5809, + OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL = 5810, + OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL = 5811, + OpSubgroupAvcSicGetPackedIpeLumaModesINTEL = 5812, + OpSubgroupAvcSicGetIpeChromaModeINTEL = 5813, + OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, + OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, + OpSubgroupAvcSicGetInterRawSadsINTEL = 5816, + OpRayQueryGetRayTMinKHR = 6016, + OpRayQueryGetRayFlagsKHR = 6017, + OpRayQueryGetIntersectionTKHR = 6018, + OpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019, + OpRayQueryGetIntersectionInstanceIdKHR = 6020, + OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021, + OpRayQueryGetIntersectionGeometryIndexKHR = 6022, + OpRayQueryGetIntersectionPrimitiveIndexKHR = 6023, + OpRayQueryGetIntersectionBarycentricsKHR = 6024, + OpRayQueryGetIntersectionFrontFaceKHR = 6025, + OpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026, + OpRayQueryGetIntersectionObjectRayDirectionKHR = 6027, + OpRayQueryGetIntersectionObjectRayOriginKHR = 6028, + OpRayQueryGetWorldRayDirectionKHR = 6029, + OpRayQueryGetWorldRayOriginKHR = 6030, + OpRayQueryGetIntersectionObjectToWorldKHR = 6031, + OpRayQueryGetIntersectionWorldToObjectKHR = 6032, + OpMax = 0x7fffffff, +}; + +#ifdef SPV_ENABLE_UTILITY_CODE +inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) { + *hasResult = *hasResultType = false; + switch (opcode) { + default: /* unknown opcode */ break; + case OpNop: *hasResult = false; *hasResultType = false; break; + case OpUndef: *hasResult = true; *hasResultType = true; break; + case OpSourceContinued: *hasResult = false; *hasResultType = false; break; + case OpSource: *hasResult = false; *hasResultType = false; break; + case OpSourceExtension: *hasResult = false; *hasResultType = false; break; + case OpName: *hasResult = false; *hasResultType = false; break; + case OpMemberName: *hasResult = false; *hasResultType = false; break; + case OpString: *hasResult = true; *hasResultType = false; break; + case OpLine: *hasResult = false; *hasResultType = false; break; + case OpExtension: *hasResult = false; *hasResultType = false; break; + case OpExtInstImport: *hasResult = true; *hasResultType = false; break; + case OpExtInst: *hasResult = true; *hasResultType = true; break; + case OpMemoryModel: *hasResult = false; *hasResultType = false; break; + case OpEntryPoint: *hasResult = false; *hasResultType = false; break; + case OpExecutionMode: *hasResult = false; *hasResultType = false; break; + case OpCapability: *hasResult = false; *hasResultType = false; break; + case OpTypeVoid: *hasResult = true; *hasResultType = false; break; + case OpTypeBool: *hasResult = true; *hasResultType = false; break; + case OpTypeInt: *hasResult = true; *hasResultType = false; break; + case OpTypeFloat: *hasResult = true; *hasResultType = false; break; + case OpTypeVector: *hasResult = true; *hasResultType = false; break; + case OpTypeMatrix: *hasResult = true; *hasResultType = false; break; + case OpTypeImage: *hasResult = true; *hasResultType = false; break; + case OpTypeSampler: *hasResult = true; *hasResultType = false; break; + case OpTypeSampledImage: *hasResult = true; *hasResultType = false; break; + case OpTypeArray: *hasResult = true; *hasResultType = false; break; + case OpTypeRuntimeArray: *hasResult = true; *hasResultType = false; break; + case OpTypeStruct: *hasResult = true; *hasResultType = false; break; + case OpTypeOpaque: *hasResult = true; *hasResultType = false; break; + case OpTypePointer: *hasResult = true; *hasResultType = false; break; + case OpTypeFunction: *hasResult = true; *hasResultType = false; break; + case OpTypeEvent: *hasResult = true; *hasResultType = false; break; + case OpTypeDeviceEvent: *hasResult = true; *hasResultType = false; break; + case OpTypeReserveId: *hasResult = true; *hasResultType = false; break; + case OpTypeQueue: *hasResult = true; *hasResultType = false; break; + case OpTypePipe: *hasResult = true; *hasResultType = false; break; + case OpTypeForwardPointer: *hasResult = false; *hasResultType = false; break; + case OpConstantTrue: *hasResult = true; *hasResultType = true; break; + case OpConstantFalse: *hasResult = true; *hasResultType = true; break; + case OpConstant: *hasResult = true; *hasResultType = true; break; + case OpConstantComposite: *hasResult = true; *hasResultType = true; break; + case OpConstantSampler: *hasResult = true; *hasResultType = true; break; + case OpConstantNull: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantTrue: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantFalse: *hasResult = true; *hasResultType = true; break; + case OpSpecConstant: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantComposite: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantOp: *hasResult = true; *hasResultType = true; break; + case OpFunction: *hasResult = true; *hasResultType = true; break; + case OpFunctionParameter: *hasResult = true; *hasResultType = true; break; + case OpFunctionEnd: *hasResult = false; *hasResultType = false; break; + case OpFunctionCall: *hasResult = true; *hasResultType = true; break; + case OpVariable: *hasResult = true; *hasResultType = true; break; + case OpImageTexelPointer: *hasResult = true; *hasResultType = true; break; + case OpLoad: *hasResult = true; *hasResultType = true; break; + case OpStore: *hasResult = false; *hasResultType = false; break; + case OpCopyMemory: *hasResult = false; *hasResultType = false; break; + case OpCopyMemorySized: *hasResult = false; *hasResultType = false; break; + case OpAccessChain: *hasResult = true; *hasResultType = true; break; + case OpInBoundsAccessChain: *hasResult = true; *hasResultType = true; break; + case OpPtrAccessChain: *hasResult = true; *hasResultType = true; break; + case OpArrayLength: *hasResult = true; *hasResultType = true; break; + case OpGenericPtrMemSemantics: *hasResult = true; *hasResultType = true; break; + case OpInBoundsPtrAccessChain: *hasResult = true; *hasResultType = true; break; + case OpDecorate: *hasResult = false; *hasResultType = false; break; + case OpMemberDecorate: *hasResult = false; *hasResultType = false; break; + case OpDecorationGroup: *hasResult = true; *hasResultType = false; break; + case OpGroupDecorate: *hasResult = false; *hasResultType = false; break; + case OpGroupMemberDecorate: *hasResult = false; *hasResultType = false; break; + case OpVectorExtractDynamic: *hasResult = true; *hasResultType = true; break; + case OpVectorInsertDynamic: *hasResult = true; *hasResultType = true; break; + case OpVectorShuffle: *hasResult = true; *hasResultType = true; break; + case OpCompositeConstruct: *hasResult = true; *hasResultType = true; break; + case OpCompositeExtract: *hasResult = true; *hasResultType = true; break; + case OpCompositeInsert: *hasResult = true; *hasResultType = true; break; + case OpCopyObject: *hasResult = true; *hasResultType = true; break; + case OpTranspose: *hasResult = true; *hasResultType = true; break; + case OpSampledImage: *hasResult = true; *hasResultType = true; break; + case OpImageSampleImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageFetch: *hasResult = true; *hasResultType = true; break; + case OpImageGather: *hasResult = true; *hasResultType = true; break; + case OpImageDrefGather: *hasResult = true; *hasResultType = true; break; + case OpImageRead: *hasResult = true; *hasResultType = true; break; + case OpImageWrite: *hasResult = false; *hasResultType = false; break; + case OpImage: *hasResult = true; *hasResultType = true; break; + case OpImageQueryFormat: *hasResult = true; *hasResultType = true; break; + case OpImageQueryOrder: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySizeLod: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySize: *hasResult = true; *hasResultType = true; break; + case OpImageQueryLod: *hasResult = true; *hasResultType = true; break; + case OpImageQueryLevels: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySamples: *hasResult = true; *hasResultType = true; break; + case OpConvertFToU: *hasResult = true; *hasResultType = true; break; + case OpConvertFToS: *hasResult = true; *hasResultType = true; break; + case OpConvertSToF: *hasResult = true; *hasResultType = true; break; + case OpConvertUToF: *hasResult = true; *hasResultType = true; break; + case OpUConvert: *hasResult = true; *hasResultType = true; break; + case OpSConvert: *hasResult = true; *hasResultType = true; break; + case OpFConvert: *hasResult = true; *hasResultType = true; break; + case OpQuantizeToF16: *hasResult = true; *hasResultType = true; break; + case OpConvertPtrToU: *hasResult = true; *hasResultType = true; break; + case OpSatConvertSToU: *hasResult = true; *hasResultType = true; break; + case OpSatConvertUToS: *hasResult = true; *hasResultType = true; break; + case OpConvertUToPtr: *hasResult = true; *hasResultType = true; break; + case OpPtrCastToGeneric: *hasResult = true; *hasResultType = true; break; + case OpGenericCastToPtr: *hasResult = true; *hasResultType = true; break; + case OpGenericCastToPtrExplicit: *hasResult = true; *hasResultType = true; break; + case OpBitcast: *hasResult = true; *hasResultType = true; break; + case OpSNegate: *hasResult = true; *hasResultType = true; break; + case OpFNegate: *hasResult = true; *hasResultType = true; break; + case OpIAdd: *hasResult = true; *hasResultType = true; break; + case OpFAdd: *hasResult = true; *hasResultType = true; break; + case OpISub: *hasResult = true; *hasResultType = true; break; + case OpFSub: *hasResult = true; *hasResultType = true; break; + case OpIMul: *hasResult = true; *hasResultType = true; break; + case OpFMul: *hasResult = true; *hasResultType = true; break; + case OpUDiv: *hasResult = true; *hasResultType = true; break; + case OpSDiv: *hasResult = true; *hasResultType = true; break; + case OpFDiv: *hasResult = true; *hasResultType = true; break; + case OpUMod: *hasResult = true; *hasResultType = true; break; + case OpSRem: *hasResult = true; *hasResultType = true; break; + case OpSMod: *hasResult = true; *hasResultType = true; break; + case OpFRem: *hasResult = true; *hasResultType = true; break; + case OpFMod: *hasResult = true; *hasResultType = true; break; + case OpVectorTimesScalar: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesScalar: *hasResult = true; *hasResultType = true; break; + case OpVectorTimesMatrix: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesVector: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesMatrix: *hasResult = true; *hasResultType = true; break; + case OpOuterProduct: *hasResult = true; *hasResultType = true; break; + case OpDot: *hasResult = true; *hasResultType = true; break; + case OpIAddCarry: *hasResult = true; *hasResultType = true; break; + case OpISubBorrow: *hasResult = true; *hasResultType = true; break; + case OpUMulExtended: *hasResult = true; *hasResultType = true; break; + case OpSMulExtended: *hasResult = true; *hasResultType = true; break; + case OpAny: *hasResult = true; *hasResultType = true; break; + case OpAll: *hasResult = true; *hasResultType = true; break; + case OpIsNan: *hasResult = true; *hasResultType = true; break; + case OpIsInf: *hasResult = true; *hasResultType = true; break; + case OpIsFinite: *hasResult = true; *hasResultType = true; break; + case OpIsNormal: *hasResult = true; *hasResultType = true; break; + case OpSignBitSet: *hasResult = true; *hasResultType = true; break; + case OpLessOrGreater: *hasResult = true; *hasResultType = true; break; + case OpOrdered: *hasResult = true; *hasResultType = true; break; + case OpUnordered: *hasResult = true; *hasResultType = true; break; + case OpLogicalEqual: *hasResult = true; *hasResultType = true; break; + case OpLogicalNotEqual: *hasResult = true; *hasResultType = true; break; + case OpLogicalOr: *hasResult = true; *hasResultType = true; break; + case OpLogicalAnd: *hasResult = true; *hasResultType = true; break; + case OpLogicalNot: *hasResult = true; *hasResultType = true; break; + case OpSelect: *hasResult = true; *hasResultType = true; break; + case OpIEqual: *hasResult = true; *hasResultType = true; break; + case OpINotEqual: *hasResult = true; *hasResultType = true; break; + case OpUGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpSGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpUGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpSGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpULessThan: *hasResult = true; *hasResultType = true; break; + case OpSLessThan: *hasResult = true; *hasResultType = true; break; + case OpULessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpSLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdNotEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordNotEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdLessThan: *hasResult = true; *hasResultType = true; break; + case OpFUnordLessThan: *hasResult = true; *hasResultType = true; break; + case OpFOrdGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpFUnordGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpFOrdLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpShiftRightLogical: *hasResult = true; *hasResultType = true; break; + case OpShiftRightArithmetic: *hasResult = true; *hasResultType = true; break; + case OpShiftLeftLogical: *hasResult = true; *hasResultType = true; break; + case OpBitwiseOr: *hasResult = true; *hasResultType = true; break; + case OpBitwiseXor: *hasResult = true; *hasResultType = true; break; + case OpBitwiseAnd: *hasResult = true; *hasResultType = true; break; + case OpNot: *hasResult = true; *hasResultType = true; break; + case OpBitFieldInsert: *hasResult = true; *hasResultType = true; break; + case OpBitFieldSExtract: *hasResult = true; *hasResultType = true; break; + case OpBitFieldUExtract: *hasResult = true; *hasResultType = true; break; + case OpBitReverse: *hasResult = true; *hasResultType = true; break; + case OpBitCount: *hasResult = true; *hasResultType = true; break; + case OpDPdx: *hasResult = true; *hasResultType = true; break; + case OpDPdy: *hasResult = true; *hasResultType = true; break; + case OpFwidth: *hasResult = true; *hasResultType = true; break; + case OpDPdxFine: *hasResult = true; *hasResultType = true; break; + case OpDPdyFine: *hasResult = true; *hasResultType = true; break; + case OpFwidthFine: *hasResult = true; *hasResultType = true; break; + case OpDPdxCoarse: *hasResult = true; *hasResultType = true; break; + case OpDPdyCoarse: *hasResult = true; *hasResultType = true; break; + case OpFwidthCoarse: *hasResult = true; *hasResultType = true; break; + case OpEmitVertex: *hasResult = false; *hasResultType = false; break; + case OpEndPrimitive: *hasResult = false; *hasResultType = false; break; + case OpEmitStreamVertex: *hasResult = false; *hasResultType = false; break; + case OpEndStreamPrimitive: *hasResult = false; *hasResultType = false; break; + case OpControlBarrier: *hasResult = false; *hasResultType = false; break; + case OpMemoryBarrier: *hasResult = false; *hasResultType = false; break; + case OpAtomicLoad: *hasResult = true; *hasResultType = true; break; + case OpAtomicStore: *hasResult = false; *hasResultType = false; break; + case OpAtomicExchange: *hasResult = true; *hasResultType = true; break; + case OpAtomicCompareExchange: *hasResult = true; *hasResultType = true; break; + case OpAtomicCompareExchangeWeak: *hasResult = true; *hasResultType = true; break; + case OpAtomicIIncrement: *hasResult = true; *hasResultType = true; break; + case OpAtomicIDecrement: *hasResult = true; *hasResultType = true; break; + case OpAtomicIAdd: *hasResult = true; *hasResultType = true; break; + case OpAtomicISub: *hasResult = true; *hasResultType = true; break; + case OpAtomicSMin: *hasResult = true; *hasResultType = true; break; + case OpAtomicUMin: *hasResult = true; *hasResultType = true; break; + case OpAtomicSMax: *hasResult = true; *hasResultType = true; break; + case OpAtomicUMax: *hasResult = true; *hasResultType = true; break; + case OpAtomicAnd: *hasResult = true; *hasResultType = true; break; + case OpAtomicOr: *hasResult = true; *hasResultType = true; break; + case OpAtomicXor: *hasResult = true; *hasResultType = true; break; + case OpPhi: *hasResult = true; *hasResultType = true; break; + case OpLoopMerge: *hasResult = false; *hasResultType = false; break; + case OpSelectionMerge: *hasResult = false; *hasResultType = false; break; + case OpLabel: *hasResult = true; *hasResultType = false; break; + case OpBranch: *hasResult = false; *hasResultType = false; break; + case OpBranchConditional: *hasResult = false; *hasResultType = false; break; + case OpSwitch: *hasResult = false; *hasResultType = false; break; + case OpKill: *hasResult = false; *hasResultType = false; break; + case OpReturn: *hasResult = false; *hasResultType = false; break; + case OpReturnValue: *hasResult = false; *hasResultType = false; break; + case OpUnreachable: *hasResult = false; *hasResultType = false; break; + case OpLifetimeStart: *hasResult = false; *hasResultType = false; break; + case OpLifetimeStop: *hasResult = false; *hasResultType = false; break; + case OpGroupAsyncCopy: *hasResult = true; *hasResultType = true; break; + case OpGroupWaitEvents: *hasResult = false; *hasResultType = false; break; + case OpGroupAll: *hasResult = true; *hasResultType = true; break; + case OpGroupAny: *hasResult = true; *hasResultType = true; break; + case OpGroupBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupIAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupFAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupFMin: *hasResult = true; *hasResultType = true; break; + case OpGroupUMin: *hasResult = true; *hasResultType = true; break; + case OpGroupSMin: *hasResult = true; *hasResultType = true; break; + case OpGroupFMax: *hasResult = true; *hasResultType = true; break; + case OpGroupUMax: *hasResult = true; *hasResultType = true; break; + case OpGroupSMax: *hasResult = true; *hasResultType = true; break; + case OpReadPipe: *hasResult = true; *hasResultType = true; break; + case OpWritePipe: *hasResult = true; *hasResultType = true; break; + case OpReservedReadPipe: *hasResult = true; *hasResultType = true; break; + case OpReservedWritePipe: *hasResult = true; *hasResultType = true; break; + case OpReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; + case OpReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; + case OpCommitReadPipe: *hasResult = false; *hasResultType = false; break; + case OpCommitWritePipe: *hasResult = false; *hasResultType = false; break; + case OpIsValidReserveId: *hasResult = true; *hasResultType = true; break; + case OpGetNumPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGetMaxPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupCommitReadPipe: *hasResult = false; *hasResultType = false; break; + case OpGroupCommitWritePipe: *hasResult = false; *hasResultType = false; break; + case OpEnqueueMarker: *hasResult = true; *hasResultType = true; break; + case OpEnqueueKernel: *hasResult = true; *hasResultType = true; break; + case OpGetKernelNDrangeSubGroupCount: *hasResult = true; *hasResultType = true; break; + case OpGetKernelNDrangeMaxSubGroupSize: *hasResult = true; *hasResultType = true; break; + case OpGetKernelWorkGroupSize: *hasResult = true; *hasResultType = true; break; + case OpGetKernelPreferredWorkGroupSizeMultiple: *hasResult = true; *hasResultType = true; break; + case OpRetainEvent: *hasResult = false; *hasResultType = false; break; + case OpReleaseEvent: *hasResult = false; *hasResultType = false; break; + case OpCreateUserEvent: *hasResult = true; *hasResultType = true; break; + case OpIsValidEvent: *hasResult = true; *hasResultType = true; break; + case OpSetUserEventStatus: *hasResult = false; *hasResultType = false; break; + case OpCaptureEventProfilingInfo: *hasResult = false; *hasResultType = false; break; + case OpGetDefaultQueue: *hasResult = true; *hasResultType = true; break; + case OpBuildNDRange: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseFetch: *hasResult = true; *hasResultType = true; break; + case OpImageSparseGather: *hasResult = true; *hasResultType = true; break; + case OpImageSparseDrefGather: *hasResult = true; *hasResultType = true; break; + case OpImageSparseTexelsResident: *hasResult = true; *hasResultType = true; break; + case OpNoLine: *hasResult = false; *hasResultType = false; break; + case OpAtomicFlagTestAndSet: *hasResult = true; *hasResultType = true; break; + case OpAtomicFlagClear: *hasResult = false; *hasResultType = false; break; + case OpImageSparseRead: *hasResult = true; *hasResultType = true; break; + case OpSizeOf: *hasResult = true; *hasResultType = true; break; + case OpTypePipeStorage: *hasResult = true; *hasResultType = false; break; + case OpConstantPipeStorage: *hasResult = true; *hasResultType = true; break; + case OpCreatePipeFromPipeStorage: *hasResult = true; *hasResultType = true; break; + case OpGetKernelLocalSizeForSubgroupCount: *hasResult = true; *hasResultType = true; break; + case OpGetKernelMaxNumSubgroups: *hasResult = true; *hasResultType = true; break; + case OpTypeNamedBarrier: *hasResult = true; *hasResultType = false; break; + case OpNamedBarrierInitialize: *hasResult = true; *hasResultType = true; break; + case OpMemoryNamedBarrier: *hasResult = false; *hasResultType = false; break; + case OpModuleProcessed: *hasResult = false; *hasResultType = false; break; + case OpExecutionModeId: *hasResult = false; *hasResultType = false; break; + case OpDecorateId: *hasResult = false; *hasResultType = false; break; + case OpGroupNonUniformElect: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAll: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAny: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAllEqual: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBroadcastFirst: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallot: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformInverseBallot: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotBitExtract: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotBitCount: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotFindLSB: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotFindMSB: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffle: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleUp: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleDown: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformIAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformIMul: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMul: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformSMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformUMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformSMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformUMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseAnd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseOr: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalAnd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalOr: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformQuadBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformQuadSwap: *hasResult = true; *hasResultType = true; break; + case OpCopyLogical: *hasResult = true; *hasResultType = true; break; + case OpPtrEqual: *hasResult = true; *hasResultType = true; break; + case OpPtrNotEqual: *hasResult = true; *hasResultType = true; break; + case OpPtrDiff: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break; + case OpTypeRayQueryProvisionalKHR: *hasResult = true; *hasResultType = false; break; + case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break; + case OpGroupIAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupUMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupSMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupUMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupSMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpFragmentMaskFetchAMD: *hasResult = true; *hasResultType = true; break; + case OpFragmentFetchAMD: *hasResult = true; *hasResultType = true; break; + case OpReadClockKHR: *hasResult = true; *hasResultType = true; break; + case OpImageSampleFootprintNV: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformPartitionNV: *hasResult = true; *hasResultType = true; break; + case OpWritePackedPrimitiveIndices4x8NV: *hasResult = false; *hasResultType = false; break; + case OpReportIntersectionNV: *hasResult = true; *hasResultType = true; break; + case OpIgnoreIntersectionNV: *hasResult = false; *hasResultType = false; break; + case OpTerminateRayNV: *hasResult = false; *hasResultType = false; break; + case OpTraceNV: *hasResult = false; *hasResultType = false; break; + case OpTypeAccelerationStructureNV: *hasResult = true; *hasResultType = false; break; + case OpExecuteCallableNV: *hasResult = false; *hasResultType = false; break; + case OpTypeCooperativeMatrixNV: *hasResult = true; *hasResultType = false; break; + case OpCooperativeMatrixLoadNV: *hasResult = true; *hasResultType = true; break; + case OpCooperativeMatrixStoreNV: *hasResult = false; *hasResultType = false; break; + case OpCooperativeMatrixMulAddNV: *hasResult = true; *hasResultType = true; break; + case OpCooperativeMatrixLengthNV: *hasResult = true; *hasResultType = true; break; + case OpBeginInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; + case OpEndInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; + case OpDemoteToHelperInvocationEXT: *hasResult = false; *hasResultType = false; break; + case OpIsHelperInvocationEXT: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleDownINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleUpINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleXorINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpSubgroupImageBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupImageBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpSubgroupImageMediaBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupImageMediaBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpUCountLeadingZerosINTEL: *hasResult = true; *hasResultType = true; break; + case OpUCountTrailingZerosINTEL: *hasResult = true; *hasResultType = true; break; + case OpAbsISubINTEL: *hasResult = true; *hasResultType = true; break; + case OpAbsUSubINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAddSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAddSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAverageINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAverageINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; + case OpISubSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break; + case OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break; + case OpDecorateString: *hasResult = false; *hasResultType = false; break; + case OpMemberDecorateString: *hasResult = false; *hasResultType = false; break; + case OpVmeImageINTEL: *hasResult = true; *hasResultType = true; break; + case OpTypeVmeImageINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImePayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcRefPayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcSicPayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcMcePayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcMceResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcRefResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcSicResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetAcOnlyHaarINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToImePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToImeResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToRefPayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToRefResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToSicPayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToSicResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetBestInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMajorShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMinorShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterDirectionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeRefWindowSizeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeAdjustRefOffsetINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetMaxMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetWeightedSadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeStripDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetBorderReachedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcFmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcBmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefSetBidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureSkcINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureIpeLumaINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureIpeLumaChromaINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetMotionVectorMaskINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateIpeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetIpeLumaShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedIpeLumaModesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetIpeChromaModeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetRayTMinKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetRayFlagsKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionTKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceCustomIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceIdKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionGeometryIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionPrimitiveIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionBarycentricsKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionFrontFaceKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetWorldRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetWorldRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break; + } +} +#endif /* SPV_ENABLE_UTILITY_CODE */ + +// Overload operator| for mask bit combining + +inline ImageOperandsMask operator|(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) | unsigned(b)); } +inline FPFastMathModeMask operator|(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) | unsigned(b)); } +inline SelectionControlMask operator|(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) | unsigned(b)); } +inline LoopControlMask operator|(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) | unsigned(b)); } +inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) | unsigned(b)); } +inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); } +inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); } +inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); } +inline RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); } + +} // end namespace spv + +#endif // #ifndef spirv_HPP + diff --git a/android/x86/include/SPIRV/spvIR.h b/android/x86/include/SPIRV/spvIR.h new file mode 100644 index 00000000..6523035e --- /dev/null +++ b/android/x86/include/SPIRV/spvIR.h @@ -0,0 +1,485 @@ +// +// Copyright (C) 2014 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// SPIRV-IR +// +// Simple in-memory representation (IR) of SPIRV. Just for holding +// Each function's CFG of blocks. Has this hierarchy: +// - Module, which is a list of +// - Function, which is a list of +// - Block, which is a list of +// - Instruction +// + +#pragma once +#ifndef spvIR_H +#define spvIR_H + +#include "spirv.hpp" + +#include +#include +#include +#include +#include +#include + +namespace spv { + +class Block; +class Function; +class Module; + +const Id NoResult = 0; +const Id NoType = 0; + +const Decoration NoPrecision = DecorationMax; + +#ifdef __GNUC__ +# define POTENTIALLY_UNUSED __attribute__((unused)) +#else +# define POTENTIALLY_UNUSED +#endif + +POTENTIALLY_UNUSED +const MemorySemanticsMask MemorySemanticsAllMemory = + (MemorySemanticsMask)(MemorySemanticsUniformMemoryMask | + MemorySemanticsWorkgroupMemoryMask | + MemorySemanticsAtomicCounterMemoryMask | + MemorySemanticsImageMemoryMask); + +struct IdImmediate { + bool isId; // true if word is an Id, false if word is an immediate + unsigned word; + IdImmediate(bool i, unsigned w) : isId(i), word(w) {} +}; + +// +// SPIR-V IR instruction. +// + +class Instruction { +public: + Instruction(Id resultId, Id typeId, Op opCode) : resultId(resultId), typeId(typeId), opCode(opCode), block(nullptr) { } + explicit Instruction(Op opCode) : resultId(NoResult), typeId(NoType), opCode(opCode), block(nullptr) { } + virtual ~Instruction() {} + void addIdOperand(Id id) { + operands.push_back(id); + idOperand.push_back(true); + } + void addImmediateOperand(unsigned int immediate) { + operands.push_back(immediate); + idOperand.push_back(false); + } + void setImmediateOperand(unsigned idx, unsigned int immediate) { + assert(!idOperand[idx]); + operands[idx] = immediate; + } + + void addStringOperand(const char* str) + { + unsigned int word; + char* wordString = (char*)&word; + char* wordPtr = wordString; + int charCount = 0; + char c; + do { + c = *(str++); + *(wordPtr++) = c; + ++charCount; + if (charCount == 4) { + addImmediateOperand(word); + wordPtr = wordString; + charCount = 0; + } + } while (c != 0); + + // deal with partial last word + if (charCount > 0) { + // pad with 0s + for (; charCount < 4; ++charCount) + *(wordPtr++) = 0; + addImmediateOperand(word); + } + } + bool isIdOperand(int op) const { return idOperand[op]; } + void setBlock(Block* b) { block = b; } + Block* getBlock() const { return block; } + Op getOpCode() const { return opCode; } + int getNumOperands() const + { + assert(operands.size() == idOperand.size()); + return (int)operands.size(); + } + Id getResultId() const { return resultId; } + Id getTypeId() const { return typeId; } + Id getIdOperand(int op) const { + assert(idOperand[op]); + return operands[op]; + } + unsigned int getImmediateOperand(int op) const { + assert(!idOperand[op]); + return operands[op]; + } + + // Write out the binary form. + void dump(std::vector& out) const + { + // Compute the wordCount + unsigned int wordCount = 1; + if (typeId) + ++wordCount; + if (resultId) + ++wordCount; + wordCount += (unsigned int)operands.size(); + + // Write out the beginning of the instruction + out.push_back(((wordCount) << WordCountShift) | opCode); + if (typeId) + out.push_back(typeId); + if (resultId) + out.push_back(resultId); + + // Write out the operands + for (int op = 0; op < (int)operands.size(); ++op) + out.push_back(operands[op]); + } + +protected: + Instruction(const Instruction&); + Id resultId; + Id typeId; + Op opCode; + std::vector operands; // operands, both and immediates (both are unsigned int) + std::vector idOperand; // true for operands that are , false for immediates + Block* block; +}; + +// +// SPIR-V IR block. +// + +class Block { +public: + Block(Id id, Function& parent); + virtual ~Block() + { + } + + Id getId() { return instructions.front()->getResultId(); } + + Function& getParent() const { return parent; } + void addInstruction(std::unique_ptr inst); + void addPredecessor(Block* pred) { predecessors.push_back(pred); pred->successors.push_back(this);} + void addLocalVariable(std::unique_ptr inst) { localVariables.push_back(std::move(inst)); } + const std::vector& getPredecessors() const { return predecessors; } + const std::vector& getSuccessors() const { return successors; } + const std::vector >& getInstructions() const { + return instructions; + } + const std::vector >& getLocalVariables() const { return localVariables; } + void setUnreachable() { unreachable = true; } + bool isUnreachable() const { return unreachable; } + // Returns the block's merge instruction, if one exists (otherwise null). + const Instruction* getMergeInstruction() const { + if (instructions.size() < 2) return nullptr; + const Instruction* nextToLast = (instructions.cend() - 2)->get(); + switch (nextToLast->getOpCode()) { + case OpSelectionMerge: + case OpLoopMerge: + return nextToLast; + default: + return nullptr; + } + return nullptr; + } + + // Change this block into a canonical dead merge block. Delete instructions + // as necessary. A canonical dead merge block has only an OpLabel and an + // OpUnreachable. + void rewriteAsCanonicalUnreachableMerge() { + assert(localVariables.empty()); + // Delete all instructions except for the label. + assert(instructions.size() > 0); + instructions.resize(1); + successors.clear(); + addInstruction(std::unique_ptr(new Instruction(OpUnreachable))); + } + // Change this block into a canonical dead continue target branching to the + // given header ID. Delete instructions as necessary. A canonical dead continue + // target has only an OpLabel and an unconditional branch back to the corresponding + // header. + void rewriteAsCanonicalUnreachableContinue(Block* header) { + assert(localVariables.empty()); + // Delete all instructions except for the label. + assert(instructions.size() > 0); + instructions.resize(1); + successors.clear(); + // Add OpBranch back to the header. + assert(header != nullptr); + Instruction* branch = new Instruction(OpBranch); + branch->addIdOperand(header->getId()); + addInstruction(std::unique_ptr(branch)); + successors.push_back(header); + } + + bool isTerminated() const + { + switch (instructions.back()->getOpCode()) { + case OpBranch: + case OpBranchConditional: + case OpSwitch: + case OpKill: + case OpReturn: + case OpReturnValue: + case OpUnreachable: + return true; + default: + return false; + } + } + + void dump(std::vector& out) const + { + instructions[0]->dump(out); + for (int i = 0; i < (int)localVariables.size(); ++i) + localVariables[i]->dump(out); + for (int i = 1; i < (int)instructions.size(); ++i) + instructions[i]->dump(out); + } + +protected: + Block(const Block&); + Block& operator=(Block&); + + // To enforce keeping parent and ownership in sync: + friend Function; + + std::vector > instructions; + std::vector predecessors, successors; + std::vector > localVariables; + Function& parent; + + // track whether this block is known to be uncreachable (not necessarily + // true for all unreachable blocks, but should be set at least + // for the extraneous ones introduced by the builder). + bool unreachable; +}; + +// The different reasons for reaching a block in the inReadableOrder traversal. +enum ReachReason { + // Reachable from the entry block via transfers of control, i.e. branches. + ReachViaControlFlow = 0, + // A continue target that is not reachable via control flow. + ReachDeadContinue, + // A merge block that is not reachable via control flow. + ReachDeadMerge +}; + +// Traverses the control-flow graph rooted at root in an order suited for +// readable code generation. Invokes callback at every node in the traversal +// order. The callback arguments are: +// - the block, +// - the reason we reached the block, +// - if the reason was that block is an unreachable continue or unreachable merge block +// then the last parameter is the corresponding header block. +void inReadableOrder(Block* root, std::function callback); + +// +// SPIR-V IR Function. +// + +class Function { +public: + Function(Id id, Id resultType, Id functionType, Id firstParam, Module& parent); + virtual ~Function() + { + for (int i = 0; i < (int)parameterInstructions.size(); ++i) + delete parameterInstructions[i]; + + for (int i = 0; i < (int)blocks.size(); ++i) + delete blocks[i]; + } + Id getId() const { return functionInstruction.getResultId(); } + Id getParamId(int p) const { return parameterInstructions[p]->getResultId(); } + Id getParamType(int p) const { return parameterInstructions[p]->getTypeId(); } + + void addBlock(Block* block) { blocks.push_back(block); } + void removeBlock(Block* block) + { + auto found = find(blocks.begin(), blocks.end(), block); + assert(found != blocks.end()); + blocks.erase(found); + delete block; + } + + Module& getParent() const { return parent; } + Block* getEntryBlock() const { return blocks.front(); } + Block* getLastBlock() const { return blocks.back(); } + const std::vector& getBlocks() const { return blocks; } + void addLocalVariable(std::unique_ptr inst); + Id getReturnType() const { return functionInstruction.getTypeId(); } + + void setImplicitThis() { implicitThis = true; } + bool hasImplicitThis() const { return implicitThis; } + + void dump(std::vector& out) const + { + // OpFunction + functionInstruction.dump(out); + + // OpFunctionParameter + for (int p = 0; p < (int)parameterInstructions.size(); ++p) + parameterInstructions[p]->dump(out); + + // Blocks + inReadableOrder(blocks[0], [&out](const Block* b, ReachReason, Block*) { b->dump(out); }); + Instruction end(0, 0, OpFunctionEnd); + end.dump(out); + } + +protected: + Function(const Function&); + Function& operator=(Function&); + + Module& parent; + Instruction functionInstruction; + std::vector parameterInstructions; + std::vector blocks; + bool implicitThis; // true if this is a member function expecting to be passed a 'this' as the first argument +}; + +// +// SPIR-V IR Module. +// + +class Module { +public: + Module() {} + virtual ~Module() + { + // TODO delete things + } + + void addFunction(Function *fun) { functions.push_back(fun); } + + void mapInstruction(Instruction *instruction) + { + spv::Id resultId = instruction->getResultId(); + // map the instruction's result id + if (resultId >= idToInstruction.size()) + idToInstruction.resize(resultId + 16); + idToInstruction[resultId] = instruction; + } + + Instruction* getInstruction(Id id) const { return idToInstruction[id]; } + const std::vector& getFunctions() const { return functions; } + spv::Id getTypeId(Id resultId) const { + return idToInstruction[resultId] == nullptr ? NoType : idToInstruction[resultId]->getTypeId(); + } + StorageClass getStorageClass(Id typeId) const + { + assert(idToInstruction[typeId]->getOpCode() == spv::OpTypePointer); + return (StorageClass)idToInstruction[typeId]->getImmediateOperand(0); + } + + void dump(std::vector& out) const + { + for (int f = 0; f < (int)functions.size(); ++f) + functions[f]->dump(out); + } + +protected: + Module(const Module&); + std::vector functions; + + // map from result id to instruction having that result id + std::vector idToInstruction; + + // map from a result id to its type id +}; + +// +// Implementation (it's here due to circular type definitions). +// + +// Add both +// - the OpFunction instruction +// - all the OpFunctionParameter instructions +__inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, Module& parent) + : parent(parent), functionInstruction(id, resultType, OpFunction), implicitThis(false) +{ + // OpFunction + functionInstruction.addImmediateOperand(FunctionControlMaskNone); + functionInstruction.addIdOperand(functionType); + parent.mapInstruction(&functionInstruction); + parent.addFunction(this); + + // OpFunctionParameter + Instruction* typeInst = parent.getInstruction(functionType); + int numParams = typeInst->getNumOperands() - 1; + for (int p = 0; p < numParams; ++p) { + Instruction* param = new Instruction(firstParamId + p, typeInst->getIdOperand(p + 1), OpFunctionParameter); + parent.mapInstruction(param); + parameterInstructions.push_back(param); + } +} + +__inline void Function::addLocalVariable(std::unique_ptr inst) +{ + Instruction* raw_instruction = inst.get(); + blocks[0]->addLocalVariable(std::move(inst)); + parent.mapInstruction(raw_instruction); +} + +__inline Block::Block(Id id, Function& parent) : parent(parent), unreachable(false) +{ + instructions.push_back(std::unique_ptr(new Instruction(id, NoType, OpLabel))); + instructions.back()->setBlock(this); + parent.getParent().mapInstruction(instructions.back().get()); +} + +__inline void Block::addInstruction(std::unique_ptr inst) +{ + Instruction* raw_instruction = inst.get(); + instructions.push_back(std::move(inst)); + raw_instruction->setBlock(this); + if (raw_instruction->getResultId()) + parent.getParent().mapInstruction(raw_instruction); +} + +} // end spv namespace + +#endif // spvIR_H diff --git a/android/x86/include/glslang/Include/BaseTypes.h b/android/x86/include/glslang/Include/BaseTypes.h new file mode 100644 index 00000000..816b1794 --- /dev/null +++ b/android/x86/include/glslang/Include/BaseTypes.h @@ -0,0 +1,565 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 LunarG, Inc. +// Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _BASICTYPES_INCLUDED_ +#define _BASICTYPES_INCLUDED_ + +namespace glslang { + +// +// Basic type. Arrays, vectors, sampler details, etc., are orthogonal to this. +// +enum TBasicType { + EbtVoid, + EbtFloat, + EbtDouble, + EbtFloat16, + EbtInt8, + EbtUint8, + EbtInt16, + EbtUint16, + EbtInt, + EbtUint, + EbtInt64, + EbtUint64, + EbtBool, + EbtAtomicUint, + EbtSampler, + EbtStruct, + EbtBlock, + EbtAccStruct, + EbtReference, + EbtRayQuery, + + // HLSL types that live only temporarily. + EbtString, + + EbtNumTypes +}; + +// +// Storage qualifiers. Should align with different kinds of storage or +// resource or GLSL storage qualifier. Expansion is deprecated. +// +// N.B.: You probably DON'T want to add anything here, but rather just add it +// to the built-in variables. See the comment above TBuiltInVariable. +// +// A new built-in variable will normally be an existing qualifier, like 'in', 'out', etc. +// DO NOT follow the design pattern of, say EvqInstanceId, etc. +// +enum TStorageQualifier { + EvqTemporary, // For temporaries (within a function), read/write + EvqGlobal, // For globals read/write + EvqConst, // User-defined constant values, will be semantically constant and constant folded + EvqVaryingIn, // pipeline input, read only, also supercategory for all built-ins not included in this enum (see TBuiltInVariable) + EvqVaryingOut, // pipeline output, read/write, also supercategory for all built-ins not included in this enum (see TBuiltInVariable) + EvqUniform, // read only, shared with app + EvqBuffer, // read/write, shared with app + EvqShared, // compute shader's read/write 'shared' qualifier + + EvqPayload, + EvqPayloadIn, + EvqHitAttr, + EvqCallableData, + EvqCallableDataIn, + + // parameters + EvqIn, // also, for 'in' in the grammar before we know if it's a pipeline input or an 'in' parameter + EvqOut, // also, for 'out' in the grammar before we know if it's a pipeline output or an 'out' parameter + EvqInOut, + EvqConstReadOnly, // input; also other read-only types having neither a constant value nor constant-value semantics + + // built-ins read by vertex shader + EvqVertexId, + EvqInstanceId, + + // built-ins written by vertex shader + EvqPosition, + EvqPointSize, + EvqClipVertex, + + // built-ins read by fragment shader + EvqFace, + EvqFragCoord, + EvqPointCoord, + + // built-ins written by fragment shader + EvqFragColor, + EvqFragDepth, + + // end of list + EvqLast +}; + +// +// Subcategories of the TStorageQualifier, simply to give a direct mapping +// between built-in variable names and an numerical value (the enum). +// +// For backward compatibility, there is some redundancy between the +// TStorageQualifier and these. Existing members should both be maintained accurately. +// However, any new built-in variable (and any existing non-redundant one) +// must follow the pattern that the specific built-in is here, and only its +// general qualifier is in TStorageQualifier. +// +// Something like gl_Position, which is sometimes 'in' and sometimes 'out' +// shows up as two different built-in variables in a single stage, but +// only has a single enum in TBuiltInVariable, so both the +// TStorageQualifier and the TBuitinVariable are needed to distinguish +// between them. +// +enum TBuiltInVariable { + EbvNone, + EbvNumWorkGroups, + EbvWorkGroupSize, + EbvWorkGroupId, + EbvLocalInvocationId, + EbvGlobalInvocationId, + EbvLocalInvocationIndex, + EbvNumSubgroups, + EbvSubgroupID, + EbvSubGroupSize, + EbvSubGroupInvocation, + EbvSubGroupEqMask, + EbvSubGroupGeMask, + EbvSubGroupGtMask, + EbvSubGroupLeMask, + EbvSubGroupLtMask, + EbvSubgroupSize2, + EbvSubgroupInvocation2, + EbvSubgroupEqMask2, + EbvSubgroupGeMask2, + EbvSubgroupGtMask2, + EbvSubgroupLeMask2, + EbvSubgroupLtMask2, + EbvVertexId, + EbvInstanceId, + EbvVertexIndex, + EbvInstanceIndex, + EbvBaseVertex, + EbvBaseInstance, + EbvDrawId, + EbvPosition, + EbvPointSize, + EbvClipVertex, + EbvClipDistance, + EbvCullDistance, + EbvNormal, + EbvVertex, + EbvMultiTexCoord0, + EbvMultiTexCoord1, + EbvMultiTexCoord2, + EbvMultiTexCoord3, + EbvMultiTexCoord4, + EbvMultiTexCoord5, + EbvMultiTexCoord6, + EbvMultiTexCoord7, + EbvFrontColor, + EbvBackColor, + EbvFrontSecondaryColor, + EbvBackSecondaryColor, + EbvTexCoord, + EbvFogFragCoord, + EbvInvocationId, + EbvPrimitiveId, + EbvLayer, + EbvViewportIndex, + EbvPatchVertices, + EbvTessLevelOuter, + EbvTessLevelInner, + EbvBoundingBox, + EbvTessCoord, + EbvColor, + EbvSecondaryColor, + EbvFace, + EbvFragCoord, + EbvPointCoord, + EbvFragColor, + EbvFragData, + EbvFragDepth, + EbvFragStencilRef, + EbvSampleId, + EbvSamplePosition, + EbvSampleMask, + EbvHelperInvocation, + + EbvBaryCoordNoPersp, + EbvBaryCoordNoPerspCentroid, + EbvBaryCoordNoPerspSample, + EbvBaryCoordSmooth, + EbvBaryCoordSmoothCentroid, + EbvBaryCoordSmoothSample, + EbvBaryCoordPullModel, + + EbvViewIndex, + EbvDeviceIndex, + + EbvFragSizeEXT, + EbvFragInvocationCountEXT, + + EbvViewportMaskNV, + EbvSecondaryPositionNV, + EbvSecondaryViewportMaskNV, + EbvPositionPerViewNV, + EbvViewportMaskPerViewNV, + EbvFragFullyCoveredNV, + EbvFragmentSizeNV, + EbvInvocationsPerPixelNV, + // ray tracing + EbvLaunchId, + EbvLaunchSize, + EbvInstanceCustomIndex, + EbvGeometryIndex, + EbvWorldRayOrigin, + EbvWorldRayDirection, + EbvObjectRayOrigin, + EbvObjectRayDirection, + EbvRayTmin, + EbvRayTmax, + EbvHitT, + EbvHitKind, + EbvObjectToWorld, + EbvObjectToWorld3x4, + EbvWorldToObject, + EbvWorldToObject3x4, + EbvIncomingRayFlags, + // barycentrics + EbvBaryCoordNV, + EbvBaryCoordNoPerspNV, + // mesh shaders + EbvTaskCountNV, + EbvPrimitiveCountNV, + EbvPrimitiveIndicesNV, + EbvClipDistancePerViewNV, + EbvCullDistancePerViewNV, + EbvLayerPerViewNV, + EbvMeshViewCountNV, + EbvMeshViewIndicesNV, + + // sm builtins + EbvWarpsPerSM, + EbvSMCount, + EbvWarpID, + EbvSMID, + + // HLSL built-ins that live only temporarily, until they get remapped + // to one of the above. + EbvFragDepthGreater, + EbvFragDepthLesser, + EbvGsOutputStream, + EbvOutputPatch, + EbvInputPatch, + + // structbuffer types + EbvAppendConsume, // no need to differentiate append and consume + EbvRWStructuredBuffer, + EbvStructuredBuffer, + EbvByteAddressBuffer, + EbvRWByteAddressBuffer, + + EbvLast +}; + +// In this enum, order matters; users can assume higher precision is a bigger value +// and EpqNone is 0. +enum TPrecisionQualifier { + EpqNone = 0, + EpqLow, + EpqMedium, + EpqHigh +}; + +#ifdef GLSLANG_WEB +__inline const char* GetStorageQualifierString(TStorageQualifier q) { return ""; } +__inline const char* GetPrecisionQualifierString(TPrecisionQualifier p) { return ""; } +#else +// These will show up in error messages +__inline const char* GetStorageQualifierString(TStorageQualifier q) +{ + switch (q) { + case EvqTemporary: return "temp"; break; + case EvqGlobal: return "global"; break; + case EvqConst: return "const"; break; + case EvqConstReadOnly: return "const (read only)"; break; + case EvqVaryingIn: return "in"; break; + case EvqVaryingOut: return "out"; break; + case EvqUniform: return "uniform"; break; + case EvqBuffer: return "buffer"; break; + case EvqShared: return "shared"; break; + case EvqIn: return "in"; break; + case EvqOut: return "out"; break; + case EvqInOut: return "inout"; break; + case EvqVertexId: return "gl_VertexId"; break; + case EvqInstanceId: return "gl_InstanceId"; break; + case EvqPosition: return "gl_Position"; break; + case EvqPointSize: return "gl_PointSize"; break; + case EvqClipVertex: return "gl_ClipVertex"; break; + case EvqFace: return "gl_FrontFacing"; break; + case EvqFragCoord: return "gl_FragCoord"; break; + case EvqPointCoord: return "gl_PointCoord"; break; + case EvqFragColor: return "fragColor"; break; + case EvqFragDepth: return "gl_FragDepth"; break; + case EvqPayload: return "rayPayloadNV"; break; + case EvqPayloadIn: return "rayPayloadInNV"; break; + case EvqHitAttr: return "hitAttributeNV"; break; + case EvqCallableData: return "callableDataNV"; break; + case EvqCallableDataIn: return "callableDataInNV"; break; + default: return "unknown qualifier"; + } +} + +__inline const char* GetBuiltInVariableString(TBuiltInVariable v) +{ + switch (v) { + case EbvNone: return ""; + case EbvNumWorkGroups: return "NumWorkGroups"; + case EbvWorkGroupSize: return "WorkGroupSize"; + case EbvWorkGroupId: return "WorkGroupID"; + case EbvLocalInvocationId: return "LocalInvocationID"; + case EbvGlobalInvocationId: return "GlobalInvocationID"; + case EbvLocalInvocationIndex: return "LocalInvocationIndex"; + case EbvNumSubgroups: return "NumSubgroups"; + case EbvSubgroupID: return "SubgroupID"; + case EbvSubGroupSize: return "SubGroupSize"; + case EbvSubGroupInvocation: return "SubGroupInvocation"; + case EbvSubGroupEqMask: return "SubGroupEqMask"; + case EbvSubGroupGeMask: return "SubGroupGeMask"; + case EbvSubGroupGtMask: return "SubGroupGtMask"; + case EbvSubGroupLeMask: return "SubGroupLeMask"; + case EbvSubGroupLtMask: return "SubGroupLtMask"; + case EbvSubgroupSize2: return "SubgroupSize"; + case EbvSubgroupInvocation2: return "SubgroupInvocationID"; + case EbvSubgroupEqMask2: return "SubgroupEqMask"; + case EbvSubgroupGeMask2: return "SubgroupGeMask"; + case EbvSubgroupGtMask2: return "SubgroupGtMask"; + case EbvSubgroupLeMask2: return "SubgroupLeMask"; + case EbvSubgroupLtMask2: return "SubgroupLtMask"; + case EbvVertexId: return "VertexId"; + case EbvInstanceId: return "InstanceId"; + case EbvVertexIndex: return "VertexIndex"; + case EbvInstanceIndex: return "InstanceIndex"; + case EbvBaseVertex: return "BaseVertex"; + case EbvBaseInstance: return "BaseInstance"; + case EbvDrawId: return "DrawId"; + case EbvPosition: return "Position"; + case EbvPointSize: return "PointSize"; + case EbvClipVertex: return "ClipVertex"; + case EbvClipDistance: return "ClipDistance"; + case EbvCullDistance: return "CullDistance"; + case EbvNormal: return "Normal"; + case EbvVertex: return "Vertex"; + case EbvMultiTexCoord0: return "MultiTexCoord0"; + case EbvMultiTexCoord1: return "MultiTexCoord1"; + case EbvMultiTexCoord2: return "MultiTexCoord2"; + case EbvMultiTexCoord3: return "MultiTexCoord3"; + case EbvMultiTexCoord4: return "MultiTexCoord4"; + case EbvMultiTexCoord5: return "MultiTexCoord5"; + case EbvMultiTexCoord6: return "MultiTexCoord6"; + case EbvMultiTexCoord7: return "MultiTexCoord7"; + case EbvFrontColor: return "FrontColor"; + case EbvBackColor: return "BackColor"; + case EbvFrontSecondaryColor: return "FrontSecondaryColor"; + case EbvBackSecondaryColor: return "BackSecondaryColor"; + case EbvTexCoord: return "TexCoord"; + case EbvFogFragCoord: return "FogFragCoord"; + case EbvInvocationId: return "InvocationID"; + case EbvPrimitiveId: return "PrimitiveID"; + case EbvLayer: return "Layer"; + case EbvViewportIndex: return "ViewportIndex"; + case EbvPatchVertices: return "PatchVertices"; + case EbvTessLevelOuter: return "TessLevelOuter"; + case EbvTessLevelInner: return "TessLevelInner"; + case EbvBoundingBox: return "BoundingBox"; + case EbvTessCoord: return "TessCoord"; + case EbvColor: return "Color"; + case EbvSecondaryColor: return "SecondaryColor"; + case EbvFace: return "Face"; + case EbvFragCoord: return "FragCoord"; + case EbvPointCoord: return "PointCoord"; + case EbvFragColor: return "FragColor"; + case EbvFragData: return "FragData"; + case EbvFragDepth: return "FragDepth"; + case EbvFragStencilRef: return "FragStencilRef"; + case EbvSampleId: return "SampleId"; + case EbvSamplePosition: return "SamplePosition"; + case EbvSampleMask: return "SampleMaskIn"; + case EbvHelperInvocation: return "HelperInvocation"; + + case EbvBaryCoordNoPersp: return "BaryCoordNoPersp"; + case EbvBaryCoordNoPerspCentroid: return "BaryCoordNoPerspCentroid"; + case EbvBaryCoordNoPerspSample: return "BaryCoordNoPerspSample"; + case EbvBaryCoordSmooth: return "BaryCoordSmooth"; + case EbvBaryCoordSmoothCentroid: return "BaryCoordSmoothCentroid"; + case EbvBaryCoordSmoothSample: return "BaryCoordSmoothSample"; + case EbvBaryCoordPullModel: return "BaryCoordPullModel"; + + case EbvViewIndex: return "ViewIndex"; + case EbvDeviceIndex: return "DeviceIndex"; + + case EbvFragSizeEXT: return "FragSizeEXT"; + case EbvFragInvocationCountEXT: return "FragInvocationCountEXT"; + + case EbvViewportMaskNV: return "ViewportMaskNV"; + case EbvSecondaryPositionNV: return "SecondaryPositionNV"; + case EbvSecondaryViewportMaskNV: return "SecondaryViewportMaskNV"; + case EbvPositionPerViewNV: return "PositionPerViewNV"; + case EbvViewportMaskPerViewNV: return "ViewportMaskPerViewNV"; + case EbvFragFullyCoveredNV: return "FragFullyCoveredNV"; + case EbvFragmentSizeNV: return "FragmentSizeNV"; + case EbvInvocationsPerPixelNV: return "InvocationsPerPixelNV"; + case EbvLaunchId: return "LaunchIdNV"; + case EbvLaunchSize: return "LaunchSizeNV"; + case EbvInstanceCustomIndex: return "InstanceCustomIndexNV"; + case EbvGeometryIndex: return "GeometryIndexEXT"; + case EbvWorldRayOrigin: return "WorldRayOriginNV"; + case EbvWorldRayDirection: return "WorldRayDirectionNV"; + case EbvObjectRayOrigin: return "ObjectRayOriginNV"; + case EbvObjectRayDirection: return "ObjectRayDirectionNV"; + case EbvRayTmin: return "ObjectRayTminNV"; + case EbvRayTmax: return "ObjectRayTmaxNV"; + case EbvHitT: return "HitTNV"; + case EbvHitKind: return "HitKindNV"; + case EbvIncomingRayFlags: return "IncomingRayFlagsNV"; + case EbvObjectToWorld: return "ObjectToWorldNV"; + case EbvWorldToObject: return "WorldToObjectNV"; + + case EbvBaryCoordNV: return "BaryCoordNV"; + case EbvBaryCoordNoPerspNV: return "BaryCoordNoPerspNV"; + + case EbvTaskCountNV: return "TaskCountNV"; + case EbvPrimitiveCountNV: return "PrimitiveCountNV"; + case EbvPrimitiveIndicesNV: return "PrimitiveIndicesNV"; + case EbvClipDistancePerViewNV: return "ClipDistancePerViewNV"; + case EbvCullDistancePerViewNV: return "CullDistancePerViewNV"; + case EbvLayerPerViewNV: return "LayerPerViewNV"; + case EbvMeshViewCountNV: return "MeshViewCountNV"; + case EbvMeshViewIndicesNV: return "MeshViewIndicesNV"; + + case EbvWarpsPerSM: return "WarpsPerSMNV"; + case EbvSMCount: return "SMCountNV"; + case EbvWarpID: return "WarpIDNV"; + case EbvSMID: return "SMIDNV"; + + default: return "unknown built-in variable"; + } +} + +__inline const char* GetPrecisionQualifierString(TPrecisionQualifier p) +{ + switch (p) { + case EpqNone: return ""; break; + case EpqLow: return "lowp"; break; + case EpqMedium: return "mediump"; break; + case EpqHigh: return "highp"; break; + default: return "unknown precision qualifier"; + } +} +#endif + +__inline bool isTypeSignedInt(TBasicType type) +{ + switch (type) { + case EbtInt8: + case EbtInt16: + case EbtInt: + case EbtInt64: + return true; + default: + return false; + } +} + +__inline bool isTypeUnsignedInt(TBasicType type) +{ + switch (type) { + case EbtUint8: + case EbtUint16: + case EbtUint: + case EbtUint64: + return true; + default: + return false; + } +} + +__inline bool isTypeInt(TBasicType type) +{ + return isTypeSignedInt(type) || isTypeUnsignedInt(type); +} + +__inline bool isTypeFloat(TBasicType type) +{ + switch (type) { + case EbtFloat: + case EbtDouble: + case EbtFloat16: + return true; + default: + return false; + } +} + +__inline int getTypeRank(TBasicType type) +{ + int res = -1; + switch(type) { + case EbtInt8: + case EbtUint8: + res = 0; + break; + case EbtInt16: + case EbtUint16: + res = 1; + break; + case EbtInt: + case EbtUint: + res = 2; + break; + case EbtInt64: + case EbtUint64: + res = 3; + break; + default: + assert(false); + break; + } + return res; +} + +} // end namespace glslang + +#endif // _BASICTYPES_INCLUDED_ diff --git a/android/x86/include/glslang/Include/Common.h b/android/x86/include/glslang/Include/Common.h new file mode 100644 index 00000000..733a790c --- /dev/null +++ b/android/x86/include/glslang/Include/Common.h @@ -0,0 +1,292 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _COMMON_INCLUDED_ +#define _COMMON_INCLUDED_ + + +#if defined(__ANDROID__) || (defined(_MSC_VER) && _MSC_VER < 1700) +#include +namespace std { +template +std::string to_string(const T& val) { + std::ostringstream os; + os << val; + return os.str(); +} +} +#endif + +#if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/) || defined MINGW_HAS_SECURE_API + #include + #ifndef snprintf + #define snprintf sprintf_s + #endif + #define safe_vsprintf(buf,max,format,args) vsnprintf_s((buf), (max), (max), (format), (args)) +#elif defined (solaris) + #define safe_vsprintf(buf,max,format,args) vsnprintf((buf), (max), (format), (args)) + #include + #define UINT_PTR uintptr_t +#else + #define safe_vsprintf(buf,max,format,args) vsnprintf((buf), (max), (format), (args)) + #include + #define UINT_PTR uintptr_t +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1800 + #include + inline long long int strtoll (const char* str, char** endptr, int base) + { + return _strtoi64(str, endptr, base); + } + inline unsigned long long int strtoull (const char* str, char** endptr, int base) + { + return _strtoui64(str, endptr, base); + } + inline long long int atoll (const char* str) + { + return strtoll(str, NULL, 10); + } +#endif + +#if defined(_MSC_VER) +#define strdup _strdup +#endif + +/* windows only pragma */ +#ifdef _MSC_VER + #pragma warning(disable : 4786) // Don't warn about too long identifiers + #pragma warning(disable : 4514) // unused inline method + #pragma warning(disable : 4201) // nameless union +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "PoolAlloc.h" + +// +// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme. +// +#define POOL_ALLOCATOR_NEW_DELETE(A) \ + void* operator new(size_t s) { return (A).allocate(s); } \ + void* operator new(size_t, void *_Where) { return (_Where); } \ + void operator delete(void*) { } \ + void operator delete(void *, void *) { } \ + void* operator new[](size_t s) { return (A).allocate(s); } \ + void* operator new[](size_t, void *_Where) { return (_Where); } \ + void operator delete[](void*) { } \ + void operator delete[](void *, void *) { } + +namespace glslang { + + // + // Pool version of string. + // + typedef pool_allocator TStringAllocator; + typedef std::basic_string , TStringAllocator> TString; + +} // end namespace glslang + +// Repackage the std::hash for use by unordered map/set with a TString key. +namespace std { + + template<> struct hash { + std::size_t operator()(const glslang::TString& s) const + { + const unsigned _FNV_offset_basis = 2166136261U; + const unsigned _FNV_prime = 16777619U; + unsigned _Val = _FNV_offset_basis; + size_t _Count = s.size(); + const char* _First = s.c_str(); + for (size_t _Next = 0; _Next < _Count; ++_Next) + { + _Val ^= (unsigned)_First[_Next]; + _Val *= _FNV_prime; + } + + return _Val; + } + }; +} + +namespace glslang { + +inline TString* NewPoolTString(const char* s) +{ + void* memory = GetThreadPoolAllocator().allocate(sizeof(TString)); + return new(memory) TString(s); +} + +template inline T* NewPoolObject(T*) +{ + return new(GetThreadPoolAllocator().allocate(sizeof(T))) T; +} + +template inline T* NewPoolObject(T, int instances) +{ + return new(GetThreadPoolAllocator().allocate(instances * sizeof(T))) T[instances]; +} + +// +// Pool allocator versions of vectors, lists, and maps +// +template class TVector : public std::vector > { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + typedef typename std::vector >::size_type size_type; + TVector() : std::vector >() {} + TVector(const pool_allocator& a) : std::vector >(a) {} + TVector(size_type i) : std::vector >(i) {} + TVector(size_type i, const T& val) : std::vector >(i, val) {} +}; + +template class TList : public std::list > { +}; + +template > +class TMap : public std::map > > { +}; + +template , class PRED = std::equal_to > +class TUnorderedMap : public std::unordered_map > > { +}; + +// +// Persistent string memory. Should only be used for strings that survive +// across compiles/links. +// +typedef std::basic_string TPersistString; + +// +// templatized min and max functions. +// +template T Min(const T a, const T b) { return a < b ? a : b; } +template T Max(const T a, const T b) { return a > b ? a : b; } + +// +// Create a TString object from an integer. +// +#if defined _MSC_VER || defined MINGW_HAS_SECURE_API +inline const TString String(const int i, const int base = 10) +{ + char text[16]; // 32 bit ints are at most 10 digits in base 10 + _itoa_s(i, text, sizeof(text), base); + return text; +} +#else +inline const TString String(const int i, const int /*base*/ = 10) +{ + char text[16]; // 32 bit ints are at most 10 digits in base 10 + + // we assume base 10 for all cases + snprintf(text, sizeof(text), "%d", i); + + return text; +} +#endif + +struct TSourceLoc { + void init() + { + name = nullptr; string = 0; line = 0; column = 0; + } + void init(int stringNum) { init(); string = stringNum; } + // Returns the name if it exists. Otherwise, returns the string number. + std::string getStringNameOrNum(bool quoteStringName = true) const + { + if (name != nullptr) { + TString qstr = quoteStringName ? ("\"" + *name + "\"") : *name; + std::string ret_str(qstr.c_str()); + return ret_str; + } + return std::to_string((long long)string); + } + const char* getFilename() const + { + if (name == nullptr) + return nullptr; + return name->c_str(); + } + const char* getFilenameStr() const { return name == nullptr ? "" : name->c_str(); } + TString* name; // descriptive name for this string, when a textual name is available, otherwise nullptr + int string; + int line; + int column; +}; + +class TPragmaTable : public TMap { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) +}; + +const int MaxTokenLength = 1024; + +template bool IsPow2(T powerOf2) +{ + if (powerOf2 <= 0) + return false; + + return (powerOf2 & (powerOf2 - 1)) == 0; +} + +// Round number up to a multiple of the given powerOf2, which is not +// a power, just a number that must be a power of 2. +template void RoundToPow2(T& number, int powerOf2) +{ + assert(IsPow2(powerOf2)); + number = (number + powerOf2 - 1) & ~(powerOf2 - 1); +} + +template bool IsMultipleOfPow2(T number, int powerOf2) +{ + assert(IsPow2(powerOf2)); + return ! (number & (powerOf2 - 1)); +} + +} // end namespace glslang + +#endif // _COMMON_INCLUDED_ diff --git a/android/x86/include/glslang/Include/ConstantUnion.h b/android/x86/include/glslang/Include/ConstantUnion.h new file mode 100644 index 00000000..c4ffb857 --- /dev/null +++ b/android/x86/include/glslang/Include/ConstantUnion.h @@ -0,0 +1,974 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013 LunarG, Inc. +// Copyright (C) 2017 ARM Limited. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _CONSTANT_UNION_INCLUDED_ +#define _CONSTANT_UNION_INCLUDED_ + +#include "../Include/Common.h" +#include "../Include/BaseTypes.h" + +namespace glslang { + +class TConstUnion { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + TConstUnion() : iConst(0), type(EbtInt) { } + + void setI8Const(signed char i) + { + i8Const = i; + type = EbtInt8; + } + + void setU8Const(unsigned char u) + { + u8Const = u; + type = EbtUint8; + } + + void setI16Const(signed short i) + { + i16Const = i; + type = EbtInt16; + } + + void setU16Const(unsigned short u) + { + u16Const = u; + type = EbtUint16; + } + + void setIConst(int i) + { + iConst = i; + type = EbtInt; + } + + void setUConst(unsigned int u) + { + uConst = u; + type = EbtUint; + } + + void setI64Const(long long i64) + { + i64Const = i64; + type = EbtInt64; + } + + void setU64Const(unsigned long long u64) + { + u64Const = u64; + type = EbtUint64; + } + + void setDConst(double d) + { + dConst = d; + type = EbtDouble; + } + + void setBConst(bool b) + { + bConst = b; + type = EbtBool; + } + + void setSConst(const TString* s) + { + sConst = s; + type = EbtString; + } + + signed char getI8Const() const { return i8Const; } + unsigned char getU8Const() const { return u8Const; } + signed short getI16Const() const { return i16Const; } + unsigned short getU16Const() const { return u16Const; } + int getIConst() const { return iConst; } + unsigned int getUConst() const { return uConst; } + long long getI64Const() const { return i64Const; } + unsigned long long getU64Const() const { return u64Const; } + double getDConst() const { return dConst; } + bool getBConst() const { return bConst; } + const TString* getSConst() const { return sConst; } + + bool operator==(const signed char i) const + { + if (i == i8Const) + return true; + + return false; + } + + bool operator==(const unsigned char u) const + { + if (u == u8Const) + return true; + + return false; + } + + bool operator==(const signed short i) const + { + if (i == i16Const) + return true; + + return false; + } + + bool operator==(const unsigned short u) const + { + if (u == u16Const) + return true; + + return false; + } + + bool operator==(const int i) const + { + if (i == iConst) + return true; + + return false; + } + + bool operator==(const unsigned int u) const + { + if (u == uConst) + return true; + + return false; + } + + bool operator==(const long long i64) const + { + if (i64 == i64Const) + return true; + + return false; + } + + bool operator==(const unsigned long long u64) const + { + if (u64 == u64Const) + return true; + + return false; + } + + bool operator==(const double d) const + { + if (d == dConst) + return true; + + return false; + } + + bool operator==(const bool b) const + { + if (b == bConst) + return true; + + return false; + } + + bool operator==(const TConstUnion& constant) const + { + if (constant.type != type) + return false; + + switch (type) { + case EbtInt: + if (constant.iConst == iConst) + return true; + + break; + case EbtUint: + if (constant.uConst == uConst) + return true; + + break; + case EbtBool: + if (constant.bConst == bConst) + return true; + + break; + case EbtDouble: + if (constant.dConst == dConst) + return true; + + break; + +#ifndef GLSLANG_WEB + case EbtInt16: + if (constant.i16Const == i16Const) + return true; + + break; + case EbtUint16: + if (constant.u16Const == u16Const) + return true; + + break; + case EbtInt8: + if (constant.i8Const == i8Const) + return true; + + break; + case EbtUint8: + if (constant.u8Const == u8Const) + return true; + + break; + case EbtInt64: + if (constant.i64Const == i64Const) + return true; + + break; + case EbtUint64: + if (constant.u64Const == u64Const) + return true; + + break; +#endif + default: + assert(false && "Default missing"); + } + + return false; + } + + bool operator!=(const signed char i) const + { + return !operator==(i); + } + + bool operator!=(const unsigned char u) const + { + return !operator==(u); + } + + bool operator!=(const signed short i) const + { + return !operator==(i); + } + + bool operator!=(const unsigned short u) const + { + return !operator==(u); + } + + bool operator!=(const int i) const + { + return !operator==(i); + } + + bool operator!=(const unsigned int u) const + { + return !operator==(u); + } + + bool operator!=(const long long i) const + { + return !operator==(i); + } + + bool operator!=(const unsigned long long u) const + { + return !operator==(u); + } + + bool operator!=(const float f) const + { + return !operator==(f); + } + + bool operator!=(const bool b) const + { + return !operator==(b); + } + + bool operator!=(const TConstUnion& constant) const + { + return !operator==(constant); + } + + bool operator>(const TConstUnion& constant) const + { + assert(type == constant.type); + switch (type) { + case EbtInt: + if (iConst > constant.iConst) + return true; + + return false; + case EbtUint: + if (uConst > constant.uConst) + return true; + + return false; + case EbtDouble: + if (dConst > constant.dConst) + return true; + + return false; +#ifndef GLSLANG_WEB + case EbtInt8: + if (i8Const > constant.i8Const) + return true; + + return false; + case EbtUint8: + if (u8Const > constant.u8Const) + return true; + + return false; + case EbtInt16: + if (i16Const > constant.i16Const) + return true; + + return false; + case EbtUint16: + if (u16Const > constant.u16Const) + return true; + + return false; + case EbtInt64: + if (i64Const > constant.i64Const) + return true; + + return false; + case EbtUint64: + if (u64Const > constant.u64Const) + return true; + + return false; +#endif + default: + assert(false && "Default missing"); + return false; + } + } + + bool operator<(const TConstUnion& constant) const + { + assert(type == constant.type); + switch (type) { +#ifndef GLSLANG_WEB + case EbtInt8: + if (i8Const < constant.i8Const) + return true; + + return false; + case EbtUint8: + if (u8Const < constant.u8Const) + return true; + + return false; + case EbtInt16: + if (i16Const < constant.i16Const) + return true; + + return false; + case EbtUint16: + if (u16Const < constant.u16Const) + return true; + return false; + case EbtInt64: + if (i64Const < constant.i64Const) + return true; + + return false; + case EbtUint64: + if (u64Const < constant.u64Const) + return true; + + return false; +#endif + case EbtDouble: + if (dConst < constant.dConst) + return true; + + return false; + case EbtInt: + if (iConst < constant.iConst) + return true; + + return false; + case EbtUint: + if (uConst < constant.uConst) + return true; + + return false; + default: + assert(false && "Default missing"); + return false; + } + } + + TConstUnion operator+(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst + constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst + constant.uConst); break; + case EbtDouble: returnValue.setDConst(dConst + constant.dConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const + constant.i8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const + constant.i16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const + constant.i64Const); break; + case EbtUint8: returnValue.setU8Const(u8Const + constant.u8Const); break; + case EbtUint16: returnValue.setU16Const(u16Const + constant.u16Const); break; + case EbtUint64: returnValue.setU64Const(u64Const + constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator-(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst - constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst - constant.uConst); break; + case EbtDouble: returnValue.setDConst(dConst - constant.dConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const - constant.i8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const - constant.i16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const - constant.i64Const); break; + case EbtUint8: returnValue.setU8Const(u8Const - constant.u8Const); break; + case EbtUint16: returnValue.setU16Const(u16Const - constant.u16Const); break; + case EbtUint64: returnValue.setU64Const(u64Const - constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator*(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst * constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst * constant.uConst); break; + case EbtDouble: returnValue.setDConst(dConst * constant.dConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const * constant.i8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const * constant.i16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const * constant.i64Const); break; + case EbtUint8: returnValue.setU8Const(u8Const * constant.u8Const); break; + case EbtUint16: returnValue.setU16Const(u16Const * constant.u16Const); break; + case EbtUint64: returnValue.setU64Const(u64Const * constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator%(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst % constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst % constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const % constant.i8Const); break; + case EbtInt16: returnValue.setI8Const(i8Const % constant.i16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const % constant.i64Const); break; + case EbtUint8: returnValue.setU8Const(u8Const % constant.u8Const); break; + case EbtUint16: returnValue.setU16Const(u16Const % constant.u16Const); break; + case EbtUint64: returnValue.setU64Const(u64Const % constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator>>(const TConstUnion& constant) const + { + TConstUnion returnValue; + switch (type) { +#ifndef GLSLANG_WEB + case EbtInt8: + switch (constant.type) { + case EbtInt8: returnValue.setI8Const(i8Const >> constant.i8Const); break; + case EbtUint8: returnValue.setI8Const(i8Const >> constant.u8Const); break; + case EbtInt16: returnValue.setI8Const(i8Const >> constant.i16Const); break; + case EbtUint16: returnValue.setI8Const(i8Const >> constant.u16Const); break; + case EbtInt: returnValue.setI8Const(i8Const >> constant.iConst); break; + case EbtUint: returnValue.setI8Const(i8Const >> constant.uConst); break; + case EbtInt64: returnValue.setI8Const(i8Const >> constant.i64Const); break; + case EbtUint64: returnValue.setI8Const(i8Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint8: + switch (constant.type) { + case EbtInt8: returnValue.setU8Const(u8Const >> constant.i8Const); break; + case EbtUint8: returnValue.setU8Const(u8Const >> constant.u8Const); break; + case EbtInt16: returnValue.setU8Const(u8Const >> constant.i16Const); break; + case EbtUint16: returnValue.setU8Const(u8Const >> constant.u16Const); break; + case EbtInt: returnValue.setU8Const(u8Const >> constant.iConst); break; + case EbtUint: returnValue.setU8Const(u8Const >> constant.uConst); break; + case EbtInt64: returnValue.setU8Const(u8Const >> constant.i64Const); break; + case EbtUint64: returnValue.setU8Const(u8Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtInt16: + switch (constant.type) { + case EbtInt8: returnValue.setI16Const(i16Const >> constant.i8Const); break; + case EbtUint8: returnValue.setI16Const(i16Const >> constant.u8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const >> constant.i16Const); break; + case EbtUint16: returnValue.setI16Const(i16Const >> constant.u16Const); break; + case EbtInt: returnValue.setI16Const(i16Const >> constant.iConst); break; + case EbtUint: returnValue.setI16Const(i16Const >> constant.uConst); break; + case EbtInt64: returnValue.setI16Const(i16Const >> constant.i64Const); break; + case EbtUint64: returnValue.setI16Const(i16Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint16: + switch (constant.type) { + case EbtInt8: returnValue.setU16Const(u16Const >> constant.i8Const); break; + case EbtUint8: returnValue.setU16Const(u16Const >> constant.u8Const); break; + case EbtInt16: returnValue.setU16Const(u16Const >> constant.i16Const); break; + case EbtUint16: returnValue.setU16Const(u16Const >> constant.u16Const); break; + case EbtInt: returnValue.setU16Const(u16Const >> constant.iConst); break; + case EbtUint: returnValue.setU16Const(u16Const >> constant.uConst); break; + case EbtInt64: returnValue.setU16Const(u16Const >> constant.i64Const); break; + case EbtUint64: returnValue.setU16Const(u16Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; +#endif + case EbtInt: + switch (constant.type) { + case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break; + case EbtUint: returnValue.setIConst(iConst >> constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setIConst(iConst >> constant.i8Const); break; + case EbtUint8: returnValue.setIConst(iConst >> constant.u8Const); break; + case EbtInt16: returnValue.setIConst(iConst >> constant.i16Const); break; + case EbtUint16: returnValue.setIConst(iConst >> constant.u16Const); break; + case EbtInt64: returnValue.setIConst(iConst >> constant.i64Const); break; + case EbtUint64: returnValue.setIConst(iConst >> constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + break; + case EbtUint: + switch (constant.type) { + case EbtInt: returnValue.setUConst(uConst >> constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst >> constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setUConst(uConst >> constant.i8Const); break; + case EbtUint8: returnValue.setUConst(uConst >> constant.u8Const); break; + case EbtInt16: returnValue.setUConst(uConst >> constant.i16Const); break; + case EbtUint16: returnValue.setUConst(uConst >> constant.u16Const); break; + case EbtInt64: returnValue.setUConst(uConst >> constant.i64Const); break; + case EbtUint64: returnValue.setUConst(uConst >> constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + break; +#ifndef GLSLANG_WEB + case EbtInt64: + switch (constant.type) { + case EbtInt8: returnValue.setI64Const(i64Const >> constant.i8Const); break; + case EbtUint8: returnValue.setI64Const(i64Const >> constant.u8Const); break; + case EbtInt16: returnValue.setI64Const(i64Const >> constant.i16Const); break; + case EbtUint16: returnValue.setI64Const(i64Const >> constant.u16Const); break; + case EbtInt: returnValue.setI64Const(i64Const >> constant.iConst); break; + case EbtUint: returnValue.setI64Const(i64Const >> constant.uConst); break; + case EbtInt64: returnValue.setI64Const(i64Const >> constant.i64Const); break; + case EbtUint64: returnValue.setI64Const(i64Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint64: + switch (constant.type) { + case EbtInt8: returnValue.setU64Const(u64Const >> constant.i8Const); break; + case EbtUint8: returnValue.setU64Const(u64Const >> constant.u8Const); break; + case EbtInt16: returnValue.setU64Const(u64Const >> constant.i16Const); break; + case EbtUint16: returnValue.setU64Const(u64Const >> constant.u16Const); break; + case EbtInt: returnValue.setU64Const(u64Const >> constant.iConst); break; + case EbtUint: returnValue.setU64Const(u64Const >> constant.uConst); break; + case EbtInt64: returnValue.setU64Const(u64Const >> constant.i64Const); break; + case EbtUint64: returnValue.setU64Const(u64Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator<<(const TConstUnion& constant) const + { + TConstUnion returnValue; + switch (type) { +#ifndef GLSLANG_WEB + case EbtInt8: + switch (constant.type) { + case EbtInt8: returnValue.setI8Const(i8Const << constant.i8Const); break; + case EbtUint8: returnValue.setI8Const(i8Const << constant.u8Const); break; + case EbtInt16: returnValue.setI8Const(i8Const << constant.i16Const); break; + case EbtUint16: returnValue.setI8Const(i8Const << constant.u16Const); break; + case EbtInt: returnValue.setI8Const(i8Const << constant.iConst); break; + case EbtUint: returnValue.setI8Const(i8Const << constant.uConst); break; + case EbtInt64: returnValue.setI8Const(i8Const << constant.i64Const); break; + case EbtUint64: returnValue.setI8Const(i8Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint8: + switch (constant.type) { + case EbtInt8: returnValue.setU8Const(u8Const << constant.i8Const); break; + case EbtUint8: returnValue.setU8Const(u8Const << constant.u8Const); break; + case EbtInt16: returnValue.setU8Const(u8Const << constant.i16Const); break; + case EbtUint16: returnValue.setU8Const(u8Const << constant.u16Const); break; + case EbtInt: returnValue.setU8Const(u8Const << constant.iConst); break; + case EbtUint: returnValue.setU8Const(u8Const << constant.uConst); break; + case EbtInt64: returnValue.setU8Const(u8Const << constant.i64Const); break; + case EbtUint64: returnValue.setU8Const(u8Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtInt16: + switch (constant.type) { + case EbtInt8: returnValue.setI16Const(i16Const << constant.i8Const); break; + case EbtUint8: returnValue.setI16Const(i16Const << constant.u8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const << constant.i16Const); break; + case EbtUint16: returnValue.setI16Const(i16Const << constant.u16Const); break; + case EbtInt: returnValue.setI16Const(i16Const << constant.iConst); break; + case EbtUint: returnValue.setI16Const(i16Const << constant.uConst); break; + case EbtInt64: returnValue.setI16Const(i16Const << constant.i64Const); break; + case EbtUint64: returnValue.setI16Const(i16Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint16: + switch (constant.type) { + case EbtInt8: returnValue.setU16Const(u16Const << constant.i8Const); break; + case EbtUint8: returnValue.setU16Const(u16Const << constant.u8Const); break; + case EbtInt16: returnValue.setU16Const(u16Const << constant.i16Const); break; + case EbtUint16: returnValue.setU16Const(u16Const << constant.u16Const); break; + case EbtInt: returnValue.setU16Const(u16Const << constant.iConst); break; + case EbtUint: returnValue.setU16Const(u16Const << constant.uConst); break; + case EbtInt64: returnValue.setU16Const(u16Const << constant.i64Const); break; + case EbtUint64: returnValue.setU16Const(u16Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtInt64: + switch (constant.type) { + case EbtInt8: returnValue.setI64Const(i64Const << constant.i8Const); break; + case EbtUint8: returnValue.setI64Const(i64Const << constant.u8Const); break; + case EbtInt16: returnValue.setI64Const(i64Const << constant.i16Const); break; + case EbtUint16: returnValue.setI64Const(i64Const << constant.u16Const); break; + case EbtInt: returnValue.setI64Const(i64Const << constant.iConst); break; + case EbtUint: returnValue.setI64Const(i64Const << constant.uConst); break; + case EbtInt64: returnValue.setI64Const(i64Const << constant.i64Const); break; + case EbtUint64: returnValue.setI64Const(i64Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint64: + switch (constant.type) { + case EbtInt8: returnValue.setU64Const(u64Const << constant.i8Const); break; + case EbtUint8: returnValue.setU64Const(u64Const << constant.u8Const); break; + case EbtInt16: returnValue.setU64Const(u64Const << constant.i16Const); break; + case EbtUint16: returnValue.setU64Const(u64Const << constant.u16Const); break; + case EbtInt: returnValue.setU64Const(u64Const << constant.iConst); break; + case EbtUint: returnValue.setU64Const(u64Const << constant.uConst); break; + case EbtInt64: returnValue.setU64Const(u64Const << constant.i64Const); break; + case EbtUint64: returnValue.setU64Const(u64Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; +#endif + case EbtInt: + switch (constant.type) { + case EbtInt: returnValue.setIConst(iConst << constant.iConst); break; + case EbtUint: returnValue.setIConst(iConst << constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setIConst(iConst << constant.i8Const); break; + case EbtUint8: returnValue.setIConst(iConst << constant.u8Const); break; + case EbtInt16: returnValue.setIConst(iConst << constant.i16Const); break; + case EbtUint16: returnValue.setIConst(iConst << constant.u16Const); break; + case EbtInt64: returnValue.setIConst(iConst << constant.i64Const); break; + case EbtUint64: returnValue.setIConst(iConst << constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + break; + case EbtUint: + switch (constant.type) { + case EbtInt: returnValue.setUConst(uConst << constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst << constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setUConst(uConst << constant.i8Const); break; + case EbtUint8: returnValue.setUConst(uConst << constant.u8Const); break; + case EbtInt16: returnValue.setUConst(uConst << constant.i16Const); break; + case EbtUint16: returnValue.setUConst(uConst << constant.u16Const); break; + case EbtInt64: returnValue.setUConst(uConst << constant.i64Const); break; + case EbtUint64: returnValue.setUConst(uConst << constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator&(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst & constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst & constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const & constant.i8Const); break; + case EbtUint8: returnValue.setU8Const(u8Const & constant.u8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const & constant.i16Const); break; + case EbtUint16: returnValue.setU16Const(u16Const & constant.u16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const & constant.i64Const); break; + case EbtUint64: returnValue.setU64Const(u64Const & constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator|(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst | constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst | constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const | constant.i8Const); break; + case EbtUint8: returnValue.setU8Const(u8Const | constant.u8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const | constant.i16Const); break; + case EbtUint16: returnValue.setU16Const(u16Const | constant.u16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const | constant.i64Const); break; + case EbtUint64: returnValue.setU64Const(u64Const | constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator^(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst ^ constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst ^ constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const ^ constant.i8Const); break; + case EbtUint8: returnValue.setU8Const(u8Const ^ constant.u8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const ^ constant.i16Const); break; + case EbtUint16: returnValue.setU16Const(u16Const ^ constant.u16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const ^ constant.i64Const); break; + case EbtUint64: returnValue.setU64Const(u64Const ^ constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator~() const + { + TConstUnion returnValue; + switch (type) { + case EbtInt: returnValue.setIConst(~iConst); break; + case EbtUint: returnValue.setUConst(~uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(~i8Const); break; + case EbtUint8: returnValue.setU8Const(~u8Const); break; + case EbtInt16: returnValue.setI16Const(~i16Const); break; + case EbtUint16: returnValue.setU16Const(~u16Const); break; + case EbtInt64: returnValue.setI64Const(~i64Const); break; + case EbtUint64: returnValue.setU64Const(~u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator&&(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtBool: returnValue.setBConst(bConst && constant.bConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator||(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtBool: returnValue.setBConst(bConst || constant.bConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TBasicType getType() const { return type; } + +private: + union { + signed char i8Const; // used for i8vec, scalar int8s + unsigned char u8Const; // used for u8vec, scalar uint8s + signed short i16Const; // used for i16vec, scalar int16s + unsigned short u16Const; // used for u16vec, scalar uint16s + int iConst; // used for ivec, scalar ints + unsigned int uConst; // used for uvec, scalar uints + long long i64Const; // used for i64vec, scalar int64s + unsigned long long u64Const; // used for u64vec, scalar uint64s + bool bConst; // used for bvec, scalar bools + double dConst; // used for vec, dvec, mat, dmat, scalar floats and doubles + const TString* sConst; // string constant + }; + + TBasicType type; +}; + +// Encapsulate having a pointer to an array of TConstUnion, +// which only needs to be allocated if its size is going to be +// bigger than 0. +// +// One convenience is being able to use [] to go inside the array, instead +// of C++ assuming it as an array of pointers to vectors. +// +// General usage is that the size is known up front, and it is +// created once with the proper size. +// +class TConstUnionArray { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + TConstUnionArray() : unionArray(nullptr) { } + virtual ~TConstUnionArray() { } + + explicit TConstUnionArray(int size) + { + if (size == 0) + unionArray = nullptr; + else + unionArray = new TConstUnionVector(size); + } + TConstUnionArray(const TConstUnionArray& a) = default; + TConstUnionArray(const TConstUnionArray& a, int start, int size) + { + unionArray = new TConstUnionVector(size); + for (int i = 0; i < size; ++i) + (*unionArray)[i] = a[start + i]; + } + + // Use this constructor for a smear operation + TConstUnionArray(int size, const TConstUnion& val) + { + unionArray = new TConstUnionVector(size, val); + } + + int size() const { return unionArray ? (int)unionArray->size() : 0; } + TConstUnion& operator[](size_t index) { return (*unionArray)[index]; } + const TConstUnion& operator[](size_t index) const { return (*unionArray)[index]; } + bool operator==(const TConstUnionArray& rhs) const + { + // this includes the case that both are unallocated + if (unionArray == rhs.unionArray) + return true; + + if (! unionArray || ! rhs.unionArray) + return false; + + return *unionArray == *rhs.unionArray; + } + bool operator!=(const TConstUnionArray& rhs) const { return ! operator==(rhs); } + + double dot(const TConstUnionArray& rhs) + { + assert(rhs.unionArray->size() == unionArray->size()); + double sum = 0.0; + + for (size_t comp = 0; comp < unionArray->size(); ++comp) + sum += (*this)[comp].getDConst() * rhs[comp].getDConst(); + + return sum; + } + + bool empty() const { return unionArray == nullptr; } + +protected: + typedef TVector TConstUnionVector; + TConstUnionVector* unionArray; +}; + +} // end namespace glslang + +#endif // _CONSTANT_UNION_INCLUDED_ diff --git a/android/x86/include/glslang/Include/InfoSink.h b/android/x86/include/glslang/Include/InfoSink.h new file mode 100644 index 00000000..dceb603c --- /dev/null +++ b/android/x86/include/glslang/Include/InfoSink.h @@ -0,0 +1,144 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _INFOSINK_INCLUDED_ +#define _INFOSINK_INCLUDED_ + +#include "../Include/Common.h" +#include + +namespace glslang { + +// +// TPrefixType is used to centralize how info log messages start. +// See below. +// +enum TPrefixType { + EPrefixNone, + EPrefixWarning, + EPrefixError, + EPrefixInternalError, + EPrefixUnimplemented, + EPrefixNote +}; + +enum TOutputStream { + ENull = 0, + EDebugger = 0x01, + EStdOut = 0x02, + EString = 0x04, +}; +// +// Encapsulate info logs for all objects that have them. +// +// The methods are a general set of tools for getting a variety of +// messages and types inserted into the log. +// +class TInfoSinkBase { +public: + TInfoSinkBase() : outputStream(4) {} + void erase() { sink.erase(); } + TInfoSinkBase& operator<<(const TPersistString& t) { append(t); return *this; } + TInfoSinkBase& operator<<(char c) { append(1, c); return *this; } + TInfoSinkBase& operator<<(const char* s) { append(s); return *this; } + TInfoSinkBase& operator<<(int n) { append(String(n)); return *this; } + TInfoSinkBase& operator<<(unsigned int n) { append(String(n)); return *this; } + TInfoSinkBase& operator<<(float n) { const int size = 40; char buf[size]; + snprintf(buf, size, (fabs(n) > 1e-8 && fabs(n) < 1e8) || n == 0.0f ? "%f" : "%g", n); + append(buf); + return *this; } + TInfoSinkBase& operator+(const TPersistString& t) { append(t); return *this; } + TInfoSinkBase& operator+(const TString& t) { append(t); return *this; } + TInfoSinkBase& operator<<(const TString& t) { append(t); return *this; } + TInfoSinkBase& operator+(const char* s) { append(s); return *this; } + const char* c_str() const { return sink.c_str(); } + void prefix(TPrefixType message) { + switch(message) { + case EPrefixNone: break; + case EPrefixWarning: append("WARNING: "); break; + case EPrefixError: append("ERROR: "); break; + case EPrefixInternalError: append("INTERNAL ERROR: "); break; + case EPrefixUnimplemented: append("UNIMPLEMENTED: "); break; + case EPrefixNote: append("NOTE: "); break; + default: append("UNKNOWN ERROR: "); break; + } + } + void location(const TSourceLoc& loc) { + const int maxSize = 24; + char locText[maxSize]; + snprintf(locText, maxSize, ":%d", loc.line); + append(loc.getStringNameOrNum(false).c_str()); + append(locText); + append(": "); + } + void message(TPrefixType message, const char* s) { + prefix(message); + append(s); + append("\n"); + } + void message(TPrefixType message, const char* s, const TSourceLoc& loc) { + prefix(message); + location(loc); + append(s); + append("\n"); + } + + void setOutputStream(int output = 4) + { + outputStream = output; + } + +protected: + void append(const char* s); + + void append(int count, char c); + void append(const TPersistString& t); + void append(const TString& t); + + void checkMem(size_t growth) { if (sink.capacity() < sink.size() + growth + 2) + sink.reserve(sink.capacity() + sink.capacity() / 2); } + void appendToStream(const char* s); + TPersistString sink; + int outputStream; +}; + +} // end namespace glslang + +class TInfoSink { +public: + glslang::TInfoSinkBase info; + glslang::TInfoSinkBase debug; +}; + +#endif // _INFOSINK_INCLUDED_ diff --git a/android/x86/include/glslang/Include/InitializeGlobals.h b/android/x86/include/glslang/Include/InitializeGlobals.h new file mode 100644 index 00000000..95d0a40e --- /dev/null +++ b/android/x86/include/glslang/Include/InitializeGlobals.h @@ -0,0 +1,44 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef __INITIALIZE_GLOBALS_INCLUDED_ +#define __INITIALIZE_GLOBALS_INCLUDED_ + +namespace glslang { + +bool InitializePoolIndex(); + +} // end namespace glslang + +#endif // __INITIALIZE_GLOBALS_INCLUDED_ diff --git a/android/x86/include/glslang/Include/PoolAlloc.h b/android/x86/include/glslang/Include/PoolAlloc.h new file mode 100644 index 00000000..b8eccb88 --- /dev/null +++ b/android/x86/include/glslang/Include/PoolAlloc.h @@ -0,0 +1,316 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _POOLALLOC_INCLUDED_ +#define _POOLALLOC_INCLUDED_ + +#ifdef _DEBUG +# define GUARD_BLOCKS // define to enable guard block sanity checking +#endif + +// +// This header defines an allocator that can be used to efficiently +// allocate a large number of small requests for heap memory, with the +// intention that they are not individually deallocated, but rather +// collectively deallocated at one time. +// +// This simultaneously +// +// * Makes each individual allocation much more efficient; the +// typical allocation is trivial. +// * Completely avoids the cost of doing individual deallocation. +// * Saves the trouble of tracking down and plugging a large class of leaks. +// +// Individual classes can use this allocator by supplying their own +// new and delete methods. +// +// STL containers can use this allocator by using the pool_allocator +// class as the allocator (second) template argument. +// + +#include +#include +#include + +namespace glslang { + +// If we are using guard blocks, we must track each individual +// allocation. If we aren't using guard blocks, these +// never get instantiated, so won't have any impact. +// + +class TAllocation { +public: + TAllocation(size_t size, unsigned char* mem, TAllocation* prev = 0) : + size(size), mem(mem), prevAlloc(prev) { + // Allocations are bracketed: + // [allocationHeader][initialGuardBlock][userData][finalGuardBlock] + // This would be cleaner with if (guardBlockSize)..., but that + // makes the compiler print warnings about 0 length memsets, + // even with the if() protecting them. +# ifdef GUARD_BLOCKS + memset(preGuard(), guardBlockBeginVal, guardBlockSize); + memset(data(), userDataFill, size); + memset(postGuard(), guardBlockEndVal, guardBlockSize); +# endif + } + + void check() const { + checkGuardBlock(preGuard(), guardBlockBeginVal, "before"); + checkGuardBlock(postGuard(), guardBlockEndVal, "after"); + } + + void checkAllocList() const; + + // Return total size needed to accommodate user buffer of 'size', + // plus our tracking data. + inline static size_t allocationSize(size_t size) { + return size + 2 * guardBlockSize + headerSize(); + } + + // Offset from surrounding buffer to get to user data buffer. + inline static unsigned char* offsetAllocation(unsigned char* m) { + return m + guardBlockSize + headerSize(); + } + +private: + void checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const; + + // Find offsets to pre and post guard blocks, and user data buffer + unsigned char* preGuard() const { return mem + headerSize(); } + unsigned char* data() const { return preGuard() + guardBlockSize; } + unsigned char* postGuard() const { return data() + size; } + + size_t size; // size of the user data area + unsigned char* mem; // beginning of our allocation (pts to header) + TAllocation* prevAlloc; // prior allocation in the chain + + const static unsigned char guardBlockBeginVal; + const static unsigned char guardBlockEndVal; + const static unsigned char userDataFill; + + const static size_t guardBlockSize; +# ifdef GUARD_BLOCKS + inline static size_t headerSize() { return sizeof(TAllocation); } +# else + inline static size_t headerSize() { return 0; } +# endif +}; + +// +// There are several stacks. One is to track the pushing and popping +// of the user, and not yet implemented. The others are simply a +// repositories of free pages or used pages. +// +// Page stacks are linked together with a simple header at the beginning +// of each allocation obtained from the underlying OS. Multi-page allocations +// are returned to the OS. Individual page allocations are kept for future +// re-use. +// +// The "page size" used is not, nor must it match, the underlying OS +// page size. But, having it be about that size or equal to a set of +// pages is likely most optimal. +// +class TPoolAllocator { +public: + TPoolAllocator(int growthIncrement = 8*1024, int allocationAlignment = 16); + + // + // Don't call the destructor just to free up the memory, call pop() + // + ~TPoolAllocator(); + + // + // Call push() to establish a new place to pop memory too. Does not + // have to be called to get things started. + // + void push(); + + // + // Call pop() to free all memory allocated since the last call to push(), + // or if no last call to push, frees all memory since first allocation. + // + void pop(); + + // + // Call popAll() to free all memory allocated. + // + void popAll(); + + // + // Call allocate() to actually acquire memory. Returns 0 if no memory + // available, otherwise a properly aligned pointer to 'numBytes' of memory. + // + void* allocate(size_t numBytes); + + // + // There is no deallocate. The point of this class is that + // deallocation can be skipped by the user of it, as the model + // of use is to simultaneously deallocate everything at once + // by calling pop(), and to not have to solve memory leak problems. + // + +protected: + friend struct tHeader; + + struct tHeader { + tHeader(tHeader* nextPage, size_t pageCount) : +#ifdef GUARD_BLOCKS + lastAllocation(0), +#endif + nextPage(nextPage), pageCount(pageCount) { } + + ~tHeader() { +#ifdef GUARD_BLOCKS + if (lastAllocation) + lastAllocation->checkAllocList(); +#endif + } + +#ifdef GUARD_BLOCKS + TAllocation* lastAllocation; +#endif + tHeader* nextPage; + size_t pageCount; + }; + + struct tAllocState { + size_t offset; + tHeader* page; + }; + typedef std::vector tAllocStack; + + // Track allocations if and only if we're using guard blocks +#ifndef GUARD_BLOCKS + void* initializeAllocation(tHeader*, unsigned char* memory, size_t) { +#else + void* initializeAllocation(tHeader* block, unsigned char* memory, size_t numBytes) { + new(memory) TAllocation(numBytes, memory, block->lastAllocation); + block->lastAllocation = reinterpret_cast(memory); +#endif + + // This is optimized entirely away if GUARD_BLOCKS is not defined. + return TAllocation::offsetAllocation(memory); + } + + size_t pageSize; // granularity of allocation from the OS + size_t alignment; // all returned allocations will be aligned at + // this granularity, which will be a power of 2 + size_t alignmentMask; + size_t headerSkip; // amount of memory to skip to make room for the + // header (basically, size of header, rounded + // up to make it aligned + size_t currentPageOffset; // next offset in top of inUseList to allocate from + tHeader* freeList; // list of popped memory + tHeader* inUseList; // list of all memory currently being used + tAllocStack stack; // stack of where to allocate from, to partition pool + + int numCalls; // just an interesting statistic + size_t totalBytes; // just an interesting statistic +private: + TPoolAllocator& operator=(const TPoolAllocator&); // don't allow assignment operator + TPoolAllocator(const TPoolAllocator&); // don't allow default copy constructor +}; + +// +// There could potentially be many pools with pops happening at +// different times. But a simple use is to have a global pop +// with everyone using the same global allocator. +// +extern TPoolAllocator& GetThreadPoolAllocator(); +void SetThreadPoolAllocator(TPoolAllocator* poolAllocator); + +// +// This STL compatible allocator is intended to be used as the allocator +// parameter to templatized STL containers, like vector and map. +// +// It will use the pools for allocation, and not +// do any deallocation, but will still do destruction. +// +template +class pool_allocator { +public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T *pointer; + typedef const T *const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T value_type; + template + struct rebind { + typedef pool_allocator other; + }; + pointer address(reference x) const { return &x; } + const_pointer address(const_reference x) const { return &x; } + + pool_allocator() : allocator(GetThreadPoolAllocator()) { } + pool_allocator(TPoolAllocator& a) : allocator(a) { } + pool_allocator(const pool_allocator& p) : allocator(p.allocator) { } + + template + pool_allocator(const pool_allocator& p) : allocator(p.getAllocator()) { } + + pointer allocate(size_type n) { + return reinterpret_cast(getAllocator().allocate(n * sizeof(T))); } + pointer allocate(size_type n, const void*) { + return reinterpret_cast(getAllocator().allocate(n * sizeof(T))); } + + void deallocate(void*, size_type) { } + void deallocate(pointer, size_type) { } + + pointer _Charalloc(size_t n) { + return reinterpret_cast(getAllocator().allocate(n)); } + + void construct(pointer p, const T& val) { new ((void *)p) T(val); } + void destroy(pointer p) { p->T::~T(); } + + bool operator==(const pool_allocator& rhs) const { return &getAllocator() == &rhs.getAllocator(); } + bool operator!=(const pool_allocator& rhs) const { return &getAllocator() != &rhs.getAllocator(); } + + size_type max_size() const { return static_cast(-1) / sizeof(T); } + size_type max_size(int size) const { return static_cast(-1) / size; } + + TPoolAllocator& getAllocator() const { return allocator; } + +protected: + pool_allocator& operator=(const pool_allocator&) { return *this; } + TPoolAllocator& allocator; +}; + +} // end namespace glslang + +#endif // _POOLALLOC_INCLUDED_ diff --git a/android/x86/include/glslang/Include/ResourceLimits.h b/android/x86/include/glslang/Include/ResourceLimits.h new file mode 100644 index 00000000..106b21d9 --- /dev/null +++ b/android/x86/include/glslang/Include/ResourceLimits.h @@ -0,0 +1,149 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _RESOURCE_LIMITS_INCLUDED_ +#define _RESOURCE_LIMITS_INCLUDED_ + +struct TLimits { + bool nonInductiveForLoops; + bool whileLoops; + bool doWhileLoops; + bool generalUniformIndexing; + bool generalAttributeMatrixVectorIndexing; + bool generalVaryingIndexing; + bool generalSamplerIndexing; + bool generalVariableIndexing; + bool generalConstantMatrixVectorIndexing; +}; + +struct TBuiltInResource { + int maxLights; + int maxClipPlanes; + int maxTextureUnits; + int maxTextureCoords; + int maxVertexAttribs; + int maxVertexUniformComponents; + int maxVaryingFloats; + int maxVertexTextureImageUnits; + int maxCombinedTextureImageUnits; + int maxTextureImageUnits; + int maxFragmentUniformComponents; + int maxDrawBuffers; + int maxVertexUniformVectors; + int maxVaryingVectors; + int maxFragmentUniformVectors; + int maxVertexOutputVectors; + int maxFragmentInputVectors; + int minProgramTexelOffset; + int maxProgramTexelOffset; + int maxClipDistances; + int maxComputeWorkGroupCountX; + int maxComputeWorkGroupCountY; + int maxComputeWorkGroupCountZ; + int maxComputeWorkGroupSizeX; + int maxComputeWorkGroupSizeY; + int maxComputeWorkGroupSizeZ; + int maxComputeUniformComponents; + int maxComputeTextureImageUnits; + int maxComputeImageUniforms; + int maxComputeAtomicCounters; + int maxComputeAtomicCounterBuffers; + int maxVaryingComponents; + int maxVertexOutputComponents; + int maxGeometryInputComponents; + int maxGeometryOutputComponents; + int maxFragmentInputComponents; + int maxImageUnits; + int maxCombinedImageUnitsAndFragmentOutputs; + int maxCombinedShaderOutputResources; + int maxImageSamples; + int maxVertexImageUniforms; + int maxTessControlImageUniforms; + int maxTessEvaluationImageUniforms; + int maxGeometryImageUniforms; + int maxFragmentImageUniforms; + int maxCombinedImageUniforms; + int maxGeometryTextureImageUnits; + int maxGeometryOutputVertices; + int maxGeometryTotalOutputComponents; + int maxGeometryUniformComponents; + int maxGeometryVaryingComponents; + int maxTessControlInputComponents; + int maxTessControlOutputComponents; + int maxTessControlTextureImageUnits; + int maxTessControlUniformComponents; + int maxTessControlTotalOutputComponents; + int maxTessEvaluationInputComponents; + int maxTessEvaluationOutputComponents; + int maxTessEvaluationTextureImageUnits; + int maxTessEvaluationUniformComponents; + int maxTessPatchComponents; + int maxPatchVertices; + int maxTessGenLevel; + int maxViewports; + int maxVertexAtomicCounters; + int maxTessControlAtomicCounters; + int maxTessEvaluationAtomicCounters; + int maxGeometryAtomicCounters; + int maxFragmentAtomicCounters; + int maxCombinedAtomicCounters; + int maxAtomicCounterBindings; + int maxVertexAtomicCounterBuffers; + int maxTessControlAtomicCounterBuffers; + int maxTessEvaluationAtomicCounterBuffers; + int maxGeometryAtomicCounterBuffers; + int maxFragmentAtomicCounterBuffers; + int maxCombinedAtomicCounterBuffers; + int maxAtomicCounterBufferSize; + int maxTransformFeedbackBuffers; + int maxTransformFeedbackInterleavedComponents; + int maxCullDistances; + int maxCombinedClipAndCullDistances; + int maxSamples; + int maxMeshOutputVerticesNV; + int maxMeshOutputPrimitivesNV; + int maxMeshWorkGroupSizeX_NV; + int maxMeshWorkGroupSizeY_NV; + int maxMeshWorkGroupSizeZ_NV; + int maxTaskWorkGroupSizeX_NV; + int maxTaskWorkGroupSizeY_NV; + int maxTaskWorkGroupSizeZ_NV; + int maxMeshViewCountNV; + + TLimits limits; +}; + +#endif // _RESOURCE_LIMITS_INCLUDED_ diff --git a/android/x86/include/glslang/Include/ShHandle.h b/android/x86/include/glslang/Include/ShHandle.h new file mode 100644 index 00000000..df07bd8e --- /dev/null +++ b/android/x86/include/glslang/Include/ShHandle.h @@ -0,0 +1,176 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _SHHANDLE_INCLUDED_ +#define _SHHANDLE_INCLUDED_ + +// +// Machine independent part of the compiler private objects +// sent as ShHandle to the driver. +// +// This should not be included by driver code. +// + +#define SH_EXPORTING +#include "../Public/ShaderLang.h" +#include "../MachineIndependent/Versions.h" +#include "InfoSink.h" + +class TCompiler; +class TLinker; +class TUniformMap; + +// +// The base class used to back handles returned to the driver. +// +class TShHandleBase { +public: + TShHandleBase() { pool = new glslang::TPoolAllocator; } + virtual ~TShHandleBase() { delete pool; } + virtual TCompiler* getAsCompiler() { return 0; } + virtual TLinker* getAsLinker() { return 0; } + virtual TUniformMap* getAsUniformMap() { return 0; } + virtual glslang::TPoolAllocator* getPool() const { return pool; } +private: + glslang::TPoolAllocator* pool; +}; + +// +// The base class for the machine dependent linker to derive from +// for managing where uniforms live. +// +class TUniformMap : public TShHandleBase { +public: + TUniformMap() { } + virtual ~TUniformMap() { } + virtual TUniformMap* getAsUniformMap() { return this; } + virtual int getLocation(const char* name) = 0; + virtual TInfoSink& getInfoSink() { return infoSink; } + TInfoSink infoSink; +}; + +class TIntermNode; + +// +// The base class for the machine dependent compiler to derive from +// for managing object code from the compile. +// +class TCompiler : public TShHandleBase { +public: + TCompiler(EShLanguage l, TInfoSink& sink) : infoSink(sink) , language(l), haveValidObjectCode(false) { } + virtual ~TCompiler() { } + EShLanguage getLanguage() { return language; } + virtual TInfoSink& getInfoSink() { return infoSink; } + + virtual bool compile(TIntermNode* root, int version = 0, EProfile profile = ENoProfile) = 0; + + virtual TCompiler* getAsCompiler() { return this; } + virtual bool linkable() { return haveValidObjectCode; } + + TInfoSink& infoSink; +protected: + TCompiler& operator=(TCompiler&); + + EShLanguage language; + bool haveValidObjectCode; +}; + +// +// Link operations are based on a list of compile results... +// +typedef glslang::TVector TCompilerList; +typedef glslang::TVector THandleList; + +// +// The base class for the machine dependent linker to derive from +// to manage the resulting executable. +// + +class TLinker : public TShHandleBase { +public: + TLinker(EShExecutable e, TInfoSink& iSink) : + infoSink(iSink), + executable(e), + haveReturnableObjectCode(false), + appAttributeBindings(0), + fixedAttributeBindings(0), + excludedAttributes(0), + excludedCount(0), + uniformBindings(0) { } + virtual TLinker* getAsLinker() { return this; } + virtual ~TLinker() { } + virtual bool link(TCompilerList&, TUniformMap*) = 0; + virtual bool link(THandleList&) { return false; } + virtual void setAppAttributeBindings(const ShBindingTable* t) { appAttributeBindings = t; } + virtual void setFixedAttributeBindings(const ShBindingTable* t) { fixedAttributeBindings = t; } + virtual void getAttributeBindings(ShBindingTable const **t) const = 0; + virtual void setExcludedAttributes(const int* attributes, int count) { excludedAttributes = attributes; excludedCount = count; } + virtual ShBindingTable* getUniformBindings() const { return uniformBindings; } + virtual const void* getObjectCode() const { return 0; } // a real compiler would be returning object code here + virtual TInfoSink& getInfoSink() { return infoSink; } + TInfoSink& infoSink; +protected: + TLinker& operator=(TLinker&); + EShExecutable executable; + bool haveReturnableObjectCode; // true when objectCode is acceptable to send to driver + + const ShBindingTable* appAttributeBindings; + const ShBindingTable* fixedAttributeBindings; + const int* excludedAttributes; + int excludedCount; + ShBindingTable* uniformBindings; // created by the linker +}; + +// +// This is the interface between the machine independent code +// and the machine dependent code. +// +// The machine dependent code should derive from the classes +// above. Then Construct*() and Delete*() will create and +// destroy the machine dependent objects, which contain the +// above machine independent information. +// +TCompiler* ConstructCompiler(EShLanguage, int); + +TShHandleBase* ConstructLinker(EShExecutable, int); +TShHandleBase* ConstructBindings(); +void DeleteLinker(TShHandleBase*); +void DeleteBindingList(TShHandleBase* bindingList); + +TUniformMap* ConstructUniformMap(); +void DeleteCompiler(TCompiler*); + +void DeleteUniformMap(TUniformMap*); + +#endif // _SHHANDLE_INCLUDED_ diff --git a/android/x86/include/glslang/Include/Types.h b/android/x86/include/glslang/Include/Types.h new file mode 100644 index 00000000..b2c416d1 --- /dev/null +++ b/android/x86/include/glslang/Include/Types.h @@ -0,0 +1,2483 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2016 LunarG, Inc. +// Copyright (C) 2015-2016 Google, Inc. +// Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _TYPES_INCLUDED +#define _TYPES_INCLUDED + +#include "../Include/Common.h" +#include "../Include/BaseTypes.h" +#include "../Public/ShaderLang.h" +#include "arrays.h" + +#include + +namespace glslang { + +const int GlslangMaxTypeLength = 200; // TODO: need to print block/struct one member per line, so this can stay bounded + +const char* const AnonymousPrefix = "anon@"; // for something like a block whose members can be directly accessed +inline bool IsAnonymous(const TString& name) +{ + return name.compare(0, 5, AnonymousPrefix) == 0; +} + +// +// Details within a sampler type +// +enum TSamplerDim { + EsdNone, + Esd1D, + Esd2D, + Esd3D, + EsdCube, + EsdRect, + EsdBuffer, + EsdSubpass, // goes only with non-sampled image (image is true) + EsdNumDims +}; + +struct TSampler { // misnomer now; includes images, textures without sampler, and textures with sampler + TBasicType type : 8; // type returned by sampler + TSamplerDim dim : 8; + bool arrayed : 1; + bool shadow : 1; + bool ms : 1; + bool image : 1; // image, combined should be false + bool combined : 1; // true means texture is combined with a sampler, false means texture with no sampler + bool sampler : 1; // true means a pure sampler, other fields should be clear() + +#ifdef GLSLANG_WEB + bool is1D() const { return false; } + bool isBuffer() const { return false; } + bool isRect() const { return false; } + bool isSubpass() const { return false; } + bool isCombined() const { return true; } + bool isImage() const { return false; } + bool isImageClass() const { return false; } + bool isMultiSample() const { return false; } + bool isExternal() const { return false; } + void setExternal(bool e) { } + bool isYuv() const { return false; } +#else + unsigned int vectorSize : 3; // vector return type size. + // Some languages support structures as sample results. Storing the whole structure in the + // TSampler is too large, so there is an index to a separate table. + static const unsigned structReturnIndexBits = 4; // number of index bits to use. + static const unsigned structReturnSlots = (1< TTypeList; + +typedef TVector TIdentifierList; + +// +// Following are a series of helper enums for managing layouts and qualifiers, +// used for TPublicType, TType, others. +// + +enum TLayoutPacking { + ElpNone, + ElpShared, // default, but different than saying nothing + ElpStd140, + ElpStd430, + ElpPacked, + ElpScalar, + ElpCount // If expanding, see bitfield width below +}; + +enum TLayoutMatrix { + ElmNone, + ElmRowMajor, + ElmColumnMajor, // default, but different than saying nothing + ElmCount // If expanding, see bitfield width below +}; + +// Union of geometry shader and tessellation shader geometry types. +// They don't go into TType, but rather have current state per shader or +// active parser type (TPublicType). +enum TLayoutGeometry { + ElgNone, + ElgPoints, + ElgLines, + ElgLinesAdjacency, + ElgLineStrip, + ElgTriangles, + ElgTrianglesAdjacency, + ElgTriangleStrip, + ElgQuads, + ElgIsolines, +}; + +enum TVertexSpacing { + EvsNone, + EvsEqual, + EvsFractionalEven, + EvsFractionalOdd +}; + +enum TVertexOrder { + EvoNone, + EvoCw, + EvoCcw +}; + +// Note: order matters, as type of format is done by comparison. +enum TLayoutFormat { + ElfNone, + + // Float image + ElfRgba32f, + ElfRgba16f, + ElfR32f, + ElfRgba8, + ElfRgba8Snorm, + + ElfEsFloatGuard, // to help with comparisons + + ElfRg32f, + ElfRg16f, + ElfR11fG11fB10f, + ElfR16f, + ElfRgba16, + ElfRgb10A2, + ElfRg16, + ElfRg8, + ElfR16, + ElfR8, + ElfRgba16Snorm, + ElfRg16Snorm, + ElfRg8Snorm, + ElfR16Snorm, + ElfR8Snorm, + + ElfFloatGuard, // to help with comparisons + + // Int image + ElfRgba32i, + ElfRgba16i, + ElfRgba8i, + ElfR32i, + + ElfEsIntGuard, // to help with comparisons + + ElfRg32i, + ElfRg16i, + ElfRg8i, + ElfR16i, + ElfR8i, + + ElfIntGuard, // to help with comparisons + + // Uint image + ElfRgba32ui, + ElfRgba16ui, + ElfRgba8ui, + ElfR32ui, + + ElfEsUintGuard, // to help with comparisons + + ElfRg32ui, + ElfRg16ui, + ElfRgb10a2ui, + ElfRg8ui, + ElfR16ui, + ElfR8ui, + + ElfCount +}; + +enum TLayoutDepth { + EldNone, + EldAny, + EldGreater, + EldLess, + EldUnchanged, + + EldCount +}; + +enum TBlendEquationShift { + // No 'EBlendNone': + // These are used as bit-shift amounts. A mask of such shifts will have type 'int', + // and in that space, 0 means no bits set, or none. In this enum, 0 means (1 << 0), a bit is set. + EBlendMultiply, + EBlendScreen, + EBlendOverlay, + EBlendDarken, + EBlendLighten, + EBlendColordodge, + EBlendColorburn, + EBlendHardlight, + EBlendSoftlight, + EBlendDifference, + EBlendExclusion, + EBlendHslHue, + EBlendHslSaturation, + EBlendHslColor, + EBlendHslLuminosity, + EBlendAllEquations, + + EBlendCount +}; + +enum TInterlockOrdering { + EioNone, + EioPixelInterlockOrdered, + EioPixelInterlockUnordered, + EioSampleInterlockOrdered, + EioSampleInterlockUnordered, + EioShadingRateInterlockOrdered, + EioShadingRateInterlockUnordered, + + EioCount, +}; + +enum TShaderInterface +{ + // Includes both uniform blocks and buffer blocks + EsiUniform = 0, + EsiInput, + EsiOutput, + EsiNone, + + EsiCount +}; + + +class TQualifier { +public: + static const int layoutNotSet = -1; + + void clear() + { + precision = EpqNone; + invariant = false; + makeTemporary(); + declaredBuiltIn = EbvNone; +#ifndef GLSLANG_WEB + noContraction = false; +#endif + } + + // drop qualifiers that don't belong in a temporary variable + void makeTemporary() + { + semanticName = nullptr; + storage = EvqTemporary; + builtIn = EbvNone; + clearInterstage(); + clearMemory(); + specConstant = false; + nonUniform = false; + clearLayout(); + } + + void clearInterstage() + { + clearInterpolation(); +#ifndef GLSLANG_WEB + patch = false; + sample = false; +#endif + } + + void clearInterpolation() + { + centroid = false; + smooth = false; + flat = false; +#ifndef GLSLANG_WEB + nopersp = false; + explicitInterp = false; + pervertexNV = false; + perPrimitiveNV = false; + perViewNV = false; + perTaskNV = false; +#endif + } + + void clearMemory() + { +#ifndef GLSLANG_WEB + coherent = false; + devicecoherent = false; + queuefamilycoherent = false; + workgroupcoherent = false; + subgroupcoherent = false; + shadercallcoherent = false; + nonprivate = false; + volatil = false; + restrict = false; + readonly = false; + writeonly = false; +#endif + } + + const char* semanticName; + TStorageQualifier storage : 6; + TBuiltInVariable builtIn : 9; + TBuiltInVariable declaredBuiltIn : 9; + static_assert(EbvLast < 256, "need to increase size of TBuiltInVariable bitfields!"); + TPrecisionQualifier precision : 3; + bool invariant : 1; // require canonical treatment for cross-shader invariance + bool centroid : 1; + bool smooth : 1; + bool flat : 1; + // having a constant_id is not sufficient: expressions have no id, but are still specConstant + bool specConstant : 1; + bool nonUniform : 1; + bool explicitOffset : 1; + +#ifdef GLSLANG_WEB + bool isWriteOnly() const { return false; } + bool isReadOnly() const { return false; } + bool isRestrict() const { return false; } + bool isCoherent() const { return false; } + bool isVolatile() const { return false; } + bool isSample() const { return false; } + bool isMemory() const { return false; } + bool isMemoryQualifierImageAndSSBOOnly() const { return false; } + bool bufferReferenceNeedsVulkanMemoryModel() const { return false; } + bool isInterpolation() const { return flat || smooth; } + bool isExplicitInterpolation() const { return false; } + bool isAuxiliary() const { return centroid; } + bool isPatch() const { return false; } + bool isNoContraction() const { return false; } + void setNoContraction() { } + bool isPervertexNV() const { return false; } +#else + bool noContraction: 1; // prevent contraction and reassociation, e.g., for 'precise' keyword, and expressions it affects + bool nopersp : 1; + bool explicitInterp : 1; + bool pervertexNV : 1; + bool perPrimitiveNV : 1; + bool perViewNV : 1; + bool perTaskNV : 1; + bool patch : 1; + bool sample : 1; + bool restrict : 1; + bool readonly : 1; + bool writeonly : 1; + bool coherent : 1; + bool volatil : 1; + bool devicecoherent : 1; + bool queuefamilycoherent : 1; + bool workgroupcoherent : 1; + bool subgroupcoherent : 1; + bool shadercallcoherent : 1; + bool nonprivate : 1; + bool isWriteOnly() const { return writeonly; } + bool isReadOnly() const { return readonly; } + bool isRestrict() const { return restrict; } + bool isCoherent() const { return coherent; } + bool isVolatile() const { return volatil; } + bool isSample() const { return sample; } + bool isMemory() const + { + return shadercallcoherent || subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly || nonprivate; + } + bool isMemoryQualifierImageAndSSBOOnly() const + { + return shadercallcoherent || subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly; + } + bool bufferReferenceNeedsVulkanMemoryModel() const + { + // include qualifiers that map to load/store availability/visibility/nonprivate memory access operands + return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || nonprivate; + } + bool isInterpolation() const + { + return flat || smooth || nopersp || explicitInterp; + } + bool isExplicitInterpolation() const + { + return explicitInterp; + } + bool isAuxiliary() const + { + return centroid || patch || sample || pervertexNV; + } + bool isPatch() const { return patch; } + bool isNoContraction() const { return noContraction; } + void setNoContraction() { noContraction = true; } + bool isPervertexNV() const { return pervertexNV; } +#endif + + bool isPipeInput() const + { + switch (storage) { + case EvqVaryingIn: + case EvqFragCoord: + case EvqPointCoord: + case EvqFace: + case EvqVertexId: + case EvqInstanceId: + return true; + default: + return false; + } + } + + bool isPipeOutput() const + { + switch (storage) { + case EvqPosition: + case EvqPointSize: + case EvqClipVertex: + case EvqVaryingOut: + case EvqFragColor: + case EvqFragDepth: + return true; + default: + return false; + } + } + + bool isParamInput() const + { + switch (storage) { + case EvqIn: + case EvqInOut: + case EvqConstReadOnly: + return true; + default: + return false; + } + } + + bool isParamOutput() const + { + switch (storage) { + case EvqOut: + case EvqInOut: + return true; + default: + return false; + } + } + + bool isUniformOrBuffer() const + { + switch (storage) { + case EvqUniform: + case EvqBuffer: + return true; + default: + return false; + } + } + + bool isIo() const + { + switch (storage) { + case EvqUniform: + case EvqBuffer: + case EvqVaryingIn: + case EvqFragCoord: + case EvqPointCoord: + case EvqFace: + case EvqVertexId: + case EvqInstanceId: + case EvqPosition: + case EvqPointSize: + case EvqClipVertex: + case EvqVaryingOut: + case EvqFragColor: + case EvqFragDepth: + return true; + default: + return false; + } + } + + // non-built-in symbols that might link between compilation units + bool isLinkable() const + { + switch (storage) { + case EvqGlobal: + case EvqVaryingIn: + case EvqVaryingOut: + case EvqUniform: + case EvqBuffer: + case EvqShared: + return true; + default: + return false; + } + } + +#ifdef GLSLANG_WEB + bool isPerView() const { return false; } + bool isTaskMemory() const { return false; } + bool isArrayedIo(EShLanguage language) const { return false; } +#else + bool isPerPrimitive() const { return perPrimitiveNV; } + bool isPerView() const { return perViewNV; } + bool isTaskMemory() const { return perTaskNV; } + + // True if this type of IO is supposed to be arrayed with extra level for per-vertex data + bool isArrayedIo(EShLanguage language) const + { + switch (language) { + case EShLangGeometry: + return isPipeInput(); + case EShLangTessControl: + return ! patch && (isPipeInput() || isPipeOutput()); + case EShLangTessEvaluation: + return ! patch && isPipeInput(); + case EShLangFragment: + return pervertexNV && isPipeInput(); + case EShLangMeshNV: + return ! perTaskNV && isPipeOutput(); + + default: + return false; + } + } +#endif + + // Implementing an embedded layout-qualifier class here, since C++ can't have a real class bitfield + void clearLayout() // all layout + { + clearUniformLayout(); + +#ifndef GLSLANG_WEB + layoutPushConstant = false; + layoutBufferReference = false; + layoutPassthrough = false; + layoutViewportRelative = false; + // -2048 as the default value indicating layoutSecondaryViewportRelative is not set + layoutSecondaryViewportRelativeOffset = -2048; + layoutShaderRecord = false; + layoutBufferReferenceAlign = layoutBufferReferenceAlignEnd; + layoutFormat = ElfNone; +#endif + + clearInterstageLayout(); + + layoutSpecConstantId = layoutSpecConstantIdEnd; + } + void clearInterstageLayout() + { + layoutLocation = layoutLocationEnd; + layoutComponent = layoutComponentEnd; +#ifndef GLSLANG_WEB + layoutIndex = layoutIndexEnd; + clearStreamLayout(); + clearXfbLayout(); +#endif + } + +#ifndef GLSLANG_WEB + void clearStreamLayout() + { + layoutStream = layoutStreamEnd; + } + void clearXfbLayout() + { + layoutXfbBuffer = layoutXfbBufferEnd; + layoutXfbStride = layoutXfbStrideEnd; + layoutXfbOffset = layoutXfbOffsetEnd; + } +#endif + + bool hasNonXfbLayout() const + { + return hasUniformLayout() || + hasAnyLocation() || + hasStream() || + hasFormat() || + isShaderRecord() || + isPushConstant() || + hasBufferReference(); + } + bool hasLayout() const + { + return hasNonXfbLayout() || + hasXfb(); + } + TLayoutMatrix layoutMatrix : 3; + TLayoutPacking layoutPacking : 4; + int layoutOffset; + int layoutAlign; + + unsigned int layoutLocation : 12; + static const unsigned int layoutLocationEnd = 0xFFF; + + unsigned int layoutComponent : 3; + static const unsigned int layoutComponentEnd = 4; + + unsigned int layoutSet : 7; + static const unsigned int layoutSetEnd = 0x3F; + + unsigned int layoutBinding : 16; + static const unsigned int layoutBindingEnd = 0xFFFF; + + unsigned int layoutIndex : 8; + static const unsigned int layoutIndexEnd = 0xFF; + + unsigned int layoutStream : 8; + static const unsigned int layoutStreamEnd = 0xFF; + + unsigned int layoutXfbBuffer : 4; + static const unsigned int layoutXfbBufferEnd = 0xF; + + unsigned int layoutXfbStride : 14; + static const unsigned int layoutXfbStrideEnd = 0x3FFF; + + unsigned int layoutXfbOffset : 13; + static const unsigned int layoutXfbOffsetEnd = 0x1FFF; + + unsigned int layoutAttachment : 8; // for input_attachment_index + static const unsigned int layoutAttachmentEnd = 0XFF; + + unsigned int layoutSpecConstantId : 11; + static const unsigned int layoutSpecConstantIdEnd = 0x7FF; + +#ifndef GLSLANG_WEB + // stored as log2 of the actual alignment value + unsigned int layoutBufferReferenceAlign : 6; + static const unsigned int layoutBufferReferenceAlignEnd = 0x3F; + + TLayoutFormat layoutFormat : 8; + + bool layoutPushConstant; + bool layoutBufferReference; + bool layoutPassthrough; + bool layoutViewportRelative; + int layoutSecondaryViewportRelativeOffset; + bool layoutShaderRecord; +#endif + + bool hasUniformLayout() const + { + return hasMatrix() || + hasPacking() || + hasOffset() || + hasBinding() || + hasSet() || + hasAlign(); + } + void clearUniformLayout() // only uniform specific + { + layoutMatrix = ElmNone; + layoutPacking = ElpNone; + layoutOffset = layoutNotSet; + layoutAlign = layoutNotSet; + + layoutSet = layoutSetEnd; + layoutBinding = layoutBindingEnd; +#ifndef GLSLANG_WEB + layoutAttachment = layoutAttachmentEnd; +#endif + } + + bool hasMatrix() const + { + return layoutMatrix != ElmNone; + } + bool hasPacking() const + { + return layoutPacking != ElpNone; + } + bool hasAlign() const + { + return layoutAlign != layoutNotSet; + } + bool hasAnyLocation() const + { + return hasLocation() || + hasComponent() || + hasIndex(); + } + bool hasLocation() const + { + return layoutLocation != layoutLocationEnd; + } + bool hasSet() const + { + return layoutSet != layoutSetEnd; + } + bool hasBinding() const + { + return layoutBinding != layoutBindingEnd; + } +#ifdef GLSLANG_WEB + bool hasOffset() const { return false; } + bool isNonPerspective() const { return false; } + bool hasIndex() const { return false; } + unsigned getIndex() const { return 0; } + bool hasComponent() const { return false; } + bool hasStream() const { return false; } + bool hasFormat() const { return false; } + bool hasXfb() const { return false; } + bool hasXfbBuffer() const { return false; } + bool hasXfbStride() const { return false; } + bool hasXfbOffset() const { return false; } + bool hasAttachment() const { return false; } + TLayoutFormat getFormat() const { return ElfNone; } + bool isPushConstant() const { return false; } + bool isShaderRecord() const { return false; } + bool hasBufferReference() const { return false; } + bool hasBufferReferenceAlign() const { return false; } + bool isNonUniform() const { return false; } +#else + bool hasOffset() const + { + return layoutOffset != layoutNotSet; + } + bool isNonPerspective() const { return nopersp; } + bool hasIndex() const + { + return layoutIndex != layoutIndexEnd; + } + unsigned getIndex() const { return layoutIndex; } + bool hasComponent() const + { + return layoutComponent != layoutComponentEnd; + } + bool hasStream() const + { + return layoutStream != layoutStreamEnd; + } + bool hasFormat() const + { + return layoutFormat != ElfNone; + } + bool hasXfb() const + { + return hasXfbBuffer() || + hasXfbStride() || + hasXfbOffset(); + } + bool hasXfbBuffer() const + { + return layoutXfbBuffer != layoutXfbBufferEnd; + } + bool hasXfbStride() const + { + return layoutXfbStride != layoutXfbStrideEnd; + } + bool hasXfbOffset() const + { + return layoutXfbOffset != layoutXfbOffsetEnd; + } + bool hasAttachment() const + { + return layoutAttachment != layoutAttachmentEnd; + } + TLayoutFormat getFormat() const { return layoutFormat; } + bool isPushConstant() const { return layoutPushConstant; } + bool isShaderRecord() const { return layoutShaderRecord; } + bool hasBufferReference() const { return layoutBufferReference; } + bool hasBufferReferenceAlign() const + { + return layoutBufferReferenceAlign != layoutBufferReferenceAlignEnd; + } + bool isNonUniform() const + { + return nonUniform; + } +#endif + bool hasSpecConstantId() const + { + // Not the same thing as being a specialization constant, this + // is just whether or not it was declared with an ID. + return layoutSpecConstantId != layoutSpecConstantIdEnd; + } + bool isSpecConstant() const + { + // True if type is a specialization constant, whether or not it + // had a specialization-constant ID, and false if it is not a + // true front-end constant. + return specConstant; + } + bool isFrontEndConstant() const + { + // True if the front-end knows the final constant value. + // This allows front-end constant folding. + return storage == EvqConst && ! specConstant; + } + bool isConstant() const + { + // True if is either kind of constant; specialization or regular. + return isFrontEndConstant() || isSpecConstant(); + } + void makeSpecConstant() + { + storage = EvqConst; + specConstant = true; + } + static const char* getLayoutPackingString(TLayoutPacking packing) + { + switch (packing) { + case ElpStd140: return "std140"; +#ifndef GLSLANG_WEB + case ElpPacked: return "packed"; + case ElpShared: return "shared"; + case ElpStd430: return "std430"; + case ElpScalar: return "scalar"; +#endif + default: return "none"; + } + } + static const char* getLayoutMatrixString(TLayoutMatrix m) + { + switch (m) { + case ElmColumnMajor: return "column_major"; + case ElmRowMajor: return "row_major"; + default: return "none"; + } + } +#ifdef GLSLANG_WEB + static const char* getLayoutFormatString(TLayoutFormat f) { return "none"; } +#else + static const char* getLayoutFormatString(TLayoutFormat f) + { + switch (f) { + case ElfRgba32f: return "rgba32f"; + case ElfRgba16f: return "rgba16f"; + case ElfRg32f: return "rg32f"; + case ElfRg16f: return "rg16f"; + case ElfR11fG11fB10f: return "r11f_g11f_b10f"; + case ElfR32f: return "r32f"; + case ElfR16f: return "r16f"; + case ElfRgba16: return "rgba16"; + case ElfRgb10A2: return "rgb10_a2"; + case ElfRgba8: return "rgba8"; + case ElfRg16: return "rg16"; + case ElfRg8: return "rg8"; + case ElfR16: return "r16"; + case ElfR8: return "r8"; + case ElfRgba16Snorm: return "rgba16_snorm"; + case ElfRgba8Snorm: return "rgba8_snorm"; + case ElfRg16Snorm: return "rg16_snorm"; + case ElfRg8Snorm: return "rg8_snorm"; + case ElfR16Snorm: return "r16_snorm"; + case ElfR8Snorm: return "r8_snorm"; + + case ElfRgba32i: return "rgba32i"; + case ElfRgba16i: return "rgba16i"; + case ElfRgba8i: return "rgba8i"; + case ElfRg32i: return "rg32i"; + case ElfRg16i: return "rg16i"; + case ElfRg8i: return "rg8i"; + case ElfR32i: return "r32i"; + case ElfR16i: return "r16i"; + case ElfR8i: return "r8i"; + + case ElfRgba32ui: return "rgba32ui"; + case ElfRgba16ui: return "rgba16ui"; + case ElfRgba8ui: return "rgba8ui"; + case ElfRg32ui: return "rg32ui"; + case ElfRg16ui: return "rg16ui"; + case ElfRgb10a2ui: return "rgb10_a2ui"; + case ElfRg8ui: return "rg8ui"; + case ElfR32ui: return "r32ui"; + case ElfR16ui: return "r16ui"; + case ElfR8ui: return "r8ui"; + default: return "none"; + } + } + static const char* getLayoutDepthString(TLayoutDepth d) + { + switch (d) { + case EldAny: return "depth_any"; + case EldGreater: return "depth_greater"; + case EldLess: return "depth_less"; + case EldUnchanged: return "depth_unchanged"; + default: return "none"; + } + } + static const char* getBlendEquationString(TBlendEquationShift e) + { + switch (e) { + case EBlendMultiply: return "blend_support_multiply"; + case EBlendScreen: return "blend_support_screen"; + case EBlendOverlay: return "blend_support_overlay"; + case EBlendDarken: return "blend_support_darken"; + case EBlendLighten: return "blend_support_lighten"; + case EBlendColordodge: return "blend_support_colordodge"; + case EBlendColorburn: return "blend_support_colorburn"; + case EBlendHardlight: return "blend_support_hardlight"; + case EBlendSoftlight: return "blend_support_softlight"; + case EBlendDifference: return "blend_support_difference"; + case EBlendExclusion: return "blend_support_exclusion"; + case EBlendHslHue: return "blend_support_hsl_hue"; + case EBlendHslSaturation: return "blend_support_hsl_saturation"; + case EBlendHslColor: return "blend_support_hsl_color"; + case EBlendHslLuminosity: return "blend_support_hsl_luminosity"; + case EBlendAllEquations: return "blend_support_all_equations"; + default: return "unknown"; + } + } + static const char* getGeometryString(TLayoutGeometry geometry) + { + switch (geometry) { + case ElgPoints: return "points"; + case ElgLines: return "lines"; + case ElgLinesAdjacency: return "lines_adjacency"; + case ElgLineStrip: return "line_strip"; + case ElgTriangles: return "triangles"; + case ElgTrianglesAdjacency: return "triangles_adjacency"; + case ElgTriangleStrip: return "triangle_strip"; + case ElgQuads: return "quads"; + case ElgIsolines: return "isolines"; + default: return "none"; + } + } + static const char* getVertexSpacingString(TVertexSpacing spacing) + { + switch (spacing) { + case EvsEqual: return "equal_spacing"; + case EvsFractionalEven: return "fractional_even_spacing"; + case EvsFractionalOdd: return "fractional_odd_spacing"; + default: return "none"; + } + } + static const char* getVertexOrderString(TVertexOrder order) + { + switch (order) { + case EvoCw: return "cw"; + case EvoCcw: return "ccw"; + default: return "none"; + } + } + static int mapGeometryToSize(TLayoutGeometry geometry) + { + switch (geometry) { + case ElgPoints: return 1; + case ElgLines: return 2; + case ElgLinesAdjacency: return 4; + case ElgTriangles: return 3; + case ElgTrianglesAdjacency: return 6; + default: return 0; + } + } + static const char* getInterlockOrderingString(TInterlockOrdering order) + { + switch (order) { + case EioPixelInterlockOrdered: return "pixel_interlock_ordered"; + case EioPixelInterlockUnordered: return "pixel_interlock_unordered"; + case EioSampleInterlockOrdered: return "sample_interlock_ordered"; + case EioSampleInterlockUnordered: return "sample_interlock_unordered"; + case EioShadingRateInterlockOrdered: return "shading_rate_interlock_ordered"; + case EioShadingRateInterlockUnordered: return "shading_rate_interlock_unordered"; + default: return "none"; + } + } +#endif +}; + +// Qualifiers that don't need to be keep per object. They have shader scope, not object scope. +// So, they will not be part of TType, TQualifier, etc. +struct TShaderQualifiers { + TLayoutGeometry geometry; // geometry/tessellation shader in/out primitives + bool pixelCenterInteger; // fragment shader + bool originUpperLeft; // fragment shader + int invocations; + int vertices; // for tessellation "vertices", geometry & mesh "max_vertices" + TVertexSpacing spacing; + TVertexOrder order; + bool pointMode; + int localSize[3]; // compute shader + bool localSizeNotDefault[3]; // compute shader + int localSizeSpecId[3]; // compute shader specialization id for gl_WorkGroupSize +#ifndef GLSLANG_WEB + bool earlyFragmentTests; // fragment input + bool postDepthCoverage; // fragment input + TLayoutDepth layoutDepth; + bool blendEquation; // true if any blend equation was specified + int numViews; // multiview extenstions + TInterlockOrdering interlockOrdering; + bool layoutOverrideCoverage; // true if layout override_coverage set + bool layoutDerivativeGroupQuads; // true if layout derivative_group_quadsNV set + bool layoutDerivativeGroupLinear; // true if layout derivative_group_linearNV set + int primitives; // mesh shader "max_primitives"DerivativeGroupLinear; // true if layout derivative_group_linearNV set + TLayoutDepth getDepth() const { return layoutDepth; } +#else + TLayoutDepth getDepth() const { return EldNone; } +#endif + + void init() + { + geometry = ElgNone; + originUpperLeft = false; + pixelCenterInteger = false; + invocations = TQualifier::layoutNotSet; + vertices = TQualifier::layoutNotSet; + spacing = EvsNone; + order = EvoNone; + pointMode = false; + localSize[0] = 1; + localSize[1] = 1; + localSize[2] = 1; + localSizeNotDefault[0] = false; + localSizeNotDefault[1] = false; + localSizeNotDefault[2] = false; + localSizeSpecId[0] = TQualifier::layoutNotSet; + localSizeSpecId[1] = TQualifier::layoutNotSet; + localSizeSpecId[2] = TQualifier::layoutNotSet; +#ifndef GLSLANG_WEB + earlyFragmentTests = false; + postDepthCoverage = false; + layoutDepth = EldNone; + blendEquation = false; + numViews = TQualifier::layoutNotSet; + layoutOverrideCoverage = false; + layoutDerivativeGroupQuads = false; + layoutDerivativeGroupLinear = false; + primitives = TQualifier::layoutNotSet; + interlockOrdering = EioNone; +#endif + } + +#ifdef GLSLANG_WEB + bool hasBlendEquation() const { return false; } +#else + bool hasBlendEquation() const { return blendEquation; } +#endif + + // Merge in characteristics from the 'src' qualifier. They can override when + // set, but never erase when not set. + void merge(const TShaderQualifiers& src) + { + if (src.geometry != ElgNone) + geometry = src.geometry; + if (src.pixelCenterInteger) + pixelCenterInteger = src.pixelCenterInteger; + if (src.originUpperLeft) + originUpperLeft = src.originUpperLeft; + if (src.invocations != TQualifier::layoutNotSet) + invocations = src.invocations; + if (src.vertices != TQualifier::layoutNotSet) + vertices = src.vertices; + if (src.spacing != EvsNone) + spacing = src.spacing; + if (src.order != EvoNone) + order = src.order; + if (src.pointMode) + pointMode = true; + for (int i = 0; i < 3; ++i) { + if (src.localSize[i] > 1) + localSize[i] = src.localSize[i]; + } + for (int i = 0; i < 3; ++i) { + localSizeNotDefault[i] = src.localSizeNotDefault[i] || localSizeNotDefault[i]; + } + for (int i = 0; i < 3; ++i) { + if (src.localSizeSpecId[i] != TQualifier::layoutNotSet) + localSizeSpecId[i] = src.localSizeSpecId[i]; + } +#ifndef GLSLANG_WEB + if (src.earlyFragmentTests) + earlyFragmentTests = true; + if (src.postDepthCoverage) + postDepthCoverage = true; + if (src.layoutDepth) + layoutDepth = src.layoutDepth; + if (src.blendEquation) + blendEquation = src.blendEquation; + if (src.numViews != TQualifier::layoutNotSet) + numViews = src.numViews; + if (src.layoutOverrideCoverage) + layoutOverrideCoverage = src.layoutOverrideCoverage; + if (src.layoutDerivativeGroupQuads) + layoutDerivativeGroupQuads = src.layoutDerivativeGroupQuads; + if (src.layoutDerivativeGroupLinear) + layoutDerivativeGroupLinear = src.layoutDerivativeGroupLinear; + if (src.primitives != TQualifier::layoutNotSet) + primitives = src.primitives; + if (src.interlockOrdering != EioNone) + interlockOrdering = src.interlockOrdering; +#endif + } +}; + +// +// TPublicType is just temporarily used while parsing and not quite the same +// information kept per node in TType. Due to the bison stack, it can't have +// types that it thinks have non-trivial constructors. It should +// just be used while recognizing the grammar, not anything else. +// Once enough is known about the situation, the proper information +// moved into a TType, or the parse context, etc. +// +class TPublicType { +public: + TBasicType basicType; + TSampler sampler; + TQualifier qualifier; + TShaderQualifiers shaderQualifiers; + int vectorSize : 4; + int matrixCols : 4; + int matrixRows : 4; + bool coopmat : 1; + TArraySizes* arraySizes; + const TType* userDef; + TSourceLoc loc; + TArraySizes* typeParameters; + +#ifdef GLSLANG_WEB + bool isCoopmat() const { return false; } +#else + bool isCoopmat() const { return coopmat; } +#endif + + void initType(const TSourceLoc& l) + { + basicType = EbtVoid; + vectorSize = 1; + matrixRows = 0; + matrixCols = 0; + arraySizes = nullptr; + userDef = nullptr; + loc = l; + typeParameters = nullptr; + coopmat = false; + } + + void initQualifiers(bool global = false) + { + qualifier.clear(); + if (global) + qualifier.storage = EvqGlobal; + } + + void init(const TSourceLoc& l, bool global = false) + { + initType(l); + sampler.clear(); + initQualifiers(global); + shaderQualifiers.init(); + } + + void setVector(int s) + { + matrixRows = 0; + matrixCols = 0; + vectorSize = s; + } + + void setMatrix(int c, int r) + { + matrixRows = r; + matrixCols = c; + vectorSize = 0; + } + + bool isScalar() const + { + return matrixCols == 0 && vectorSize == 1 && arraySizes == nullptr && userDef == nullptr; + } + + // "Image" is a superset of "Subpass" + bool isImage() const { return basicType == EbtSampler && sampler.isImage(); } + bool isSubpass() const { return basicType == EbtSampler && sampler.isSubpass(); } +}; + +// +// Base class for things that have a type. +// +class TType { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + // for "empty" type (no args) or simple scalar/vector/matrix + explicit TType(TBasicType t = EbtVoid, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0, + bool isVector = false) : + basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1), coopmat(false), + arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr) + { + sampler.clear(); + qualifier.clear(); + qualifier.storage = q; + assert(!(isMatrix() && vectorSize != 0)); // prevent vectorSize != 0 on matrices + } + // for explicit precision qualifier + TType(TBasicType t, TStorageQualifier q, TPrecisionQualifier p, int vs = 1, int mc = 0, int mr = 0, + bool isVector = false) : + basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1), coopmat(false), + arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr) + { + sampler.clear(); + qualifier.clear(); + qualifier.storage = q; + qualifier.precision = p; + assert(p >= EpqNone && p <= EpqHigh); + assert(!(isMatrix() && vectorSize != 0)); // prevent vectorSize != 0 on matrices + } + // for turning a TPublicType into a TType, using a shallow copy + explicit TType(const TPublicType& p) : + basicType(p.basicType), + vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), vector1(false), coopmat(p.coopmat), + arraySizes(p.arraySizes), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(p.typeParameters) + { + if (basicType == EbtSampler) + sampler = p.sampler; + else + sampler.clear(); + qualifier = p.qualifier; + if (p.userDef) { + if (p.userDef->basicType == EbtReference) { + basicType = EbtReference; + referentType = p.userDef->referentType; + } else { + structure = p.userDef->getWritableStruct(); // public type is short-lived; there are no sharing issues + } + typeName = NewPoolTString(p.userDef->getTypeName().c_str()); + } + if (p.isCoopmat() && p.typeParameters && p.typeParameters->getNumDims() > 0) { + int numBits = p.typeParameters->getDimSize(0); + if (p.basicType == EbtFloat && numBits == 16) { + basicType = EbtFloat16; + qualifier.precision = EpqNone; + } else if (p.basicType == EbtUint && numBits == 8) { + basicType = EbtUint8; + qualifier.precision = EpqNone; + } else if (p.basicType == EbtInt && numBits == 8) { + basicType = EbtInt8; + qualifier.precision = EpqNone; + } + } + } + // for construction of sampler types + TType(const TSampler& sampler, TStorageQualifier q = EvqUniform, TArraySizes* as = nullptr) : + basicType(EbtSampler), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false), + arraySizes(as), structure(nullptr), fieldName(nullptr), typeName(nullptr), + sampler(sampler), typeParameters(nullptr) + { + qualifier.clear(); + qualifier.storage = q; + } + // to efficiently make a dereferenced type + // without ever duplicating the outer structure that will be thrown away + // and using only shallow copy + TType(const TType& type, int derefIndex, bool rowMajor = false) + { + if (type.isArray()) { + shallowCopy(type); + if (type.getArraySizes()->getNumDims() == 1) { + arraySizes = nullptr; + } else { + // want our own copy of the array, so we can edit it + arraySizes = new TArraySizes; + arraySizes->copyDereferenced(*type.arraySizes); + } + } else if (type.basicType == EbtStruct || type.basicType == EbtBlock) { + // do a structure dereference + const TTypeList& memberList = *type.getStruct(); + shallowCopy(*memberList[derefIndex].type); + return; + } else { + // do a vector/matrix dereference + shallowCopy(type); + if (matrixCols > 0) { + // dereference from matrix to vector + if (rowMajor) + vectorSize = matrixCols; + else + vectorSize = matrixRows; + matrixCols = 0; + matrixRows = 0; + if (vectorSize == 1) + vector1 = true; + } else if (isVector()) { + // dereference from vector to scalar + vectorSize = 1; + vector1 = false; + } else if (isCoopMat()) { + coopmat = false; + typeParameters = nullptr; + } + } + } + // for making structures, ... + TType(TTypeList* userDef, const TString& n) : + basicType(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false), + arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr) + { + sampler.clear(); + qualifier.clear(); + typeName = NewPoolTString(n.c_str()); + } + // For interface blocks + TType(TTypeList* userDef, const TString& n, const TQualifier& q) : + basicType(EbtBlock), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false), + qualifier(q), arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr) + { + sampler.clear(); + typeName = NewPoolTString(n.c_str()); + } + // for block reference (first parameter must be EbtReference) + explicit TType(TBasicType t, const TType &p, const TString& n) : + basicType(t), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), + arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr) + { + assert(t == EbtReference); + typeName = NewPoolTString(n.c_str()); + qualifier.clear(); + qualifier.storage = p.qualifier.storage; + referentType = p.clone(); + } + virtual ~TType() {} + + // Not for use across pool pops; it will cause multiple instances of TType to point to the same information. + // This only works if that information (like a structure's list of types) does not change and + // the instances are sharing the same pool. + void shallowCopy(const TType& copyOf) + { + basicType = copyOf.basicType; + sampler = copyOf.sampler; + qualifier = copyOf.qualifier; + vectorSize = copyOf.vectorSize; + matrixCols = copyOf.matrixCols; + matrixRows = copyOf.matrixRows; + vector1 = copyOf.vector1; + arraySizes = copyOf.arraySizes; // copying the pointer only, not the contents + fieldName = copyOf.fieldName; + typeName = copyOf.typeName; + if (isStruct()) { + structure = copyOf.structure; + } else { + referentType = copyOf.referentType; + } + typeParameters = copyOf.typeParameters; + coopmat = copyOf.isCoopMat(); + } + + // Make complete copy of the whole type graph rooted at 'copyOf'. + void deepCopy(const TType& copyOf) + { + TMap copied; // to enable copying a type graph as a graph, not a tree + deepCopy(copyOf, copied); + } + + // Recursively make temporary + void makeTemporary() + { + getQualifier().makeTemporary(); + + if (isStruct()) + for (unsigned int i = 0; i < structure->size(); ++i) + (*structure)[i].type->makeTemporary(); + } + + TType* clone() const + { + TType *newType = new TType(); + newType->deepCopy(*this); + + return newType; + } + + void makeVector() { vector1 = true; } + + virtual void hideMember() { basicType = EbtVoid; vectorSize = 1; } + virtual bool hiddenMember() const { return basicType == EbtVoid; } + + virtual void setFieldName(const TString& n) { fieldName = NewPoolTString(n.c_str()); } + virtual const TString& getTypeName() const + { + assert(typeName); + return *typeName; + } + + virtual const TString& getFieldName() const + { + assert(fieldName); + return *fieldName; + } + TShaderInterface getShaderInterface() const + { + if (basicType != EbtBlock) + return EsiNone; + + switch (qualifier.storage) { + default: + return EsiNone; + case EvqVaryingIn: + return EsiInput; + case EvqVaryingOut: + return EsiOutput; + case EvqUniform: + case EvqBuffer: + return EsiUniform; + } + } + + virtual TBasicType getBasicType() const { return basicType; } + virtual const TSampler& getSampler() const { return sampler; } + virtual TSampler& getSampler() { return sampler; } + + virtual TQualifier& getQualifier() { return qualifier; } + virtual const TQualifier& getQualifier() const { return qualifier; } + + virtual int getVectorSize() const { return vectorSize; } // returns 1 for either scalar or vector of size 1, valid for both + virtual int getMatrixCols() const { return matrixCols; } + virtual int getMatrixRows() const { return matrixRows; } + virtual int getOuterArraySize() const { return arraySizes->getOuterSize(); } + virtual TIntermTyped* getOuterArrayNode() const { return arraySizes->getOuterNode(); } + virtual int getCumulativeArraySize() const { return arraySizes->getCumulativeSize(); } +#ifdef GLSLANG_WEB + bool isArrayOfArrays() const { return false; } +#else + bool isArrayOfArrays() const { return arraySizes != nullptr && arraySizes->getNumDims() > 1; } +#endif + virtual int getImplicitArraySize() const { return arraySizes->getImplicitSize(); } + virtual const TArraySizes* getArraySizes() const { return arraySizes; } + virtual TArraySizes* getArraySizes() { return arraySizes; } + virtual TType* getReferentType() const { return referentType; } + virtual const TArraySizes* getTypeParameters() const { return typeParameters; } + virtual TArraySizes* getTypeParameters() { return typeParameters; } + + virtual bool isScalar() const { return ! isVector() && ! isMatrix() && ! isStruct() && ! isArray(); } + virtual bool isScalarOrVec1() const { return isScalar() || vector1; } + virtual bool isVector() const { return vectorSize > 1 || vector1; } + virtual bool isMatrix() const { return matrixCols ? true : false; } + virtual bool isArray() const { return arraySizes != nullptr; } + virtual bool isSizedArray() const { return isArray() && arraySizes->isSized(); } + virtual bool isUnsizedArray() const { return isArray() && !arraySizes->isSized(); } + virtual bool isArrayVariablyIndexed() const { assert(isArray()); return arraySizes->isVariablyIndexed(); } + virtual void setArrayVariablyIndexed() { assert(isArray()); arraySizes->setVariablyIndexed(); } + virtual void updateImplicitArraySize(int size) { assert(isArray()); arraySizes->updateImplicitSize(size); } + virtual bool isStruct() const { return basicType == EbtStruct || basicType == EbtBlock; } + virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble || basicType == EbtFloat16; } + virtual bool isIntegerDomain() const + { + switch (basicType) { + case EbtInt8: + case EbtUint8: + case EbtInt16: + case EbtUint16: + case EbtInt: + case EbtUint: + case EbtInt64: + case EbtUint64: + case EbtAtomicUint: + return true; + default: + break; + } + return false; + } + virtual bool isOpaque() const { return basicType == EbtSampler +#ifndef GLSLANG_WEB + || basicType == EbtAtomicUint || basicType == EbtAccStruct || basicType == EbtRayQuery +#endif + ; } + virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; } + + // "Image" is a superset of "Subpass" + virtual bool isImage() const { return basicType == EbtSampler && getSampler().isImage(); } + virtual bool isSubpass() const { return basicType == EbtSampler && getSampler().isSubpass(); } + virtual bool isTexture() const { return basicType == EbtSampler && getSampler().isTexture(); } + // Check the block-name convention of creating a block without populating it's members: + virtual bool isUnusableName() const { return isStruct() && structure == nullptr; } + virtual bool isParameterized() const { return typeParameters != nullptr; } +#ifdef GLSLANG_WEB + bool isAtomic() const { return false; } + bool isCoopMat() const { return false; } + bool isReference() const { return false; } +#else + bool isAtomic() const { return basicType == EbtAtomicUint; } + bool isCoopMat() const { return coopmat; } + bool isReference() const { return getBasicType() == EbtReference; } +#endif + + // return true if this type contains any subtype which satisfies the given predicate. + template + bool contains(P predicate) const + { + if (predicate(this)) + return true; + + const auto hasa = [predicate](const TTypeLoc& tl) { return tl.type->contains(predicate); }; + + return isStruct() && std::any_of(structure->begin(), structure->end(), hasa); + } + + // Recursively checks if the type contains the given basic type + virtual bool containsBasicType(TBasicType checkType) const + { + return contains([checkType](const TType* t) { return t->basicType == checkType; } ); + } + + // Recursively check the structure for any arrays, needed for some error checks + virtual bool containsArray() const + { + return contains([](const TType* t) { return t->isArray(); } ); + } + + // Check the structure for any structures, needed for some error checks + virtual bool containsStructure() const + { + return contains([this](const TType* t) { return t != this && t->isStruct(); } ); + } + + // Recursively check the structure for any unsized arrays, needed for triggering a copyUp(). + virtual bool containsUnsizedArray() const + { + return contains([](const TType* t) { return t->isUnsizedArray(); } ); + } + + virtual bool containsOpaque() const + { + return contains([](const TType* t) { return t->isOpaque(); } ); + } + + // Recursively checks if the type contains a built-in variable + virtual bool containsBuiltIn() const + { + return contains([](const TType* t) { return t->isBuiltIn(); } ); + } + + virtual bool containsNonOpaque() const + { + const auto nonOpaque = [](const TType* t) { + switch (t->basicType) { + case EbtVoid: + case EbtFloat: + case EbtDouble: + case EbtFloat16: + case EbtInt8: + case EbtUint8: + case EbtInt16: + case EbtUint16: + case EbtInt: + case EbtUint: + case EbtInt64: + case EbtUint64: + case EbtBool: + case EbtReference: + return true; + default: + return false; + } + }; + + return contains(nonOpaque); + } + + virtual bool containsSpecializationSize() const + { + return contains([](const TType* t) { return t->isArray() && t->arraySizes->isOuterSpecialization(); } ); + } + +#ifdef GLSLANG_WEB + bool containsDouble() const { return false; } + bool contains16BitFloat() const { return false; } + bool contains64BitInt() const { return false; } + bool contains16BitInt() const { return false; } + bool contains8BitInt() const { return false; } + bool containsCoopMat() const { return false; } + bool containsReference() const { return false; } +#else + bool containsDouble() const + { + return containsBasicType(EbtDouble); + } + bool contains16BitFloat() const + { + return containsBasicType(EbtFloat16); + } + bool contains64BitInt() const + { + return containsBasicType(EbtInt64) || containsBasicType(EbtUint64); + } + bool contains16BitInt() const + { + return containsBasicType(EbtInt16) || containsBasicType(EbtUint16); + } + bool contains8BitInt() const + { + return containsBasicType(EbtInt8) || containsBasicType(EbtUint8); + } + bool containsCoopMat() const + { + return contains([](const TType* t) { return t->coopmat; } ); + } + bool containsReference() const + { + return containsBasicType(EbtReference); + } +#endif + + // Array editing methods. Array descriptors can be shared across + // type instances. This allows all uses of the same array + // to be updated at once. E.g., all nodes can be explicitly sized + // by tracking and correcting one implicit size. Or, all nodes + // can get the explicit size on a redeclaration that gives size. + // + // N.B.: Don't share with the shared symbol tables (symbols are + // marked as isReadOnly(). Such symbols with arrays that will be + // edited need to copyUp() on first use, so that + // A) the edits don't effect the shared symbol table, and + // B) the edits are shared across all users. + void updateArraySizes(const TType& type) + { + // For when we may already be sharing existing array descriptors, + // keeping the pointers the same, just updating the contents. + assert(arraySizes != nullptr); + assert(type.arraySizes != nullptr); + *arraySizes = *type.arraySizes; + } + void copyArraySizes(const TArraySizes& s) + { + // For setting a fresh new set of array sizes, not yet worrying about sharing. + arraySizes = new TArraySizes; + *arraySizes = s; + } + void transferArraySizes(TArraySizes* s) + { + // For setting an already allocated set of sizes that this type can use + // (no copy made). + arraySizes = s; + } + void clearArraySizes() + { + arraySizes = nullptr; + } + + // Add inner array sizes, to any existing sizes, via copy; the + // sizes passed in can still be reused for other purposes. + void copyArrayInnerSizes(const TArraySizes* s) + { + if (s != nullptr) { + if (arraySizes == nullptr) + copyArraySizes(*s); + else + arraySizes->addInnerSizes(*s); + } + } + void changeOuterArraySize(int s) { arraySizes->changeOuterSize(s); } + + // Recursively make the implicit array size the explicit array size. + // Expicit arrays are compile-time or link-time sized, never run-time sized. + // Sometimes, policy calls for an array to be run-time sized even if it was + // never variably indexed: Don't turn a 'skipNonvariablyIndexed' array into + // an explicit array. + void adoptImplicitArraySizes(bool skipNonvariablyIndexed) + { + if (isUnsizedArray() && !(skipNonvariablyIndexed || isArrayVariablyIndexed())) + changeOuterArraySize(getImplicitArraySize()); + // For multi-dim per-view arrays, set unsized inner dimension size to 1 + if (qualifier.isPerView() && arraySizes && arraySizes->isInnerUnsized()) + arraySizes->clearInnerUnsized(); + if (isStruct() && structure->size() > 0) { + int lastMember = (int)structure->size() - 1; + for (int i = 0; i < lastMember; ++i) + (*structure)[i].type->adoptImplicitArraySizes(false); + // implement the "last member of an SSBO" policy + (*structure)[lastMember].type->adoptImplicitArraySizes(getQualifier().storage == EvqBuffer); + } + } + + + void updateTypeParameters(const TType& type) + { + // For when we may already be sharing existing array descriptors, + // keeping the pointers the same, just updating the contents. + assert(typeParameters != nullptr); + assert(type.typeParameters != nullptr); + *typeParameters = *type.typeParameters; + } + void copyTypeParameters(const TArraySizes& s) + { + // For setting a fresh new set of type parameters, not yet worrying about sharing. + typeParameters = new TArraySizes; + *typeParameters = s; + } + void transferTypeParameters(TArraySizes* s) + { + // For setting an already allocated set of sizes that this type can use + // (no copy made). + typeParameters = s; + } + void clearTypeParameters() + { + typeParameters = nullptr; + } + + // Add inner array sizes, to any existing sizes, via copy; the + // sizes passed in can still be reused for other purposes. + void copyTypeParametersInnerSizes(const TArraySizes* s) + { + if (s != nullptr) { + if (typeParameters == nullptr) + copyTypeParameters(*s); + else + typeParameters->addInnerSizes(*s); + } + } + + + + const char* getBasicString() const + { + return TType::getBasicString(basicType); + } + + static const char* getBasicString(TBasicType t) + { + switch (t) { + case EbtFloat: return "float"; + case EbtInt: return "int"; + case EbtUint: return "uint"; + case EbtSampler: return "sampler/image"; +#ifndef GLSLANG_WEB + case EbtVoid: return "void"; + case EbtDouble: return "double"; + case EbtFloat16: return "float16_t"; + case EbtInt8: return "int8_t"; + case EbtUint8: return "uint8_t"; + case EbtInt16: return "int16_t"; + case EbtUint16: return "uint16_t"; + case EbtInt64: return "int64_t"; + case EbtUint64: return "uint64_t"; + case EbtBool: return "bool"; + case EbtAtomicUint: return "atomic_uint"; + case EbtStruct: return "structure"; + case EbtBlock: return "block"; + case EbtAccStruct: return "accelerationStructureNV"; + case EbtRayQuery: return "rayQueryEXT"; + case EbtReference: return "reference"; +#endif + default: return "unknown type"; + } + } + +#ifdef GLSLANG_WEB + TString getCompleteString() const { return ""; } + const char* getStorageQualifierString() const { return ""; } + const char* getBuiltInVariableString() const { return ""; } + const char* getPrecisionQualifierString() const { return ""; } + TString getBasicTypeString() const { return ""; } +#else + TString getCompleteString() const + { + TString typeString; + + const auto appendStr = [&](const char* s) { typeString.append(s); }; + const auto appendUint = [&](unsigned int u) { typeString.append(std::to_string(u).c_str()); }; + const auto appendInt = [&](int i) { typeString.append(std::to_string(i).c_str()); }; + + if (qualifier.hasLayout()) { + // To reduce noise, skip this if the only layout is an xfb_buffer + // with no triggering xfb_offset. + TQualifier noXfbBuffer = qualifier; + noXfbBuffer.layoutXfbBuffer = TQualifier::layoutXfbBufferEnd; + if (noXfbBuffer.hasLayout()) { + appendStr("layout("); + if (qualifier.hasAnyLocation()) { + appendStr(" location="); + appendUint(qualifier.layoutLocation); + if (qualifier.hasComponent()) { + appendStr(" component="); + appendUint(qualifier.layoutComponent); + } + if (qualifier.hasIndex()) { + appendStr(" index="); + appendUint(qualifier.layoutIndex); + } + } + if (qualifier.hasSet()) { + appendStr(" set="); + appendUint(qualifier.layoutSet); + } + if (qualifier.hasBinding()) { + appendStr(" binding="); + appendUint(qualifier.layoutBinding); + } + if (qualifier.hasStream()) { + appendStr(" stream="); + appendUint(qualifier.layoutStream); + } + if (qualifier.hasMatrix()) { + appendStr(" "); + appendStr(TQualifier::getLayoutMatrixString(qualifier.layoutMatrix)); + } + if (qualifier.hasPacking()) { + appendStr(" "); + appendStr(TQualifier::getLayoutPackingString(qualifier.layoutPacking)); + } + if (qualifier.hasOffset()) { + appendStr(" offset="); + appendInt(qualifier.layoutOffset); + } + if (qualifier.hasAlign()) { + appendStr(" align="); + appendInt(qualifier.layoutAlign); + } + if (qualifier.hasFormat()) { + appendStr(" "); + appendStr(TQualifier::getLayoutFormatString(qualifier.layoutFormat)); + } + if (qualifier.hasXfbBuffer() && qualifier.hasXfbOffset()) { + appendStr(" xfb_buffer="); + appendUint(qualifier.layoutXfbBuffer); + } + if (qualifier.hasXfbOffset()) { + appendStr(" xfb_offset="); + appendUint(qualifier.layoutXfbOffset); + } + if (qualifier.hasXfbStride()) { + appendStr(" xfb_stride="); + appendUint(qualifier.layoutXfbStride); + } + if (qualifier.hasAttachment()) { + appendStr(" input_attachment_index="); + appendUint(qualifier.layoutAttachment); + } + if (qualifier.hasSpecConstantId()) { + appendStr(" constant_id="); + appendUint(qualifier.layoutSpecConstantId); + } + if (qualifier.layoutPushConstant) + appendStr(" push_constant"); + if (qualifier.layoutBufferReference) + appendStr(" buffer_reference"); + if (qualifier.hasBufferReferenceAlign()) { + appendStr(" buffer_reference_align="); + appendUint(1u << qualifier.layoutBufferReferenceAlign); + } + + if (qualifier.layoutPassthrough) + appendStr(" passthrough"); + if (qualifier.layoutViewportRelative) + appendStr(" layoutViewportRelative"); + if (qualifier.layoutSecondaryViewportRelativeOffset != -2048) { + appendStr(" layoutSecondaryViewportRelativeOffset="); + appendInt(qualifier.layoutSecondaryViewportRelativeOffset); + } + if (qualifier.layoutShaderRecord) + appendStr(" shaderRecordNV"); + + appendStr(")"); + } + } + + if (qualifier.invariant) + appendStr(" invariant"); + if (qualifier.noContraction) + appendStr(" noContraction"); + if (qualifier.centroid) + appendStr(" centroid"); + if (qualifier.smooth) + appendStr(" smooth"); + if (qualifier.flat) + appendStr(" flat"); + if (qualifier.nopersp) + appendStr(" noperspective"); + if (qualifier.explicitInterp) + appendStr(" __explicitInterpAMD"); + if (qualifier.pervertexNV) + appendStr(" pervertexNV"); + if (qualifier.perPrimitiveNV) + appendStr(" perprimitiveNV"); + if (qualifier.perViewNV) + appendStr(" perviewNV"); + if (qualifier.perTaskNV) + appendStr(" taskNV"); + if (qualifier.patch) + appendStr(" patch"); + if (qualifier.sample) + appendStr(" sample"); + if (qualifier.coherent) + appendStr(" coherent"); + if (qualifier.devicecoherent) + appendStr(" devicecoherent"); + if (qualifier.queuefamilycoherent) + appendStr(" queuefamilycoherent"); + if (qualifier.workgroupcoherent) + appendStr(" workgroupcoherent"); + if (qualifier.subgroupcoherent) + appendStr(" subgroupcoherent"); + if (qualifier.shadercallcoherent) + appendStr(" shadercallcoherent"); + if (qualifier.nonprivate) + appendStr(" nonprivate"); + if (qualifier.volatil) + appendStr(" volatile"); + if (qualifier.restrict) + appendStr(" restrict"); + if (qualifier.readonly) + appendStr(" readonly"); + if (qualifier.writeonly) + appendStr(" writeonly"); + if (qualifier.specConstant) + appendStr(" specialization-constant"); + if (qualifier.nonUniform) + appendStr(" nonuniform"); + appendStr(" "); + appendStr(getStorageQualifierString()); + if (isArray()) { + for(int i = 0; i < (int)arraySizes->getNumDims(); ++i) { + int size = arraySizes->getDimSize(i); + if (size == UnsizedArraySize && i == 0 && arraySizes->isVariablyIndexed()) + appendStr(" runtime-sized array of"); + else { + if (size == UnsizedArraySize) { + appendStr(" unsized"); + if (i == 0) { + appendStr(" "); + appendInt(arraySizes->getImplicitSize()); + } + } else { + appendStr(" "); + appendInt(arraySizes->getDimSize(i)); + } + appendStr("-element array of"); + } + } + } + if (isParameterized()) { + appendStr("<"); + for(int i = 0; i < (int)typeParameters->getNumDims(); ++i) { + appendInt(typeParameters->getDimSize(i)); + if (i != (int)typeParameters->getNumDims() - 1) + appendStr(", "); + } + appendStr(">"); + } + if (qualifier.precision != EpqNone) { + appendStr(" "); + appendStr(getPrecisionQualifierString()); + } + if (isMatrix()) { + appendStr(" "); + appendInt(matrixCols); + appendStr("X"); + appendInt(matrixRows); + appendStr(" matrix of"); + } else if (isVector()) { + appendStr(" "); + appendInt(vectorSize); + appendStr("-component vector of"); + } + + appendStr(" "); + typeString.append(getBasicTypeString()); + + if (qualifier.builtIn != EbvNone) { + appendStr(" "); + appendStr(getBuiltInVariableString()); + } + + // Add struct/block members + if (isStruct() && structure) { + appendStr("{"); + bool hasHiddenMember = true; + for (size_t i = 0; i < structure->size(); ++i) { + if (! (*structure)[i].type->hiddenMember()) { + if (!hasHiddenMember) + appendStr(", "); + typeString.append((*structure)[i].type->getCompleteString()); + typeString.append(" "); + typeString.append((*structure)[i].type->getFieldName()); + hasHiddenMember = false; + } + } + appendStr("}"); + } + + return typeString; + } + + TString getBasicTypeString() const + { + if (basicType == EbtSampler) + return sampler.getString(); + else + return getBasicString(); + } + + const char* getStorageQualifierString() const { return GetStorageQualifierString(qualifier.storage); } + const char* getBuiltInVariableString() const { return GetBuiltInVariableString(qualifier.builtIn); } + const char* getPrecisionQualifierString() const { return GetPrecisionQualifierString(qualifier.precision); } +#endif + + const TTypeList* getStruct() const { assert(isStruct()); return structure; } + void setStruct(TTypeList* s) { assert(isStruct()); structure = s; } + TTypeList* getWritableStruct() const { assert(isStruct()); return structure; } // This should only be used when known to not be sharing with other threads + void setBasicType(const TBasicType& t) { basicType = t; } + + int computeNumComponents() const + { + int components = 0; + + if (getBasicType() == EbtStruct || getBasicType() == EbtBlock) { + for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++) + components += ((*tl).type)->computeNumComponents(); + } else if (matrixCols) + components = matrixCols * matrixRows; + else + components = vectorSize; + + if (arraySizes != nullptr) { + components *= arraySizes->getCumulativeSize(); + } + + return components; + } + + // append this type's mangled name to the passed in 'name' + void appendMangledName(TString& name) const + { + buildMangledName(name); + name += ';' ; + } + + // Do two structure types match? They could be declared independently, + // in different places, but still might satisfy the definition of matching. + // From the spec: + // + // "Structures must have the same name, sequence of type names, and + // type definitions, and member names to be considered the same type. + // This rule applies recursively for nested or embedded types." + // + bool sameStructType(const TType& right) const + { + // Most commonly, they are both nullptr, or the same pointer to the same actual structure + if ((!isStruct() && !right.isStruct()) || + (isStruct() && right.isStruct() && structure == right.structure)) + return true; + + // Both being nullptr was caught above, now they both have to be structures of the same number of elements + if (!isStruct() || !right.isStruct() || + structure->size() != right.structure->size()) + return false; + + // Structure names have to match + if (*typeName != *right.typeName) + return false; + + // Compare the names and types of all the members, which have to match + for (unsigned int i = 0; i < structure->size(); ++i) { + if ((*structure)[i].type->getFieldName() != (*right.structure)[i].type->getFieldName()) + return false; + + if (*(*structure)[i].type != *(*right.structure)[i].type) + return false; + } + + return true; + } + + bool sameReferenceType(const TType& right) const + { + if (isReference() != right.isReference()) + return false; + + if (!isReference() && !right.isReference()) + return true; + + assert(referentType != nullptr); + assert(right.referentType != nullptr); + + if (referentType == right.referentType) + return true; + + return *referentType == *right.referentType; + } + + // See if two types match, in all aspects except arrayness + bool sameElementType(const TType& right) const + { + return basicType == right.basicType && sameElementShape(right); + } + + // See if two type's arrayness match + bool sameArrayness(const TType& right) const + { + return ((arraySizes == nullptr && right.arraySizes == nullptr) || + (arraySizes != nullptr && right.arraySizes != nullptr && *arraySizes == *right.arraySizes)); + } + + // See if two type's arrayness match in everything except their outer dimension + bool sameInnerArrayness(const TType& right) const + { + assert(arraySizes != nullptr && right.arraySizes != nullptr); + return arraySizes->sameInnerArrayness(*right.arraySizes); + } + + // See if two type's parameters match + bool sameTypeParameters(const TType& right) const + { + return ((typeParameters == nullptr && right.typeParameters == nullptr) || + (typeParameters != nullptr && right.typeParameters != nullptr && *typeParameters == *right.typeParameters)); + } + + // See if two type's elements match in all ways except basic type + bool sameElementShape(const TType& right) const + { + return sampler == right.sampler && + vectorSize == right.vectorSize && + matrixCols == right.matrixCols && + matrixRows == right.matrixRows && + vector1 == right.vector1 && + isCoopMat() == right.isCoopMat() && + sameStructType(right) && + sameReferenceType(right); + } + + // See if a cooperative matrix type parameter with unspecified parameters is + // an OK function parameter + bool coopMatParameterOK(const TType& right) const + { + return isCoopMat() && right.isCoopMat() && (getBasicType() == right.getBasicType()) && + typeParameters == nullptr && right.typeParameters != nullptr; + } + + bool sameCoopMatBaseType(const TType &right) const { + bool rv = coopmat && right.coopmat; + if (getBasicType() == EbtFloat || getBasicType() == EbtFloat16) + rv = right.getBasicType() == EbtFloat || right.getBasicType() == EbtFloat16; + else if (getBasicType() == EbtUint || getBasicType() == EbtUint8) + rv = right.getBasicType() == EbtUint || right.getBasicType() == EbtUint8; + else if (getBasicType() == EbtInt || getBasicType() == EbtInt8) + rv = right.getBasicType() == EbtInt || right.getBasicType() == EbtInt8; + else + rv = false; + return rv; + } + + + // See if two types match in all ways (just the actual type, not qualification) + bool operator==(const TType& right) const + { + return sameElementType(right) && sameArrayness(right) && sameTypeParameters(right); + } + + bool operator!=(const TType& right) const + { + return ! operator==(right); + } + + unsigned int getBufferReferenceAlignment() const + { +#ifndef GLSLANG_WEB + if (getBasicType() == glslang::EbtReference) { + return getReferentType()->getQualifier().hasBufferReferenceAlign() ? + (1u << getReferentType()->getQualifier().layoutBufferReferenceAlign) : 16u; + } +#endif + return 0; + } + +protected: + // Require consumer to pick between deep copy and shallow copy. + TType(const TType& type); + TType& operator=(const TType& type); + + // Recursively copy a type graph, while preserving the graph-like + // quality. That is, don't make more than one copy of a structure that + // gets reused multiple times in the type graph. + void deepCopy(const TType& copyOf, TMap& copiedMap) + { + shallowCopy(copyOf); + + if (copyOf.arraySizes) { + arraySizes = new TArraySizes; + *arraySizes = *copyOf.arraySizes; + } + + if (copyOf.typeParameters) { + typeParameters = new TArraySizes; + *typeParameters = *copyOf.typeParameters; + } + + if (copyOf.isStruct() && copyOf.structure) { + auto prevCopy = copiedMap.find(copyOf.structure); + if (prevCopy != copiedMap.end()) + structure = prevCopy->second; + else { + structure = new TTypeList; + copiedMap[copyOf.structure] = structure; + for (unsigned int i = 0; i < copyOf.structure->size(); ++i) { + TTypeLoc typeLoc; + typeLoc.loc = (*copyOf.structure)[i].loc; + typeLoc.type = new TType(); + typeLoc.type->deepCopy(*(*copyOf.structure)[i].type, copiedMap); + structure->push_back(typeLoc); + } + } + } + + if (copyOf.fieldName) + fieldName = NewPoolTString(copyOf.fieldName->c_str()); + if (copyOf.typeName) + typeName = NewPoolTString(copyOf.typeName->c_str()); + } + + + void buildMangledName(TString&) const; + + TBasicType basicType : 8; + int vectorSize : 4; // 1 means either scalar or 1-component vector; see vector1 to disambiguate. + int matrixCols : 4; + int matrixRows : 4; + bool vector1 : 1; // Backward-compatible tracking of a 1-component vector distinguished from a scalar. + // GLSL 4.5 never has a 1-component vector; so this will always be false until such + // functionality is added. + // HLSL does have a 1-component vectors, so this will be true to disambiguate + // from a scalar. + bool coopmat : 1; + TQualifier qualifier; + + TArraySizes* arraySizes; // nullptr unless an array; can be shared across types + // A type can't be both a structure (EbtStruct/EbtBlock) and a reference (EbtReference), so + // conserve space by making these a union + union { + TTypeList* structure; // invalid unless this is a struct; can be shared across types + TType *referentType; // invalid unless this is an EbtReference + }; + TString *fieldName; // for structure field names + TString *typeName; // for structure type name + TSampler sampler; + TArraySizes* typeParameters;// nullptr unless a parameterized type; can be shared across types +}; + +} // end namespace glslang + +#endif // _TYPES_INCLUDED_ diff --git a/android/x86/include/glslang/Include/arrays.h b/android/x86/include/glslang/Include/arrays.h new file mode 100644 index 00000000..7f047d9f --- /dev/null +++ b/android/x86/include/glslang/Include/arrays.h @@ -0,0 +1,341 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +// +// Implement types for tracking GLSL arrays, arrays of arrays, etc. +// + +#ifndef _ARRAYS_INCLUDED +#define _ARRAYS_INCLUDED + +#include + +namespace glslang { + +// This is used to mean there is no size yet (unsized), it is waiting to get a size from somewhere else. +const int UnsizedArraySize = 0; + +class TIntermTyped; +extern bool SameSpecializationConstants(TIntermTyped*, TIntermTyped*); + +// Specialization constants need both a nominal size and a node that defines +// the specialization constant being used. Array types are the same when their +// size and specialization constant nodes are the same. +struct TArraySize { + unsigned int size; + TIntermTyped* node; // nullptr means no specialization constant node + bool operator==(const TArraySize& rhs) const + { + if (size != rhs.size) + return false; + if (node == nullptr || rhs.node == nullptr) + return node == rhs.node; + + return SameSpecializationConstants(node, rhs.node); + } +}; + +// +// TSmallArrayVector is used as the container for the set of sizes in TArraySizes. +// It has generic-container semantics, while TArraySizes has array-of-array semantics. +// That is, TSmallArrayVector should be more focused on mechanism and TArraySizes on policy. +// +struct TSmallArrayVector { + // + // TODO: memory: TSmallArrayVector is intended to be smaller. + // Almost all arrays could be handled by two sizes each fitting + // in 16 bits, needing a real vector only in the cases where there + // are more than 3 sizes or a size needing more than 16 bits. + // + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + TSmallArrayVector() : sizes(nullptr) { } + virtual ~TSmallArrayVector() { dealloc(); } + + // For breaking into two non-shared copies, independently modifiable. + TSmallArrayVector& operator=(const TSmallArrayVector& from) + { + if (from.sizes == nullptr) + sizes = nullptr; + else { + alloc(); + *sizes = *from.sizes; + } + + return *this; + } + + int size() const + { + if (sizes == nullptr) + return 0; + return (int)sizes->size(); + } + + unsigned int frontSize() const + { + assert(sizes != nullptr && sizes->size() > 0); + return sizes->front().size; + } + + TIntermTyped* frontNode() const + { + assert(sizes != nullptr && sizes->size() > 0); + return sizes->front().node; + } + + void changeFront(unsigned int s) + { + assert(sizes != nullptr); + // this should only happen for implicitly sized arrays, not specialization constants + assert(sizes->front().node == nullptr); + sizes->front().size = s; + } + + void push_back(unsigned int e, TIntermTyped* n) + { + alloc(); + TArraySize pair = { e, n }; + sizes->push_back(pair); + } + + void push_back(const TSmallArrayVector& newDims) + { + alloc(); + sizes->insert(sizes->end(), newDims.sizes->begin(), newDims.sizes->end()); + } + + void pop_front() + { + assert(sizes != nullptr && sizes->size() > 0); + if (sizes->size() == 1) + dealloc(); + else + sizes->erase(sizes->begin()); + } + + // 'this' should currently not be holding anything, and copyNonFront + // will make it hold a copy of all but the first element of rhs. + // (This would be useful for making a type that is dereferenced by + // one dimension.) + void copyNonFront(const TSmallArrayVector& rhs) + { + assert(sizes == nullptr); + if (rhs.size() > 1) { + alloc(); + sizes->insert(sizes->begin(), rhs.sizes->begin() + 1, rhs.sizes->end()); + } + } + + unsigned int getDimSize(int i) const + { + assert(sizes != nullptr && (int)sizes->size() > i); + return (*sizes)[i].size; + } + + void setDimSize(int i, unsigned int size) const + { + assert(sizes != nullptr && (int)sizes->size() > i); + assert((*sizes)[i].node == nullptr); + (*sizes)[i].size = size; + } + + TIntermTyped* getDimNode(int i) const + { + assert(sizes != nullptr && (int)sizes->size() > i); + return (*sizes)[i].node; + } + + bool operator==(const TSmallArrayVector& rhs) const + { + if (sizes == nullptr && rhs.sizes == nullptr) + return true; + if (sizes == nullptr || rhs.sizes == nullptr) + return false; + return *sizes == *rhs.sizes; + } + bool operator!=(const TSmallArrayVector& rhs) const { return ! operator==(rhs); } + +protected: + TSmallArrayVector(const TSmallArrayVector&); + + void alloc() + { + if (sizes == nullptr) + sizes = new TVector; + } + void dealloc() + { + delete sizes; + sizes = nullptr; + } + + TVector* sizes; // will either hold such a pointer, or in the future, hold the two array sizes +}; + +// +// Represent an array, or array of arrays, to arbitrary depth. This is not +// done through a hierarchy of types in a type tree, rather all contiguous arrayness +// in the type hierarchy is localized into this single cumulative object. +// +// The arrayness in TTtype is a pointer, so that it can be non-allocated and zero +// for the vast majority of types that are non-array types. +// +// Order Policy: these are all identical: +// - left to right order within a contiguous set of ...[..][..][..]... in the source language +// - index order 0, 1, 2, ... within the 'sizes' member below +// - outer-most to inner-most +// +struct TArraySizes { + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + TArraySizes() : implicitArraySize(1), variablyIndexed(false) { } + + // For breaking into two non-shared copies, independently modifiable. + TArraySizes& operator=(const TArraySizes& from) + { + implicitArraySize = from.implicitArraySize; + variablyIndexed = from.variablyIndexed; + sizes = from.sizes; + + return *this; + } + + // translate from array-of-array semantics to container semantics + int getNumDims() const { return sizes.size(); } + int getDimSize(int dim) const { return sizes.getDimSize(dim); } + TIntermTyped* getDimNode(int dim) const { return sizes.getDimNode(dim); } + void setDimSize(int dim, int size) { sizes.setDimSize(dim, size); } + int getOuterSize() const { return sizes.frontSize(); } + TIntermTyped* getOuterNode() const { return sizes.frontNode(); } + int getCumulativeSize() const + { + int size = 1; + for (int d = 0; d < sizes.size(); ++d) { + // this only makes sense in paths that have a known array size + assert(sizes.getDimSize(d) != UnsizedArraySize); + size *= sizes.getDimSize(d); + } + return size; + } + void addInnerSize() { addInnerSize((unsigned)UnsizedArraySize); } + void addInnerSize(int s) { addInnerSize((unsigned)s, nullptr); } + void addInnerSize(int s, TIntermTyped* n) { sizes.push_back((unsigned)s, n); } + void addInnerSize(TArraySize pair) { + sizes.push_back(pair.size, pair.node); + } + void addInnerSizes(const TArraySizes& s) { sizes.push_back(s.sizes); } + void changeOuterSize(int s) { sizes.changeFront((unsigned)s); } + int getImplicitSize() const { return implicitArraySize; } + void updateImplicitSize(int s) { implicitArraySize = std::max(implicitArraySize, s); } + bool isInnerUnsized() const + { + for (int d = 1; d < sizes.size(); ++d) { + if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize) + return true; + } + + return false; + } + bool clearInnerUnsized() + { + for (int d = 1; d < sizes.size(); ++d) { + if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize) + setDimSize(d, 1); + } + + return false; + } + bool isInnerSpecialization() const + { + for (int d = 1; d < sizes.size(); ++d) { + if (sizes.getDimNode(d) != nullptr) + return true; + } + + return false; + } + bool isOuterSpecialization() + { + return sizes.getDimNode(0) != nullptr; + } + + bool hasUnsized() const { return getOuterSize() == UnsizedArraySize || isInnerUnsized(); } + bool isSized() const { return getOuterSize() != UnsizedArraySize; } + void dereference() { sizes.pop_front(); } + void copyDereferenced(const TArraySizes& rhs) + { + assert(sizes.size() == 0); + if (rhs.sizes.size() > 1) + sizes.copyNonFront(rhs.sizes); + } + + bool sameInnerArrayness(const TArraySizes& rhs) const + { + if (sizes.size() != rhs.sizes.size()) + return false; + + for (int d = 1; d < sizes.size(); ++d) { + if (sizes.getDimSize(d) != rhs.sizes.getDimSize(d) || + sizes.getDimNode(d) != rhs.sizes.getDimNode(d)) + return false; + } + + return true; + } + + void setVariablyIndexed() { variablyIndexed = true; } + bool isVariablyIndexed() const { return variablyIndexed; } + + bool operator==(const TArraySizes& rhs) const { return sizes == rhs.sizes; } + bool operator!=(const TArraySizes& rhs) const { return sizes != rhs.sizes; } + +protected: + TSmallArrayVector sizes; + + TArraySizes(const TArraySizes&); + + // For tracking maximum referenced compile-time constant index. + // Applies only to the outer-most dimension. Potentially becomes + // the implicit size of the array, if not variably indexed and + // otherwise legal. + int implicitArraySize; + bool variablyIndexed; // true if array is indexed with a non compile-time constant +}; + +} // end namespace glslang + +#endif // _ARRAYS_INCLUDED_ diff --git a/android/x86/include/glslang/Include/glslang_c_interface.h b/android/x86/include/glslang/Include/glslang_c_interface.h new file mode 100644 index 00000000..5a450e0e --- /dev/null +++ b/android/x86/include/glslang/Include/glslang_c_interface.h @@ -0,0 +1,232 @@ +/** + This code is based on the glslang_c_interface implementation by Viktor Latypov +**/ + +/** +BSD 2-Clause License + +Copyright (c) 2019, Viktor Latypov +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**/ + +#ifndef GLSLANG_C_IFACE_H_INCLUDED +#define GLSLANG_C_IFACE_H_INCLUDED + +#include +#include + +#include "glslang_c_shader_types.h" + +typedef struct glslang_shader_s glslang_shader_t; +typedef struct glslang_program_s glslang_program_t; + +/* TLimits counterpart */ +typedef struct glslang_limits_s { + bool non_inductive_for_loops; + bool while_loops; + bool do_while_loops; + bool general_uniform_indexing; + bool general_attribute_matrix_vector_indexing; + bool general_varying_indexing; + bool general_sampler_indexing; + bool general_variable_indexing; + bool general_constant_matrix_vector_indexing; +} glslang_limits_t; + +/* TBuiltInResource counterpart */ +typedef struct glslang_resource_s { + int max_lights; + int max_clip_planes; + int max_texture_units; + int max_texture_coords; + int max_vertex_attribs; + int max_vertex_uniform_components; + int max_varying_floats; + int max_vertex_texture_image_units; + int max_combined_texture_image_units; + int max_texture_image_units; + int max_fragment_uniform_components; + int max_draw_buffers; + int max_vertex_uniform_vectors; + int max_varying_vectors; + int max_fragment_uniform_vectors; + int max_vertex_output_vectors; + int max_fragment_input_vectors; + int min_program_texel_offset; + int max_program_texel_offset; + int max_clip_distances; + int max_compute_work_group_count_x; + int max_compute_work_group_count_y; + int max_compute_work_group_count_z; + int max_compute_work_group_size_x; + int max_compute_work_group_size_y; + int max_compute_work_group_size_z; + int max_compute_uniform_components; + int max_compute_texture_image_units; + int max_compute_image_uniforms; + int max_compute_atomic_counters; + int max_compute_atomic_counter_buffers; + int max_varying_components; + int max_vertex_output_components; + int max_geometry_input_components; + int max_geometry_output_components; + int max_fragment_input_components; + int max_image_units; + int max_combined_image_units_and_fragment_outputs; + int max_combined_shader_output_resources; + int max_image_samples; + int max_vertex_image_uniforms; + int max_tess_control_image_uniforms; + int max_tess_evaluation_image_uniforms; + int max_geometry_image_uniforms; + int max_fragment_image_uniforms; + int max_combined_image_uniforms; + int max_geometry_texture_image_units; + int max_geometry_output_vertices; + int max_geometry_total_output_components; + int max_geometry_uniform_components; + int max_geometry_varying_components; + int max_tess_control_input_components; + int max_tess_control_output_components; + int max_tess_control_texture_image_units; + int max_tess_control_uniform_components; + int max_tess_control_total_output_components; + int max_tess_evaluation_input_components; + int max_tess_evaluation_output_components; + int max_tess_evaluation_texture_image_units; + int max_tess_evaluation_uniform_components; + int max_tess_patch_components; + int max_patch_vertices; + int max_tess_gen_level; + int max_viewports; + int max_vertex_atomic_counters; + int max_tess_control_atomic_counters; + int max_tess_evaluation_atomic_counters; + int max_geometry_atomic_counters; + int max_fragment_atomic_counters; + int max_combined_atomic_counters; + int max_atomic_counter_bindings; + int max_vertex_atomic_counter_buffers; + int max_tess_control_atomic_counter_buffers; + int max_tess_evaluation_atomic_counter_buffers; + int max_geometry_atomic_counter_buffers; + int max_fragment_atomic_counter_buffers; + int max_combined_atomic_counter_buffers; + int max_atomic_counter_buffer_size; + int max_transform_feedback_buffers; + int max_transform_feedback_interleaved_components; + int max_cull_distances; + int max_combined_clip_and_cull_distances; + int max_samples; + int max_mesh_output_vertices_nv; + int max_mesh_output_primitives_nv; + int max_mesh_work_group_size_x_nv; + int max_mesh_work_group_size_y_nv; + int max_mesh_work_group_size_z_nv; + int max_task_work_group_size_x_nv; + int max_task_work_group_size_y_nv; + int max_task_work_group_size_z_nv; + int max_mesh_view_count_nv; + + glslang_limits_t limits; +} glslang_resource_t; + +typedef struct glslang_input_s { + glslang_source_t language; + glslang_stage_t stage; + glslang_client_t client; + glslang_target_client_version_t client_version; + glslang_target_language_t target_language; + glslang_target_language_version_t target_language_version; + /** Shader source code */ + const char* code; + int default_version; + glslang_profile_t default_profile; + int force_default_version_and_profile; + int forward_compatible; + glslang_messages_t messages; + const glslang_resource_t* resource; +} glslang_input_t; + +/* Inclusion result structure allocated by C include_local/include_system callbacks */ +typedef struct glsl_include_result_s { + /* Header file name or NULL if inclusion failed */ + const char* header_name; + + /* Header contents or NULL */ + const char* header_data; + size_t header_length; + +} glsl_include_result_t; + +/* Callback for local file inclusion */ +typedef glsl_include_result_t* (*glsl_include_local_func)(void* ctx, const char* header_name, const char* includer_name, + size_t include_depth); + +/* Callback for system file inclusion */ +typedef glsl_include_result_t* (*glsl_include_system_func)(void* ctx, const char* header_name, + const char* includer_name, size_t include_depth); + +/* Callback for include result destruction */ +typedef int (*glsl_free_include_result_func)(void* ctx, glsl_include_result_t* result); + +/* Collection of callbacks for GLSL preprocessor */ +typedef struct glsl_include_callbacks_s { + glsl_include_system_func include_system; + glsl_include_local_func include_local; + glsl_free_include_result_func free_include_result; +} glsl_include_callbacks_t; + +#ifdef __cplusplus +extern "C" { +#endif + +int glslang_initialize_process(); +void glslang_finalize_process(); + +glslang_shader_t* glslang_shader_create(const glslang_input_t* input); +void glslang_shader_delete(glslang_shader_t* shader); +int glslang_shader_preprocess(glslang_shader_t* shader, const glslang_input_t* input); +int glslang_shader_parse(glslang_shader_t* shader, const glslang_input_t* input); +const char* glslang_shader_get_preprocessed_code(glslang_shader_t* shader); +const char* glslang_shader_get_info_log(glslang_shader_t* shader); +const char* glslang_shader_get_info_debug_log(glslang_shader_t* shader); + +glslang_program_t* glslang_program_create(); +void glslang_program_delete(glslang_program_t* program); +void glslang_program_add_shader(glslang_program_t* program, glslang_shader_t* shader); +int glslang_program_link(glslang_program_t* program, int messages); // glslang_messages_t +void glslang_program_SPIRV_generate(glslang_program_t* program, glslang_stage_t stage); +size_t glslang_program_SPIRV_get_size(glslang_program_t* program); +void glslang_program_SPIRV_get(glslang_program_t* program, unsigned int*); +unsigned int* glslang_program_SPIRV_get_ptr(glslang_program_t* program); +const char* glslang_program_SPIRV_get_messages(glslang_program_t* program); +const char* glslang_program_get_info_log(glslang_program_t* program); +const char* glslang_program_get_info_debug_log(glslang_program_t* program); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifdef GLSLANG_C_IFACE_INCLUDED */ diff --git a/android/x86/include/glslang/Include/glslang_c_shader_types.h b/android/x86/include/glslang/Include/glslang_c_shader_types.h new file mode 100644 index 00000000..769f4c4a --- /dev/null +++ b/android/x86/include/glslang/Include/glslang_c_shader_types.h @@ -0,0 +1,182 @@ +/** + This code is based on the glslang_c_interface implementation by Viktor Latypov +**/ + +/** +BSD 2-Clause License + +Copyright (c) 2019, Viktor Latypov +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**/ + +#ifndef C_SHADER_TYPES_H_INCLUDED +#define C_SHADER_TYPES_H_INCLUDED + +#define LAST_ELEMENT_MARKER(x) x + +/* EShLanguage counterpart */ +typedef enum { + GLSLANG_STAGE_VERTEX, + GLSLANG_STAGE_TESSCONTROL, + GLSLANG_STAGE_TESSEVALUATION, + GLSLANG_STAGE_GEOMETRY, + GLSLANG_STAGE_FRAGMENT, + GLSLANG_STAGE_COMPUTE, + GLSLANG_STAGE_RAYGEN_NV, + GLSLANG_STAGE_INTERSECT_NV, + GLSLANG_STAGE_ANYHIT_NV, + GLSLANG_STAGE_CLOSESTHIT_NV, + GLSLANG_STAGE_MISS_NV, + GLSLANG_STAGE_CALLABLE_NV, + GLSLANG_STAGE_TASK_NV, + GLSLANG_STAGE_MESH_NV, + LAST_ELEMENT_MARKER(GLSLANG_STAGE_COUNT), +} glslang_stage_t; // would be better as stage, but this is ancient now + +/* EShLanguageMask counterpart */ +typedef enum { + GLSLANG_STAGE_VERTEX_MASK = (1 << GLSLANG_STAGE_VERTEX), + GLSLANG_STAGE_TESSCONTROL_MASK = (1 << GLSLANG_STAGE_TESSCONTROL), + GLSLANG_STAGE_TESSEVALUATION_MASK = (1 << GLSLANG_STAGE_TESSEVALUATION), + GLSLANG_STAGE_GEOMETRY_MASK = (1 << GLSLANG_STAGE_GEOMETRY), + GLSLANG_STAGE_FRAGMENT_MASK = (1 << GLSLANG_STAGE_FRAGMENT), + GLSLANG_STAGE_COMPUTE_MASK = (1 << GLSLANG_STAGE_COMPUTE), + GLSLANG_STAGE_RAYGEN_NV_MASK = (1 << GLSLANG_STAGE_RAYGEN_NV), + GLSLANG_STAGE_INTERSECT_NV_MASK = (1 << GLSLANG_STAGE_INTERSECT_NV), + GLSLANG_STAGE_ANYHIT_NV_MASK = (1 << GLSLANG_STAGE_ANYHIT_NV), + GLSLANG_STAGE_CLOSESTHIT_NV_MASK = (1 << GLSLANG_STAGE_CLOSESTHIT_NV), + GLSLANG_STAGE_MISS_NV_MASK = (1 << GLSLANG_STAGE_MISS_NV), + GLSLANG_STAGE_CALLABLE_NV_MASK = (1 << GLSLANG_STAGE_CALLABLE_NV), + GLSLANG_STAGE_TASK_NV_MASK = (1 << GLSLANG_STAGE_TASK_NV), + GLSLANG_STAGE_MESH_NV_MASK = (1 << GLSLANG_STAGE_MESH_NV), + LAST_ELEMENT_MARKER(GLSLANG_STAGE_MASK_COUNT), +} glslang_stage_mask_t; + +/* EShSource counterpart */ +typedef enum { + GLSLANG_SOURCE_NONE, + GLSLANG_SOURCE_GLSL, + GLSLANG_SOURCE_HLSL, + LAST_ELEMENT_MARKER(GLSLANG_SOURCE_COUNT), +} glslang_source_t; + +/* EShClient counterpart */ +typedef enum { + GLSLANG_CLIENT_NONE, + GLSLANG_CLIENT_VULKAN, + GLSLANG_CLIENT_OPENGL, + LAST_ELEMENT_MARKER(GLSLANG_CLIENT_COUNT), +} glslang_client_t; + +/* EShTargetLanguage counterpart */ +typedef enum { + GLSLANG_TARGET_NONE, + GLSLANG_TARGET_SPV, + LAST_ELEMENT_MARKER(GLSLANG_TARGET_COUNT), +} glslang_target_language_t; + +/* SH_TARGET_ClientVersion counterpart */ +typedef enum { + GLSLANG_TARGET_VULKAN_1_0 = (1 << 22), + GLSLANG_TARGET_VULKAN_1_1 = (1 << 22) | (1 << 12), + GLSLANG_TARGET_OPENGL_450 = 450, + LAST_ELEMENT_MARKER(GLSLANG_TARGET_CLIENT_VERSION_COUNT), +} glslang_target_client_version_t; + +/* SH_TARGET_LanguageVersion counterpart */ +typedef enum { + GLSLANG_TARGET_SPV_1_0 = (1 << 16), + GLSLANG_TARGET_SPV_1_1 = (1 << 16) | (1 << 8), + GLSLANG_TARGET_SPV_1_2 = (1 << 16) | (2 << 8), + GLSLANG_TARGET_SPV_1_3 = (1 << 16) | (3 << 8), + GLSLANG_TARGET_SPV_1_4 = (1 << 16) | (4 << 8), + GLSLANG_TARGET_SPV_1_5 = (1 << 16) | (5 << 8), + LAST_ELEMENT_MARKER(GLSLANG_TARGET_LANGUAGE_VERSION_COUNT), +} glslang_target_language_version_t; + +/* EShExecutable counterpart */ +typedef enum { GLSLANG_EX_VERTEX_FRAGMENT, GLSLANG_EX_FRAGMENT } glslang_executable_t; + +/* EShOptimizationLevel counterpart */ +typedef enum { + GLSLANG_OPT_NO_GENERATION, + GLSLANG_OPT_NONE, + GLSLANG_OPT_SIMPLE, + GLSLANG_OPT_FULL, + LAST_ELEMENT_MARKER(GLSLANG_OPT_LEVEL_COUNT), +} glslang_optimization_level_t; + +/* EShTextureSamplerTransformMode counterpart */ +typedef enum { + GLSLANG_TEX_SAMP_TRANS_KEEP, + GLSLANG_TEX_SAMP_TRANS_UPGRADE_TEXTURE_REMOVE_SAMPLER, + LAST_ELEMENT_MARKER(GLSLANG_TEX_SAMP_TRANS_COUNT), +} glslang_texture_sampler_transform_mode_t; + +/* EShMessages counterpart */ +typedef enum { + GLSLANG_MSG_DEFAULT_BIT = 0, + GLSLANG_MSG_RELAXED_ERRORS_BIT = (1 << 0), + GLSLANG_MSG_SUPPRESS_WARNINGS_BIT = (1 << 1), + GLSLANG_MSG_AST_BIT = (1 << 2), + GLSLANG_MSG_SPV_RULES_BIT = (1 << 3), + GLSLANG_MSG_VULKAN_RULES_BIT = (1 << 4), + GLSLANG_MSG_ONLY_PREPROCESSOR_BIT = (1 << 5), + GLSLANG_MSG_READ_HLSL_BIT = (1 << 6), + GLSLANG_MSG_CASCADING_ERRORS_BIT = (1 << 7), + GLSLANG_MSG_KEEP_UNCALLED_BIT = (1 << 8), + GLSLANG_MSG_HLSL_OFFSETS_BIT = (1 << 9), + GLSLANG_MSG_DEBUG_INFO_BIT = (1 << 10), + GLSLANG_MSG_HLSL_ENABLE_16BIT_TYPES_BIT = (1 << 11), + GLSLANG_MSG_HLSL_LEGALIZATION_BIT = (1 << 12), + GLSLANG_MSG_HLSL_DX9_COMPATIBLE_BIT = (1 << 13), + GLSLANG_MSG_BUILTIN_SYMBOL_TABLE_BIT = (1 << 14), + LAST_ELEMENT_MARKER(GLSLANG_MSG_COUNT), +} glslang_messages_t; + +/* EShReflectionOptions counterpart */ +typedef enum { + GLSLANG_REFLECTION_DEFAULT_BIT = 0, + GLSLANG_REFLECTION_STRICT_ARRAY_SUFFIX_BIT = (1 << 0), + GLSLANG_REFLECTION_BASIC_ARRAY_SUFFIX_BIT = (1 << 1), + GLSLANG_REFLECTION_INTERMEDIATE_IOO_BIT = (1 << 2), + GLSLANG_REFLECTION_SEPARATE_BUFFERS_BIT = (1 << 3), + GLSLANG_REFLECTION_ALL_BLOCK_VARIABLES_BIT = (1 << 4), + GLSLANG_REFLECTION_UNWRAP_IO_BLOCKS_BIT = (1 << 5), + LAST_ELEMENT_MARKER(GLSLANG_REFLECTION_COUNT), +} glslang_reflection_options_t; + +/* EProfile counterpart (from Versions.h) */ +typedef enum { + GLSLANG_BAD_PROFILE = 0, + GLSLANG_NO_PROFILE = (1 << 0), + GLSLANG_CORE_PROFILE = (1 << 1), + GLSLANG_COMPATIBILITY_PROFILE = (1 << 2), + GLSLANG_ES_PROFILE = (1 << 3), + LAST_ELEMENT_MARKER(GLSLANG_PROFILE_COUNT), +} glslang_profile_t; + +#undef LAST_ELEMENT_MARKER + +#endif diff --git a/android/x86/include/glslang/Include/intermediate.h b/android/x86/include/glslang/Include/intermediate.h new file mode 100644 index 00000000..bf12fcf8 --- /dev/null +++ b/android/x86/include/glslang/Include/intermediate.h @@ -0,0 +1,1805 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2016 LunarG, Inc. +// Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +// +// Definition of the in-memory high-level intermediate representation +// of shaders. This is a tree that parser creates. +// +// Nodes in the tree are defined as a hierarchy of classes derived from +// TIntermNode. Each is a node in a tree. There is no preset branching factor; +// each node can have it's own type of list of children. +// + +#ifndef __INTERMEDIATE_H +#define __INTERMEDIATE_H + +#if defined(_MSC_VER) && _MSC_VER >= 1900 + #pragma warning(disable : 4464) // relative include path contains '..' + #pragma warning(disable : 5026) // 'glslang::TIntermUnary': move constructor was implicitly defined as deleted +#endif + +#include "../Include/Common.h" +#include "../Include/Types.h" +#include "../Include/ConstantUnion.h" + +namespace glslang { + +class TIntermediate; + +// +// Operators used by the high-level (parse tree) representation. +// +enum TOperator { + EOpNull, // if in a node, should only mean a node is still being built + EOpSequence, // denotes a list of statements, or parameters, etc. + EOpLinkerObjects, // for aggregate node of objects the linker may need, if not reference by the rest of the AST + EOpFunctionCall, + EOpFunction, // For function definition + EOpParameters, // an aggregate listing the parameters to a function + + // + // Unary operators + // + + EOpNegative, + EOpLogicalNot, + EOpVectorLogicalNot, + EOpBitwiseNot, + + EOpPostIncrement, + EOpPostDecrement, + EOpPreIncrement, + EOpPreDecrement, + + EOpCopyObject, + + // (u)int* -> bool + EOpConvInt8ToBool, + EOpConvUint8ToBool, + EOpConvInt16ToBool, + EOpConvUint16ToBool, + EOpConvIntToBool, + EOpConvUintToBool, + EOpConvInt64ToBool, + EOpConvUint64ToBool, + + // float* -> bool + EOpConvFloat16ToBool, + EOpConvFloatToBool, + EOpConvDoubleToBool, + + // bool -> (u)int* + EOpConvBoolToInt8, + EOpConvBoolToUint8, + EOpConvBoolToInt16, + EOpConvBoolToUint16, + EOpConvBoolToInt, + EOpConvBoolToUint, + EOpConvBoolToInt64, + EOpConvBoolToUint64, + + // bool -> float* + EOpConvBoolToFloat16, + EOpConvBoolToFloat, + EOpConvBoolToDouble, + + // int8_t -> (u)int* + EOpConvInt8ToInt16, + EOpConvInt8ToInt, + EOpConvInt8ToInt64, + EOpConvInt8ToUint8, + EOpConvInt8ToUint16, + EOpConvInt8ToUint, + EOpConvInt8ToUint64, + + // uint8_t -> (u)int* + EOpConvUint8ToInt8, + EOpConvUint8ToInt16, + EOpConvUint8ToInt, + EOpConvUint8ToInt64, + EOpConvUint8ToUint16, + EOpConvUint8ToUint, + EOpConvUint8ToUint64, + + // int8_t -> float* + EOpConvInt8ToFloat16, + EOpConvInt8ToFloat, + EOpConvInt8ToDouble, + + // uint8_t -> float* + EOpConvUint8ToFloat16, + EOpConvUint8ToFloat, + EOpConvUint8ToDouble, + + // int16_t -> (u)int* + EOpConvInt16ToInt8, + EOpConvInt16ToInt, + EOpConvInt16ToInt64, + EOpConvInt16ToUint8, + EOpConvInt16ToUint16, + EOpConvInt16ToUint, + EOpConvInt16ToUint64, + + // uint16_t -> (u)int* + EOpConvUint16ToInt8, + EOpConvUint16ToInt16, + EOpConvUint16ToInt, + EOpConvUint16ToInt64, + EOpConvUint16ToUint8, + EOpConvUint16ToUint, + EOpConvUint16ToUint64, + + // int16_t -> float* + EOpConvInt16ToFloat16, + EOpConvInt16ToFloat, + EOpConvInt16ToDouble, + + // uint16_t -> float* + EOpConvUint16ToFloat16, + EOpConvUint16ToFloat, + EOpConvUint16ToDouble, + + // int32_t -> (u)int* + EOpConvIntToInt8, + EOpConvIntToInt16, + EOpConvIntToInt64, + EOpConvIntToUint8, + EOpConvIntToUint16, + EOpConvIntToUint, + EOpConvIntToUint64, + + // uint32_t -> (u)int* + EOpConvUintToInt8, + EOpConvUintToInt16, + EOpConvUintToInt, + EOpConvUintToInt64, + EOpConvUintToUint8, + EOpConvUintToUint16, + EOpConvUintToUint64, + + // int32_t -> float* + EOpConvIntToFloat16, + EOpConvIntToFloat, + EOpConvIntToDouble, + + // uint32_t -> float* + EOpConvUintToFloat16, + EOpConvUintToFloat, + EOpConvUintToDouble, + + // int64_t -> (u)int* + EOpConvInt64ToInt8, + EOpConvInt64ToInt16, + EOpConvInt64ToInt, + EOpConvInt64ToUint8, + EOpConvInt64ToUint16, + EOpConvInt64ToUint, + EOpConvInt64ToUint64, + + // uint64_t -> (u)int* + EOpConvUint64ToInt8, + EOpConvUint64ToInt16, + EOpConvUint64ToInt, + EOpConvUint64ToInt64, + EOpConvUint64ToUint8, + EOpConvUint64ToUint16, + EOpConvUint64ToUint, + + // int64_t -> float* + EOpConvInt64ToFloat16, + EOpConvInt64ToFloat, + EOpConvInt64ToDouble, + + // uint64_t -> float* + EOpConvUint64ToFloat16, + EOpConvUint64ToFloat, + EOpConvUint64ToDouble, + + // float16_t -> (u)int* + EOpConvFloat16ToInt8, + EOpConvFloat16ToInt16, + EOpConvFloat16ToInt, + EOpConvFloat16ToInt64, + EOpConvFloat16ToUint8, + EOpConvFloat16ToUint16, + EOpConvFloat16ToUint, + EOpConvFloat16ToUint64, + + // float16_t -> float* + EOpConvFloat16ToFloat, + EOpConvFloat16ToDouble, + + // float -> (u)int* + EOpConvFloatToInt8, + EOpConvFloatToInt16, + EOpConvFloatToInt, + EOpConvFloatToInt64, + EOpConvFloatToUint8, + EOpConvFloatToUint16, + EOpConvFloatToUint, + EOpConvFloatToUint64, + + // float -> float* + EOpConvFloatToFloat16, + EOpConvFloatToDouble, + + // float64 _t-> (u)int* + EOpConvDoubleToInt8, + EOpConvDoubleToInt16, + EOpConvDoubleToInt, + EOpConvDoubleToInt64, + EOpConvDoubleToUint8, + EOpConvDoubleToUint16, + EOpConvDoubleToUint, + EOpConvDoubleToUint64, + + // float64_t -> float* + EOpConvDoubleToFloat16, + EOpConvDoubleToFloat, + + // uint64_t <-> pointer + EOpConvUint64ToPtr, + EOpConvPtrToUint64, + + // uvec2 <-> pointer + EOpConvUvec2ToPtr, + EOpConvPtrToUvec2, + + // + // binary operations + // + + EOpAdd, + EOpSub, + EOpMul, + EOpDiv, + EOpMod, + EOpRightShift, + EOpLeftShift, + EOpAnd, + EOpInclusiveOr, + EOpExclusiveOr, + EOpEqual, + EOpNotEqual, + EOpVectorEqual, + EOpVectorNotEqual, + EOpLessThan, + EOpGreaterThan, + EOpLessThanEqual, + EOpGreaterThanEqual, + EOpComma, + + EOpVectorTimesScalar, + EOpVectorTimesMatrix, + EOpMatrixTimesVector, + EOpMatrixTimesScalar, + + EOpLogicalOr, + EOpLogicalXor, + EOpLogicalAnd, + + EOpIndexDirect, + EOpIndexIndirect, + EOpIndexDirectStruct, + + EOpVectorSwizzle, + + EOpMethod, + EOpScoping, + + // + // Built-in functions mapped to operators + // + + EOpRadians, + EOpDegrees, + EOpSin, + EOpCos, + EOpTan, + EOpAsin, + EOpAcos, + EOpAtan, + EOpSinh, + EOpCosh, + EOpTanh, + EOpAsinh, + EOpAcosh, + EOpAtanh, + + EOpPow, + EOpExp, + EOpLog, + EOpExp2, + EOpLog2, + EOpSqrt, + EOpInverseSqrt, + + EOpAbs, + EOpSign, + EOpFloor, + EOpTrunc, + EOpRound, + EOpRoundEven, + EOpCeil, + EOpFract, + EOpModf, + EOpMin, + EOpMax, + EOpClamp, + EOpMix, + EOpStep, + EOpSmoothStep, + + EOpIsNan, + EOpIsInf, + + EOpFma, + + EOpFrexp, + EOpLdexp, + + EOpFloatBitsToInt, + EOpFloatBitsToUint, + EOpIntBitsToFloat, + EOpUintBitsToFloat, + EOpDoubleBitsToInt64, + EOpDoubleBitsToUint64, + EOpInt64BitsToDouble, + EOpUint64BitsToDouble, + EOpFloat16BitsToInt16, + EOpFloat16BitsToUint16, + EOpInt16BitsToFloat16, + EOpUint16BitsToFloat16, + EOpPackSnorm2x16, + EOpUnpackSnorm2x16, + EOpPackUnorm2x16, + EOpUnpackUnorm2x16, + EOpPackSnorm4x8, + EOpUnpackSnorm4x8, + EOpPackUnorm4x8, + EOpUnpackUnorm4x8, + EOpPackHalf2x16, + EOpUnpackHalf2x16, + EOpPackDouble2x32, + EOpUnpackDouble2x32, + EOpPackInt2x32, + EOpUnpackInt2x32, + EOpPackUint2x32, + EOpUnpackUint2x32, + EOpPackFloat2x16, + EOpUnpackFloat2x16, + EOpPackInt2x16, + EOpUnpackInt2x16, + EOpPackUint2x16, + EOpUnpackUint2x16, + EOpPackInt4x16, + EOpUnpackInt4x16, + EOpPackUint4x16, + EOpUnpackUint4x16, + EOpPack16, + EOpPack32, + EOpPack64, + EOpUnpack32, + EOpUnpack16, + EOpUnpack8, + + EOpLength, + EOpDistance, + EOpDot, + EOpCross, + EOpNormalize, + EOpFaceForward, + EOpReflect, + EOpRefract, + + EOpMin3, + EOpMax3, + EOpMid3, + + EOpDPdx, // Fragment only + EOpDPdy, // Fragment only + EOpFwidth, // Fragment only + EOpDPdxFine, // Fragment only + EOpDPdyFine, // Fragment only + EOpFwidthFine, // Fragment only + EOpDPdxCoarse, // Fragment only + EOpDPdyCoarse, // Fragment only + EOpFwidthCoarse, // Fragment only + + EOpInterpolateAtCentroid, // Fragment only + EOpInterpolateAtSample, // Fragment only + EOpInterpolateAtOffset, // Fragment only + EOpInterpolateAtVertex, + + EOpMatrixTimesMatrix, + EOpOuterProduct, + EOpDeterminant, + EOpMatrixInverse, + EOpTranspose, + + EOpFtransform, + + EOpNoise, + + EOpEmitVertex, // geometry only + EOpEndPrimitive, // geometry only + EOpEmitStreamVertex, // geometry only + EOpEndStreamPrimitive, // geometry only + + EOpBarrier, + EOpMemoryBarrier, + EOpMemoryBarrierAtomicCounter, + EOpMemoryBarrierBuffer, + EOpMemoryBarrierImage, + EOpMemoryBarrierShared, // compute only + EOpGroupMemoryBarrier, // compute only + + EOpBallot, + EOpReadInvocation, + EOpReadFirstInvocation, + + EOpAnyInvocation, + EOpAllInvocations, + EOpAllInvocationsEqual, + + EOpSubgroupGuardStart, + EOpSubgroupBarrier, + EOpSubgroupMemoryBarrier, + EOpSubgroupMemoryBarrierBuffer, + EOpSubgroupMemoryBarrierImage, + EOpSubgroupMemoryBarrierShared, // compute only + EOpSubgroupElect, + EOpSubgroupAll, + EOpSubgroupAny, + EOpSubgroupAllEqual, + EOpSubgroupBroadcast, + EOpSubgroupBroadcastFirst, + EOpSubgroupBallot, + EOpSubgroupInverseBallot, + EOpSubgroupBallotBitExtract, + EOpSubgroupBallotBitCount, + EOpSubgroupBallotInclusiveBitCount, + EOpSubgroupBallotExclusiveBitCount, + EOpSubgroupBallotFindLSB, + EOpSubgroupBallotFindMSB, + EOpSubgroupShuffle, + EOpSubgroupShuffleXor, + EOpSubgroupShuffleUp, + EOpSubgroupShuffleDown, + EOpSubgroupAdd, + EOpSubgroupMul, + EOpSubgroupMin, + EOpSubgroupMax, + EOpSubgroupAnd, + EOpSubgroupOr, + EOpSubgroupXor, + EOpSubgroupInclusiveAdd, + EOpSubgroupInclusiveMul, + EOpSubgroupInclusiveMin, + EOpSubgroupInclusiveMax, + EOpSubgroupInclusiveAnd, + EOpSubgroupInclusiveOr, + EOpSubgroupInclusiveXor, + EOpSubgroupExclusiveAdd, + EOpSubgroupExclusiveMul, + EOpSubgroupExclusiveMin, + EOpSubgroupExclusiveMax, + EOpSubgroupExclusiveAnd, + EOpSubgroupExclusiveOr, + EOpSubgroupExclusiveXor, + EOpSubgroupClusteredAdd, + EOpSubgroupClusteredMul, + EOpSubgroupClusteredMin, + EOpSubgroupClusteredMax, + EOpSubgroupClusteredAnd, + EOpSubgroupClusteredOr, + EOpSubgroupClusteredXor, + EOpSubgroupQuadBroadcast, + EOpSubgroupQuadSwapHorizontal, + EOpSubgroupQuadSwapVertical, + EOpSubgroupQuadSwapDiagonal, + + EOpSubgroupPartition, + EOpSubgroupPartitionedAdd, + EOpSubgroupPartitionedMul, + EOpSubgroupPartitionedMin, + EOpSubgroupPartitionedMax, + EOpSubgroupPartitionedAnd, + EOpSubgroupPartitionedOr, + EOpSubgroupPartitionedXor, + EOpSubgroupPartitionedInclusiveAdd, + EOpSubgroupPartitionedInclusiveMul, + EOpSubgroupPartitionedInclusiveMin, + EOpSubgroupPartitionedInclusiveMax, + EOpSubgroupPartitionedInclusiveAnd, + EOpSubgroupPartitionedInclusiveOr, + EOpSubgroupPartitionedInclusiveXor, + EOpSubgroupPartitionedExclusiveAdd, + EOpSubgroupPartitionedExclusiveMul, + EOpSubgroupPartitionedExclusiveMin, + EOpSubgroupPartitionedExclusiveMax, + EOpSubgroupPartitionedExclusiveAnd, + EOpSubgroupPartitionedExclusiveOr, + EOpSubgroupPartitionedExclusiveXor, + + EOpSubgroupGuardStop, + + EOpMinInvocations, + EOpMaxInvocations, + EOpAddInvocations, + EOpMinInvocationsNonUniform, + EOpMaxInvocationsNonUniform, + EOpAddInvocationsNonUniform, + EOpMinInvocationsInclusiveScan, + EOpMaxInvocationsInclusiveScan, + EOpAddInvocationsInclusiveScan, + EOpMinInvocationsInclusiveScanNonUniform, + EOpMaxInvocationsInclusiveScanNonUniform, + EOpAddInvocationsInclusiveScanNonUniform, + EOpMinInvocationsExclusiveScan, + EOpMaxInvocationsExclusiveScan, + EOpAddInvocationsExclusiveScan, + EOpMinInvocationsExclusiveScanNonUniform, + EOpMaxInvocationsExclusiveScanNonUniform, + EOpAddInvocationsExclusiveScanNonUniform, + EOpSwizzleInvocations, + EOpSwizzleInvocationsMasked, + EOpWriteInvocation, + EOpMbcnt, + + EOpCubeFaceIndex, + EOpCubeFaceCoord, + EOpTime, + + EOpAtomicAdd, + EOpAtomicMin, + EOpAtomicMax, + EOpAtomicAnd, + EOpAtomicOr, + EOpAtomicXor, + EOpAtomicExchange, + EOpAtomicCompSwap, + EOpAtomicLoad, + EOpAtomicStore, + + EOpAtomicCounterIncrement, // results in pre-increment value + EOpAtomicCounterDecrement, // results in post-decrement value + EOpAtomicCounter, + EOpAtomicCounterAdd, + EOpAtomicCounterSubtract, + EOpAtomicCounterMin, + EOpAtomicCounterMax, + EOpAtomicCounterAnd, + EOpAtomicCounterOr, + EOpAtomicCounterXor, + EOpAtomicCounterExchange, + EOpAtomicCounterCompSwap, + + EOpAny, + EOpAll, + + EOpCooperativeMatrixLoad, + EOpCooperativeMatrixStore, + EOpCooperativeMatrixMulAdd, + + EOpBeginInvocationInterlock, // Fragment only + EOpEndInvocationInterlock, // Fragment only + + EOpIsHelperInvocation, + + EOpDebugPrintf, + + // + // Branch + // + + EOpKill, // Fragment only + EOpReturn, + EOpBreak, + EOpContinue, + EOpCase, + EOpDefault, + EOpDemote, // Fragment only + + // + // Constructors + // + + EOpConstructGuardStart, + EOpConstructInt, // these first scalar forms also identify what implicit conversion is needed + EOpConstructUint, + EOpConstructInt8, + EOpConstructUint8, + EOpConstructInt16, + EOpConstructUint16, + EOpConstructInt64, + EOpConstructUint64, + EOpConstructBool, + EOpConstructFloat, + EOpConstructDouble, + // Keep vector and matrix constructors in a consistent relative order for + // TParseContext::constructBuiltIn, which converts between 8/16/32 bit + // vector constructors + EOpConstructVec2, + EOpConstructVec3, + EOpConstructVec4, + EOpConstructMat2x2, + EOpConstructMat2x3, + EOpConstructMat2x4, + EOpConstructMat3x2, + EOpConstructMat3x3, + EOpConstructMat3x4, + EOpConstructMat4x2, + EOpConstructMat4x3, + EOpConstructMat4x4, + EOpConstructDVec2, + EOpConstructDVec3, + EOpConstructDVec4, + EOpConstructBVec2, + EOpConstructBVec3, + EOpConstructBVec4, + EOpConstructI8Vec2, + EOpConstructI8Vec3, + EOpConstructI8Vec4, + EOpConstructU8Vec2, + EOpConstructU8Vec3, + EOpConstructU8Vec4, + EOpConstructI16Vec2, + EOpConstructI16Vec3, + EOpConstructI16Vec4, + EOpConstructU16Vec2, + EOpConstructU16Vec3, + EOpConstructU16Vec4, + EOpConstructIVec2, + EOpConstructIVec3, + EOpConstructIVec4, + EOpConstructUVec2, + EOpConstructUVec3, + EOpConstructUVec4, + EOpConstructI64Vec2, + EOpConstructI64Vec3, + EOpConstructI64Vec4, + EOpConstructU64Vec2, + EOpConstructU64Vec3, + EOpConstructU64Vec4, + EOpConstructDMat2x2, + EOpConstructDMat2x3, + EOpConstructDMat2x4, + EOpConstructDMat3x2, + EOpConstructDMat3x3, + EOpConstructDMat3x4, + EOpConstructDMat4x2, + EOpConstructDMat4x3, + EOpConstructDMat4x4, + EOpConstructIMat2x2, + EOpConstructIMat2x3, + EOpConstructIMat2x4, + EOpConstructIMat3x2, + EOpConstructIMat3x3, + EOpConstructIMat3x4, + EOpConstructIMat4x2, + EOpConstructIMat4x3, + EOpConstructIMat4x4, + EOpConstructUMat2x2, + EOpConstructUMat2x3, + EOpConstructUMat2x4, + EOpConstructUMat3x2, + EOpConstructUMat3x3, + EOpConstructUMat3x4, + EOpConstructUMat4x2, + EOpConstructUMat4x3, + EOpConstructUMat4x4, + EOpConstructBMat2x2, + EOpConstructBMat2x3, + EOpConstructBMat2x4, + EOpConstructBMat3x2, + EOpConstructBMat3x3, + EOpConstructBMat3x4, + EOpConstructBMat4x2, + EOpConstructBMat4x3, + EOpConstructBMat4x4, + EOpConstructFloat16, + EOpConstructF16Vec2, + EOpConstructF16Vec3, + EOpConstructF16Vec4, + EOpConstructF16Mat2x2, + EOpConstructF16Mat2x3, + EOpConstructF16Mat2x4, + EOpConstructF16Mat3x2, + EOpConstructF16Mat3x3, + EOpConstructF16Mat3x4, + EOpConstructF16Mat4x2, + EOpConstructF16Mat4x3, + EOpConstructF16Mat4x4, + EOpConstructStruct, + EOpConstructTextureSampler, + EOpConstructNonuniform, // expected to be transformed away, not present in final AST + EOpConstructReference, + EOpConstructCooperativeMatrix, + EOpConstructGuardEnd, + + // + // moves + // + + EOpAssign, + EOpAddAssign, + EOpSubAssign, + EOpMulAssign, + EOpVectorTimesMatrixAssign, + EOpVectorTimesScalarAssign, + EOpMatrixTimesScalarAssign, + EOpMatrixTimesMatrixAssign, + EOpDivAssign, + EOpModAssign, + EOpAndAssign, + EOpInclusiveOrAssign, + EOpExclusiveOrAssign, + EOpLeftShiftAssign, + EOpRightShiftAssign, + + // + // Array operators + // + + // Can apply to arrays, vectors, or matrices. + // Can be decomposed to a constant at compile time, but this does not always happen, + // due to link-time effects. So, consumer can expect either a link-time sized or + // run-time sized array. + EOpArrayLength, + + // + // Image operations + // + + EOpImageGuardBegin, + + EOpImageQuerySize, + EOpImageQuerySamples, + EOpImageLoad, + EOpImageStore, + EOpImageLoadLod, + EOpImageStoreLod, + EOpImageAtomicAdd, + EOpImageAtomicMin, + EOpImageAtomicMax, + EOpImageAtomicAnd, + EOpImageAtomicOr, + EOpImageAtomicXor, + EOpImageAtomicExchange, + EOpImageAtomicCompSwap, + EOpImageAtomicLoad, + EOpImageAtomicStore, + + EOpSubpassLoad, + EOpSubpassLoadMS, + EOpSparseImageLoad, + EOpSparseImageLoadLod, + + EOpImageGuardEnd, + + // + // Texture operations + // + + EOpTextureGuardBegin, + + EOpTextureQuerySize, + EOpTextureQueryLod, + EOpTextureQueryLevels, + EOpTextureQuerySamples, + + EOpSamplingGuardBegin, + + EOpTexture, + EOpTextureProj, + EOpTextureLod, + EOpTextureOffset, + EOpTextureFetch, + EOpTextureFetchOffset, + EOpTextureProjOffset, + EOpTextureLodOffset, + EOpTextureProjLod, + EOpTextureProjLodOffset, + EOpTextureGrad, + EOpTextureGradOffset, + EOpTextureProjGrad, + EOpTextureProjGradOffset, + EOpTextureGather, + EOpTextureGatherOffset, + EOpTextureGatherOffsets, + EOpTextureClamp, + EOpTextureOffsetClamp, + EOpTextureGradClamp, + EOpTextureGradOffsetClamp, + EOpTextureGatherLod, + EOpTextureGatherLodOffset, + EOpTextureGatherLodOffsets, + EOpFragmentMaskFetch, + EOpFragmentFetch, + + EOpSparseTextureGuardBegin, + + EOpSparseTexture, + EOpSparseTextureLod, + EOpSparseTextureOffset, + EOpSparseTextureFetch, + EOpSparseTextureFetchOffset, + EOpSparseTextureLodOffset, + EOpSparseTextureGrad, + EOpSparseTextureGradOffset, + EOpSparseTextureGather, + EOpSparseTextureGatherOffset, + EOpSparseTextureGatherOffsets, + EOpSparseTexelsResident, + EOpSparseTextureClamp, + EOpSparseTextureOffsetClamp, + EOpSparseTextureGradClamp, + EOpSparseTextureGradOffsetClamp, + EOpSparseTextureGatherLod, + EOpSparseTextureGatherLodOffset, + EOpSparseTextureGatherLodOffsets, + + EOpSparseTextureGuardEnd, + + EOpImageFootprintGuardBegin, + EOpImageSampleFootprintNV, + EOpImageSampleFootprintClampNV, + EOpImageSampleFootprintLodNV, + EOpImageSampleFootprintGradNV, + EOpImageSampleFootprintGradClampNV, + EOpImageFootprintGuardEnd, + EOpSamplingGuardEnd, + EOpTextureGuardEnd, + + // + // Integer operations + // + + EOpAddCarry, + EOpSubBorrow, + EOpUMulExtended, + EOpIMulExtended, + EOpBitfieldExtract, + EOpBitfieldInsert, + EOpBitFieldReverse, + EOpBitCount, + EOpFindLSB, + EOpFindMSB, + + EOpCountLeadingZeros, + EOpCountTrailingZeros, + EOpAbsDifference, + EOpAddSaturate, + EOpSubSaturate, + EOpAverage, + EOpAverageRounded, + EOpMul32x16, + + EOpTrace, + EOpReportIntersection, + EOpIgnoreIntersection, + EOpTerminateRay, + EOpExecuteCallable, + EOpWritePackedPrimitiveIndices4x8NV, + + // + // GL_EXT_ray_query operations + // + + EOpRayQueryInitialize, + EOpRayQueryTerminate, + EOpRayQueryGenerateIntersection, + EOpRayQueryConfirmIntersection, + EOpRayQueryProceed, + EOpRayQueryGetIntersectionType, + EOpRayQueryGetRayTMin, + EOpRayQueryGetRayFlags, + EOpRayQueryGetIntersectionT, + EOpRayQueryGetIntersectionInstanceCustomIndex, + EOpRayQueryGetIntersectionInstanceId, + EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset, + EOpRayQueryGetIntersectionGeometryIndex, + EOpRayQueryGetIntersectionPrimitiveIndex, + EOpRayQueryGetIntersectionBarycentrics, + EOpRayQueryGetIntersectionFrontFace, + EOpRayQueryGetIntersectionCandidateAABBOpaque, + EOpRayQueryGetIntersectionObjectRayDirection, + EOpRayQueryGetIntersectionObjectRayOrigin, + EOpRayQueryGetWorldRayDirection, + EOpRayQueryGetWorldRayOrigin, + EOpRayQueryGetIntersectionObjectToWorld, + EOpRayQueryGetIntersectionWorldToObject, + + // + // HLSL operations + // + + EOpClip, // discard if input value < 0 + EOpIsFinite, + EOpLog10, // base 10 log + EOpRcp, // 1/x + EOpSaturate, // clamp from 0 to 1 + EOpSinCos, // sin and cos in out parameters + EOpGenMul, // mul(x,y) on any of mat/vec/scalars + EOpDst, // x = 1, y=src0.y * src1.y, z=src0.z, w=src1.w + EOpInterlockedAdd, // atomic ops, but uses [optional] out arg instead of return + EOpInterlockedAnd, // ... + EOpInterlockedCompareExchange, // ... + EOpInterlockedCompareStore, // ... + EOpInterlockedExchange, // ... + EOpInterlockedMax, // ... + EOpInterlockedMin, // ... + EOpInterlockedOr, // ... + EOpInterlockedXor, // ... + EOpAllMemoryBarrierWithGroupSync, // memory barriers without non-hlsl AST equivalents + EOpDeviceMemoryBarrier, // ... + EOpDeviceMemoryBarrierWithGroupSync, // ... + EOpWorkgroupMemoryBarrier, // ... + EOpWorkgroupMemoryBarrierWithGroupSync, // ... + EOpEvaluateAttributeSnapped, // InterpolateAtOffset with int position on 16x16 grid + EOpF32tof16, // HLSL conversion: half of a PackHalf2x16 + EOpF16tof32, // HLSL conversion: half of an UnpackHalf2x16 + EOpLit, // HLSL lighting coefficient vector + EOpTextureBias, // HLSL texture bias: will be lowered to EOpTexture + EOpAsDouble, // slightly different from EOpUint64BitsToDouble + EOpD3DCOLORtoUBYTE4, // convert and swizzle 4-component color to UBYTE4 range + + EOpMethodSample, // Texture object methods. These are translated to existing + EOpMethodSampleBias, // AST methods, and exist to represent HLSL semantics until that + EOpMethodSampleCmp, // translation is performed. See HlslParseContext::decomposeSampleMethods(). + EOpMethodSampleCmpLevelZero, // ... + EOpMethodSampleGrad, // ... + EOpMethodSampleLevel, // ... + EOpMethodLoad, // ... + EOpMethodGetDimensions, // ... + EOpMethodGetSamplePosition, // ... + EOpMethodGather, // ... + EOpMethodCalculateLevelOfDetail, // ... + EOpMethodCalculateLevelOfDetailUnclamped, // ... + + // Load already defined above for textures + EOpMethodLoad2, // Structure buffer object methods. These are translated to existing + EOpMethodLoad3, // AST methods, and exist to represent HLSL semantics until that + EOpMethodLoad4, // translation is performed. See HlslParseContext::decomposeSampleMethods(). + EOpMethodStore, // ... + EOpMethodStore2, // ... + EOpMethodStore3, // ... + EOpMethodStore4, // ... + EOpMethodIncrementCounter, // ... + EOpMethodDecrementCounter, // ... + // EOpMethodAppend is defined for geo shaders below + EOpMethodConsume, + + // SM5 texture methods + EOpMethodGatherRed, // These are covered under the above EOpMethodSample comment about + EOpMethodGatherGreen, // translation to existing AST opcodes. They exist temporarily + EOpMethodGatherBlue, // because HLSL arguments are slightly different. + EOpMethodGatherAlpha, // ... + EOpMethodGatherCmp, // ... + EOpMethodGatherCmpRed, // ... + EOpMethodGatherCmpGreen, // ... + EOpMethodGatherCmpBlue, // ... + EOpMethodGatherCmpAlpha, // ... + + // geometry methods + EOpMethodAppend, // Geometry shader methods + EOpMethodRestartStrip, // ... + + // matrix + EOpMatrixSwizzle, // select multiple matrix components (non-column) + + // SM6 wave ops + EOpWaveGetLaneCount, // Will decompose to gl_SubgroupSize. + EOpWaveGetLaneIndex, // Will decompose to gl_SubgroupInvocationID. + EOpWaveActiveCountBits, // Will decompose to subgroupBallotBitCount(subgroupBallot()). + EOpWavePrefixCountBits, // Will decompose to subgroupBallotInclusiveBitCount(subgroupBallot()). + + // Shader Clock Ops + EOpReadClockSubgroupKHR, + EOpReadClockDeviceKHR, +}; + +class TIntermTraverser; +class TIntermOperator; +class TIntermAggregate; +class TIntermUnary; +class TIntermBinary; +class TIntermConstantUnion; +class TIntermSelection; +class TIntermSwitch; +class TIntermBranch; +class TIntermTyped; +class TIntermMethod; +class TIntermSymbol; +class TIntermLoop; + +} // end namespace glslang + +// +// Base class for the tree nodes +// +// (Put outside the glslang namespace, as it's used as part of the external interface.) +// +class TIntermNode { +public: + POOL_ALLOCATOR_NEW_DELETE(glslang::GetThreadPoolAllocator()) + + TIntermNode() { loc.init(); } + virtual const glslang::TSourceLoc& getLoc() const { return loc; } + virtual void setLoc(const glslang::TSourceLoc& l) { loc = l; } + virtual void traverse(glslang::TIntermTraverser*) = 0; + virtual glslang::TIntermTyped* getAsTyped() { return 0; } + virtual glslang::TIntermOperator* getAsOperator() { return 0; } + virtual glslang::TIntermConstantUnion* getAsConstantUnion() { return 0; } + virtual glslang::TIntermAggregate* getAsAggregate() { return 0; } + virtual glslang::TIntermUnary* getAsUnaryNode() { return 0; } + virtual glslang::TIntermBinary* getAsBinaryNode() { return 0; } + virtual glslang::TIntermSelection* getAsSelectionNode() { return 0; } + virtual glslang::TIntermSwitch* getAsSwitchNode() { return 0; } + virtual glslang::TIntermMethod* getAsMethodNode() { return 0; } + virtual glslang::TIntermSymbol* getAsSymbolNode() { return 0; } + virtual glslang::TIntermBranch* getAsBranchNode() { return 0; } + virtual glslang::TIntermLoop* getAsLoopNode() { return 0; } + + virtual const glslang::TIntermTyped* getAsTyped() const { return 0; } + virtual const glslang::TIntermOperator* getAsOperator() const { return 0; } + virtual const glslang::TIntermConstantUnion* getAsConstantUnion() const { return 0; } + virtual const glslang::TIntermAggregate* getAsAggregate() const { return 0; } + virtual const glslang::TIntermUnary* getAsUnaryNode() const { return 0; } + virtual const glslang::TIntermBinary* getAsBinaryNode() const { return 0; } + virtual const glslang::TIntermSelection* getAsSelectionNode() const { return 0; } + virtual const glslang::TIntermSwitch* getAsSwitchNode() const { return 0; } + virtual const glslang::TIntermMethod* getAsMethodNode() const { return 0; } + virtual const glslang::TIntermSymbol* getAsSymbolNode() const { return 0; } + virtual const glslang::TIntermBranch* getAsBranchNode() const { return 0; } + virtual const glslang::TIntermLoop* getAsLoopNode() const { return 0; } + virtual ~TIntermNode() { } + +protected: + TIntermNode(const TIntermNode&); + TIntermNode& operator=(const TIntermNode&); + glslang::TSourceLoc loc; +}; + +namespace glslang { + +// +// This is just to help yacc. +// +struct TIntermNodePair { + TIntermNode* node1; + TIntermNode* node2; +}; + +// +// Intermediate class for nodes that have a type. +// +class TIntermTyped : public TIntermNode { +public: + TIntermTyped(const TType& t) { type.shallowCopy(t); } + TIntermTyped(TBasicType basicType) { TType bt(basicType); type.shallowCopy(bt); } + virtual TIntermTyped* getAsTyped() { return this; } + virtual const TIntermTyped* getAsTyped() const { return this; } + virtual void setType(const TType& t) { type.shallowCopy(t); } + virtual const TType& getType() const { return type; } + virtual TType& getWritableType() { return type; } + + virtual TBasicType getBasicType() const { return type.getBasicType(); } + virtual TQualifier& getQualifier() { return type.getQualifier(); } + virtual const TQualifier& getQualifier() const { return type.getQualifier(); } + virtual void propagatePrecision(TPrecisionQualifier); + virtual int getVectorSize() const { return type.getVectorSize(); } + virtual int getMatrixCols() const { return type.getMatrixCols(); } + virtual int getMatrixRows() const { return type.getMatrixRows(); } + virtual bool isMatrix() const { return type.isMatrix(); } + virtual bool isArray() const { return type.isArray(); } + virtual bool isVector() const { return type.isVector(); } + virtual bool isScalar() const { return type.isScalar(); } + virtual bool isStruct() const { return type.isStruct(); } + virtual bool isFloatingDomain() const { return type.isFloatingDomain(); } + virtual bool isIntegerDomain() const { return type.isIntegerDomain(); } + bool isAtomic() const { return type.isAtomic(); } + bool isReference() const { return type.isReference(); } + TString getCompleteString() const { return type.getCompleteString(); } + +protected: + TIntermTyped& operator=(const TIntermTyped&); + TType type; +}; + +// +// Handle for, do-while, and while loops. +// +class TIntermLoop : public TIntermNode { +public: + TIntermLoop(TIntermNode* aBody, TIntermTyped* aTest, TIntermTyped* aTerminal, bool testFirst) : + body(aBody), + test(aTest), + terminal(aTerminal), + first(testFirst), + unroll(false), + dontUnroll(false), + dependency(0), + minIterations(0), + maxIterations(iterationsInfinite), + iterationMultiple(1), + peelCount(0), + partialCount(0) + { } + + virtual TIntermLoop* getAsLoopNode() { return this; } + virtual const TIntermLoop* getAsLoopNode() const { return this; } + virtual void traverse(TIntermTraverser*); + TIntermNode* getBody() const { return body; } + TIntermTyped* getTest() const { return test; } + TIntermTyped* getTerminal() const { return terminal; } + bool testFirst() const { return first; } + + void setUnroll() { unroll = true; } + void setDontUnroll() { + dontUnroll = true; + peelCount = 0; + partialCount = 0; + } + bool getUnroll() const { return unroll; } + bool getDontUnroll() const { return dontUnroll; } + + static const unsigned int dependencyInfinite = 0xFFFFFFFF; + static const unsigned int iterationsInfinite = 0xFFFFFFFF; + void setLoopDependency(int d) { dependency = d; } + int getLoopDependency() const { return dependency; } + + void setMinIterations(unsigned int v) { minIterations = v; } + unsigned int getMinIterations() const { return minIterations; } + void setMaxIterations(unsigned int v) { maxIterations = v; } + unsigned int getMaxIterations() const { return maxIterations; } + void setIterationMultiple(unsigned int v) { iterationMultiple = v; } + unsigned int getIterationMultiple() const { return iterationMultiple; } + void setPeelCount(unsigned int v) { + peelCount = v; + dontUnroll = false; + } + unsigned int getPeelCount() const { return peelCount; } + void setPartialCount(unsigned int v) { + partialCount = v; + dontUnroll = false; + } + unsigned int getPartialCount() const { return partialCount; } + +protected: + TIntermNode* body; // code to loop over + TIntermTyped* test; // exit condition associated with loop, could be 0 for 'for' loops + TIntermTyped* terminal; // exists for for-loops + bool first; // true for while and for, not for do-while + bool unroll; // true if unroll requested + bool dontUnroll; // true if request to not unroll + unsigned int dependency; // loop dependency hint; 0 means not set or unknown + unsigned int minIterations; // as per the SPIR-V specification + unsigned int maxIterations; // as per the SPIR-V specification + unsigned int iterationMultiple; // as per the SPIR-V specification + unsigned int peelCount; // as per the SPIR-V specification + unsigned int partialCount; // as per the SPIR-V specification +}; + +// +// Handle case, break, continue, return, and kill. +// +class TIntermBranch : public TIntermNode { +public: + TIntermBranch(TOperator op, TIntermTyped* e) : + flowOp(op), + expression(e) { } + virtual TIntermBranch* getAsBranchNode() { return this; } + virtual const TIntermBranch* getAsBranchNode() const { return this; } + virtual void traverse(TIntermTraverser*); + TOperator getFlowOp() const { return flowOp; } + TIntermTyped* getExpression() const { return expression; } + void setExpression(TIntermTyped* pExpression) { expression = pExpression; } +protected: + TOperator flowOp; + TIntermTyped* expression; +}; + +// +// Represent method names before seeing their calling signature +// or resolving them to operations. Just an expression as the base object +// and a textural name. +// +class TIntermMethod : public TIntermTyped { +public: + TIntermMethod(TIntermTyped* o, const TType& t, const TString& m) : TIntermTyped(t), object(o), method(m) { } + virtual TIntermMethod* getAsMethodNode() { return this; } + virtual const TIntermMethod* getAsMethodNode() const { return this; } + virtual const TString& getMethodName() const { return method; } + virtual TIntermTyped* getObject() const { return object; } + virtual void traverse(TIntermTraverser*); +protected: + TIntermTyped* object; + TString method; +}; + +// +// Nodes that correspond to symbols or constants in the source code. +// +class TIntermSymbol : public TIntermTyped { +public: + // if symbol is initialized as symbol(sym), the memory comes from the pool allocator of sym. If sym comes from + // per process threadPoolAllocator, then it causes increased memory usage per compile + // it is essential to use "symbol = sym" to assign to symbol + TIntermSymbol(int i, const TString& n, const TType& t) + : TIntermTyped(t), id(i), +#ifndef GLSLANG_WEB + flattenSubset(-1), +#endif + constSubtree(nullptr) + { name = n; } + virtual int getId() const { return id; } + virtual void changeId(int i) { id = i; } + virtual const TString& getName() const { return name; } + virtual void traverse(TIntermTraverser*); + virtual TIntermSymbol* getAsSymbolNode() { return this; } + virtual const TIntermSymbol* getAsSymbolNode() const { return this; } + void setConstArray(const TConstUnionArray& c) { constArray = c; } + const TConstUnionArray& getConstArray() const { return constArray; } + void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; } + TIntermTyped* getConstSubtree() const { return constSubtree; } +#ifndef GLSLANG_WEB + void setFlattenSubset(int subset) { flattenSubset = subset; } + int getFlattenSubset() const { return flattenSubset; } // -1 means full object +#endif + + // This is meant for cases where a node has already been constructed, and + // later on, it becomes necessary to switch to a different symbol. + virtual void switchId(int newId) { id = newId; } + +protected: + int id; // the unique id of the symbol this node represents +#ifndef GLSLANG_WEB + int flattenSubset; // how deeply the flattened object rooted at id has been dereferenced +#endif + TString name; // the name of the symbol this node represents + TConstUnionArray constArray; // if the symbol is a front-end compile-time constant, this is its value + TIntermTyped* constSubtree; +}; + +class TIntermConstantUnion : public TIntermTyped { +public: + TIntermConstantUnion(const TConstUnionArray& ua, const TType& t) : TIntermTyped(t), constArray(ua), literal(false) { } + const TConstUnionArray& getConstArray() const { return constArray; } + virtual TIntermConstantUnion* getAsConstantUnion() { return this; } + virtual const TIntermConstantUnion* getAsConstantUnion() const { return this; } + virtual void traverse(TIntermTraverser*); + virtual TIntermTyped* fold(TOperator, const TIntermTyped*) const; + virtual TIntermTyped* fold(TOperator, const TType&) const; + void setLiteral() { literal = true; } + void setExpression() { literal = false; } + bool isLiteral() const { return literal; } + +protected: + TIntermConstantUnion& operator=(const TIntermConstantUnion&); + + const TConstUnionArray constArray; + bool literal; // true if node represents a literal in the source code +}; + +// Represent the independent aspects of a texturing TOperator +struct TCrackedTextureOp { + bool query; + bool proj; + bool lod; + bool fetch; + bool offset; + bool offsets; + bool gather; + bool grad; + bool subpass; + bool lodClamp; + bool fragMask; +}; + +// +// Intermediate class for node types that hold operators. +// +class TIntermOperator : public TIntermTyped { +public: + virtual TIntermOperator* getAsOperator() { return this; } + virtual const TIntermOperator* getAsOperator() const { return this; } + TOperator getOp() const { return op; } + void setOp(TOperator newOp) { op = newOp; } + bool modifiesState() const; + bool isConstructor() const; + bool isTexture() const { return op > EOpTextureGuardBegin && op < EOpTextureGuardEnd; } + bool isSampling() const { return op > EOpSamplingGuardBegin && op < EOpSamplingGuardEnd; } +#ifdef GLSLANG_WEB + bool isImage() const { return false; } + bool isSparseTexture() const { return false; } + bool isImageFootprint() const { return false; } + bool isSparseImage() const { return false; } + bool isSubgroup() const { return false; } +#else + bool isImage() const { return op > EOpImageGuardBegin && op < EOpImageGuardEnd; } + bool isSparseTexture() const { return op > EOpSparseTextureGuardBegin && op < EOpSparseTextureGuardEnd; } + bool isImageFootprint() const { return op > EOpImageFootprintGuardBegin && op < EOpImageFootprintGuardEnd; } + bool isSparseImage() const { return op == EOpSparseImageLoad; } + bool isSubgroup() const { return op > EOpSubgroupGuardStart && op < EOpSubgroupGuardStop; } +#endif + + void setOperationPrecision(TPrecisionQualifier p) { operationPrecision = p; } + TPrecisionQualifier getOperationPrecision() const { return operationPrecision != EpqNone ? + operationPrecision : + type.getQualifier().precision; } + TString getCompleteString() const + { + TString cs = type.getCompleteString(); + if (getOperationPrecision() != type.getQualifier().precision) { + cs += ", operation at "; + cs += GetPrecisionQualifierString(getOperationPrecision()); + } + + return cs; + } + + // Crack the op into the individual dimensions of texturing operation. + void crackTexture(TSampler sampler, TCrackedTextureOp& cracked) const + { + cracked.query = false; + cracked.proj = false; + cracked.lod = false; + cracked.fetch = false; + cracked.offset = false; + cracked.offsets = false; + cracked.gather = false; + cracked.grad = false; + cracked.subpass = false; + cracked.lodClamp = false; + cracked.fragMask = false; + + switch (op) { + case EOpImageQuerySize: + case EOpImageQuerySamples: + case EOpTextureQuerySize: + case EOpTextureQueryLod: + case EOpTextureQueryLevels: + case EOpTextureQuerySamples: + case EOpSparseTexelsResident: + cracked.query = true; + break; + case EOpTexture: + case EOpSparseTexture: + break; + case EOpTextureProj: + cracked.proj = true; + break; + case EOpTextureLod: + case EOpSparseTextureLod: + cracked.lod = true; + break; + case EOpTextureOffset: + case EOpSparseTextureOffset: + cracked.offset = true; + break; + case EOpTextureFetch: + case EOpSparseTextureFetch: + cracked.fetch = true; + if (sampler.is1D() || (sampler.dim == Esd2D && ! sampler.isMultiSample()) || sampler.dim == Esd3D) + cracked.lod = true; + break; + case EOpTextureFetchOffset: + case EOpSparseTextureFetchOffset: + cracked.fetch = true; + cracked.offset = true; + if (sampler.is1D() || (sampler.dim == Esd2D && ! sampler.isMultiSample()) || sampler.dim == Esd3D) + cracked.lod = true; + break; + case EOpTextureProjOffset: + cracked.offset = true; + cracked.proj = true; + break; + case EOpTextureLodOffset: + case EOpSparseTextureLodOffset: + cracked.offset = true; + cracked.lod = true; + break; + case EOpTextureProjLod: + cracked.lod = true; + cracked.proj = true; + break; + case EOpTextureProjLodOffset: + cracked.offset = true; + cracked.lod = true; + cracked.proj = true; + break; + case EOpTextureGrad: + case EOpSparseTextureGrad: + cracked.grad = true; + break; + case EOpTextureGradOffset: + case EOpSparseTextureGradOffset: + cracked.grad = true; + cracked.offset = true; + break; + case EOpTextureProjGrad: + cracked.grad = true; + cracked.proj = true; + break; + case EOpTextureProjGradOffset: + cracked.grad = true; + cracked.offset = true; + cracked.proj = true; + break; +#ifndef GLSLANG_WEB + case EOpTextureClamp: + case EOpSparseTextureClamp: + cracked.lodClamp = true; + break; + case EOpTextureOffsetClamp: + case EOpSparseTextureOffsetClamp: + cracked.offset = true; + cracked.lodClamp = true; + break; + case EOpTextureGradClamp: + case EOpSparseTextureGradClamp: + cracked.grad = true; + cracked.lodClamp = true; + break; + case EOpTextureGradOffsetClamp: + case EOpSparseTextureGradOffsetClamp: + cracked.grad = true; + cracked.offset = true; + cracked.lodClamp = true; + break; + case EOpTextureGather: + case EOpSparseTextureGather: + cracked.gather = true; + break; + case EOpTextureGatherOffset: + case EOpSparseTextureGatherOffset: + cracked.gather = true; + cracked.offset = true; + break; + case EOpTextureGatherOffsets: + case EOpSparseTextureGatherOffsets: + cracked.gather = true; + cracked.offsets = true; + break; + case EOpTextureGatherLod: + case EOpSparseTextureGatherLod: + cracked.gather = true; + cracked.lod = true; + break; + case EOpTextureGatherLodOffset: + case EOpSparseTextureGatherLodOffset: + cracked.gather = true; + cracked.offset = true; + cracked.lod = true; + break; + case EOpTextureGatherLodOffsets: + case EOpSparseTextureGatherLodOffsets: + cracked.gather = true; + cracked.offsets = true; + cracked.lod = true; + break; + case EOpImageLoadLod: + case EOpImageStoreLod: + case EOpSparseImageLoadLod: + cracked.lod = true; + break; + case EOpFragmentMaskFetch: + cracked.subpass = sampler.dim == EsdSubpass; + cracked.fragMask = true; + break; + case EOpFragmentFetch: + cracked.subpass = sampler.dim == EsdSubpass; + cracked.fragMask = true; + break; + case EOpImageSampleFootprintNV: + break; + case EOpImageSampleFootprintClampNV: + cracked.lodClamp = true; + break; + case EOpImageSampleFootprintLodNV: + cracked.lod = true; + break; + case EOpImageSampleFootprintGradNV: + cracked.grad = true; + break; + case EOpImageSampleFootprintGradClampNV: + cracked.lodClamp = true; + cracked.grad = true; + break; + case EOpSubpassLoad: + case EOpSubpassLoadMS: + cracked.subpass = true; + break; +#endif + default: + break; + } + } + +protected: + TIntermOperator(TOperator o) : TIntermTyped(EbtFloat), op(o), operationPrecision(EpqNone) {} + TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o), operationPrecision(EpqNone) {} + TOperator op; + // The result precision is in the inherited TType, and is usually meant to be both + // the operation precision and the result precision. However, some more complex things, + // like built-in function calls, distinguish between the two, in which case non-EqpNone + // 'operationPrecision' overrides the result precision as far as operation precision + // is concerned. + TPrecisionQualifier operationPrecision; +}; + +// +// Nodes for all the basic binary math operators. +// +class TIntermBinary : public TIntermOperator { +public: + TIntermBinary(TOperator o) : TIntermOperator(o) {} + virtual void traverse(TIntermTraverser*); + virtual void setLeft(TIntermTyped* n) { left = n; } + virtual void setRight(TIntermTyped* n) { right = n; } + virtual TIntermTyped* getLeft() const { return left; } + virtual TIntermTyped* getRight() const { return right; } + virtual TIntermBinary* getAsBinaryNode() { return this; } + virtual const TIntermBinary* getAsBinaryNode() const { return this; } + virtual void updatePrecision(); +protected: + TIntermTyped* left; + TIntermTyped* right; +}; + +// +// Nodes for unary math operators. +// +class TIntermUnary : public TIntermOperator { +public: + TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {} + TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {} + virtual void traverse(TIntermTraverser*); + virtual void setOperand(TIntermTyped* o) { operand = o; } + virtual TIntermTyped* getOperand() { return operand; } + virtual const TIntermTyped* getOperand() const { return operand; } + virtual TIntermUnary* getAsUnaryNode() { return this; } + virtual const TIntermUnary* getAsUnaryNode() const { return this; } + virtual void updatePrecision(); +protected: + TIntermTyped* operand; +}; + +typedef TVector TIntermSequence; +typedef TVector TQualifierList; +// +// Nodes that operate on an arbitrary sized set of children. +// +class TIntermAggregate : public TIntermOperator { +public: + TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(nullptr) { } + TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(nullptr) { } + ~TIntermAggregate() { delete pragmaTable; } + virtual TIntermAggregate* getAsAggregate() { return this; } + virtual const TIntermAggregate* getAsAggregate() const { return this; } + virtual void setOperator(TOperator o) { op = o; } + virtual TIntermSequence& getSequence() { return sequence; } + virtual const TIntermSequence& getSequence() const { return sequence; } + virtual void setName(const TString& n) { name = n; } + virtual const TString& getName() const { return name; } + virtual void traverse(TIntermTraverser*); + virtual void setUserDefined() { userDefined = true; } + virtual bool isUserDefined() { return userDefined; } + virtual TQualifierList& getQualifierList() { return qualifier; } + virtual const TQualifierList& getQualifierList() const { return qualifier; } + void setOptimize(bool o) { optimize = o; } + void setDebug(bool d) { debug = d; } + bool getOptimize() const { return optimize; } + bool getDebug() const { return debug; } + void setPragmaTable(const TPragmaTable& pTable); + const TPragmaTable& getPragmaTable() const { return *pragmaTable; } +protected: + TIntermAggregate(const TIntermAggregate&); // disallow copy constructor + TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator + TIntermSequence sequence; + TQualifierList qualifier; + TString name; + bool userDefined; // used for user defined function names + bool optimize; + bool debug; + TPragmaTable* pragmaTable; +}; + +// +// For if tests. +// +class TIntermSelection : public TIntermTyped { +public: + TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) : + TIntermTyped(EbtVoid), condition(cond), trueBlock(trueB), falseBlock(falseB), + shortCircuit(true), + flatten(false), dontFlatten(false) {} + TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) : + TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB), + shortCircuit(true), + flatten(false), dontFlatten(false) {} + virtual void traverse(TIntermTraverser*); + virtual TIntermTyped* getCondition() const { return condition; } + virtual TIntermNode* getTrueBlock() const { return trueBlock; } + virtual TIntermNode* getFalseBlock() const { return falseBlock; } + virtual TIntermSelection* getAsSelectionNode() { return this; } + virtual const TIntermSelection* getAsSelectionNode() const { return this; } + + void setNoShortCircuit() { shortCircuit = false; } + bool getShortCircuit() const { return shortCircuit; } + + void setFlatten() { flatten = true; } + void setDontFlatten() { dontFlatten = true; } + bool getFlatten() const { return flatten; } + bool getDontFlatten() const { return dontFlatten; } + +protected: + TIntermTyped* condition; + TIntermNode* trueBlock; + TIntermNode* falseBlock; + bool shortCircuit; // normally all if-then-else and all GLSL ?: short-circuit, but HLSL ?: does not + bool flatten; // true if flatten requested + bool dontFlatten; // true if requested to not flatten +}; + +// +// For switch statements. Designed use is that a switch will have sequence of nodes +// that are either case/default nodes or a *single* node that represents all the code +// in between (if any) consecutive case/defaults. So, a traversal need only deal with +// 0 or 1 nodes per case/default statement. +// +class TIntermSwitch : public TIntermNode { +public: + TIntermSwitch(TIntermTyped* cond, TIntermAggregate* b) : condition(cond), body(b), + flatten(false), dontFlatten(false) {} + virtual void traverse(TIntermTraverser*); + virtual TIntermNode* getCondition() const { return condition; } + virtual TIntermAggregate* getBody() const { return body; } + virtual TIntermSwitch* getAsSwitchNode() { return this; } + virtual const TIntermSwitch* getAsSwitchNode() const { return this; } + + void setFlatten() { flatten = true; } + void setDontFlatten() { dontFlatten = true; } + bool getFlatten() const { return flatten; } + bool getDontFlatten() const { return dontFlatten; } + +protected: + TIntermTyped* condition; + TIntermAggregate* body; + bool flatten; // true if flatten requested + bool dontFlatten; // true if requested to not flatten +}; + +enum TVisit +{ + EvPreVisit, + EvInVisit, + EvPostVisit +}; + +// +// For traversing the tree. User should derive from this, +// put their traversal specific data in it, and then pass +// it to a Traverse method. +// +// When using this, just fill in the methods for nodes you want visited. +// Return false from a pre-visit to skip visiting that node's subtree. +// +// Explicitly set postVisit to true if you want post visiting, otherwise, +// filled in methods will only be called at pre-visit time (before processing +// the subtree). Similarly for inVisit for in-order visiting of nodes with +// multiple children. +// +// If you only want post-visits, explicitly turn off preVisit (and inVisit) +// and turn on postVisit. +// +// In general, for the visit*() methods, return true from interior nodes +// to have the traversal continue on to children. +// +// If you process children yourself, or don't want them processed, return false. +// +class TIntermTraverser { +public: + POOL_ALLOCATOR_NEW_DELETE(glslang::GetThreadPoolAllocator()) + TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) : + preVisit(preVisit), + inVisit(inVisit), + postVisit(postVisit), + rightToLeft(rightToLeft), + depth(0), + maxDepth(0) { } + virtual ~TIntermTraverser() { } + + virtual void visitSymbol(TIntermSymbol*) { } + virtual void visitConstantUnion(TIntermConstantUnion*) { } + virtual bool visitBinary(TVisit, TIntermBinary*) { return true; } + virtual bool visitUnary(TVisit, TIntermUnary*) { return true; } + virtual bool visitSelection(TVisit, TIntermSelection*) { return true; } + virtual bool visitAggregate(TVisit, TIntermAggregate*) { return true; } + virtual bool visitLoop(TVisit, TIntermLoop*) { return true; } + virtual bool visitBranch(TVisit, TIntermBranch*) { return true; } + virtual bool visitSwitch(TVisit, TIntermSwitch*) { return true; } + + int getMaxDepth() const { return maxDepth; } + + void incrementDepth(TIntermNode *current) + { + depth++; + maxDepth = (std::max)(maxDepth, depth); + path.push_back(current); + } + + void decrementDepth() + { + depth--; + path.pop_back(); + } + + TIntermNode *getParentNode() + { + return path.size() == 0 ? NULL : path.back(); + } + + const bool preVisit; + const bool inVisit; + const bool postVisit; + const bool rightToLeft; + +protected: + TIntermTraverser& operator=(TIntermTraverser&); + + int depth; + int maxDepth; + + // All the nodes from root to the current node's parent during traversing. + TVector path; +}; + +// KHR_vulkan_glsl says "Two arrays sized with specialization constants are the same type only if +// sized with the same symbol, involving no operations" +inline bool SameSpecializationConstants(TIntermTyped* node1, TIntermTyped* node2) +{ + return node1->getAsSymbolNode() && node2->getAsSymbolNode() && + node1->getAsSymbolNode()->getId() == node2->getAsSymbolNode()->getId(); +} + +} // end namespace glslang + +#endif // __INTERMEDIATE_H diff --git a/android/x86/include/glslang/Include/revision.h b/android/x86/include/glslang/Include/revision.h new file mode 100644 index 00000000..744c2fb4 --- /dev/null +++ b/android/x86/include/glslang/Include/revision.h @@ -0,0 +1,3 @@ +// This header is generated by the make-revision script. + +#define GLSLANG_PATCH_LEVEL 3743 diff --git a/android/x86/include/glslang/MachineIndependent/Initialize.h b/android/x86/include/glslang/MachineIndependent/Initialize.h new file mode 100644 index 00000000..ac8ec33e --- /dev/null +++ b/android/x86/include/glslang/MachineIndependent/Initialize.h @@ -0,0 +1,112 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013-2016 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _INITIALIZE_INCLUDED_ +#define _INITIALIZE_INCLUDED_ + +#include "../Include/ResourceLimits.h" +#include "../Include/Common.h" +#include "../Include/ShHandle.h" +#include "SymbolTable.h" +#include "Versions.h" + +namespace glslang { + +// +// This is made to hold parseable strings for almost all the built-in +// functions and variables for one specific combination of version +// and profile. (Some still need to be added programmatically.) +// This is a base class for language-specific derivations, which +// can be used for language independent builtins. +// +// The strings are organized by +// commonBuiltins: intersection of all stages' built-ins, processed just once +// stageBuiltins[]: anything a stage needs that's not in commonBuiltins +// +class TBuiltInParseables { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + TBuiltInParseables(); + virtual ~TBuiltInParseables(); + virtual void initialize(int version, EProfile, const SpvVersion& spvVersion) = 0; + virtual void initialize(const TBuiltInResource& resources, int version, EProfile, const SpvVersion& spvVersion, EShLanguage) = 0; + virtual const TString& getCommonString() const { return commonBuiltins; } + virtual const TString& getStageString(EShLanguage language) const { return stageBuiltins[language]; } + + virtual void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable) = 0; + virtual void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources) = 0; + +protected: + TString commonBuiltins; + TString stageBuiltins[EShLangCount]; +}; + +// +// This is a GLSL specific derivation of TBuiltInParseables. To present a stable +// interface and match other similar code, it is called TBuiltIns, rather +// than TBuiltInParseablesGlsl. +// +class TBuiltIns : public TBuiltInParseables { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + TBuiltIns(); + virtual ~TBuiltIns(); + void initialize(int version, EProfile, const SpvVersion& spvVersion); + void initialize(const TBuiltInResource& resources, int version, EProfile, const SpvVersion& spvVersion, EShLanguage); + + void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable); + void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources); + +protected: + void addTabledBuiltins(int version, EProfile profile, const SpvVersion& spvVersion); + void relateTabledBuiltins(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage, TSymbolTable&); + void add2ndGenerationSamplingImaging(int version, EProfile profile, const SpvVersion& spvVersion); + void addSubpassSampling(TSampler, const TString& typeName, int version, EProfile profile); + void addQueryFunctions(TSampler, const TString& typeName, int version, EProfile profile); + void addImageFunctions(TSampler, const TString& typeName, int version, EProfile profile); + void addSamplingFunctions(TSampler, const TString& typeName, int version, EProfile profile); + void addGatherFunctions(TSampler, const TString& typeName, int version, EProfile profile); + + // Helpers for making textual representations of the permutations + // of texturing/imaging functions. + const char* postfixes[5]; + const char* prefixes[EbtNumTypes]; + int dimMap[EsdNumDims]; +}; + +} // end namespace glslang + +#endif // _INITIALIZE_INCLUDED_ diff --git a/android/x86/include/glslang/MachineIndependent/LiveTraverser.h b/android/x86/include/glslang/MachineIndependent/LiveTraverser.h new file mode 100644 index 00000000..7333bc96 --- /dev/null +++ b/android/x86/include/glslang/MachineIndependent/LiveTraverser.h @@ -0,0 +1,138 @@ +// +// Copyright (C) 2016 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#pragma once + +#include "../Include/Common.h" +#include "reflection.h" +#include "localintermediate.h" + +#include "gl_types.h" + +#include +#include + +namespace glslang { + +// +// The traverser: mostly pass through, except +// - processing function-call nodes to push live functions onto the stack of functions to process +// - processing selection nodes to trim semantically dead code +// +// This is in the glslang namespace directly so it can be a friend of TReflection. +// This can be derived from to implement reflection database traversers or +// binding mappers: anything that wants to traverse the live subset of the tree. +// + +class TLiveTraverser : public TIntermTraverser { +public: + TLiveTraverser(const TIntermediate& i, bool traverseAll = false, + bool preVisit = true, bool inVisit = false, bool postVisit = false) : + TIntermTraverser(preVisit, inVisit, postVisit), + intermediate(i), traverseAll(traverseAll) + { } + + // + // Given a function name, find its subroot in the tree, and push it onto the stack of + // functions left to process. + // + void pushFunction(const TString& name) + { + TIntermSequence& globals = intermediate.getTreeRoot()->getAsAggregate()->getSequence(); + for (unsigned int f = 0; f < globals.size(); ++f) { + TIntermAggregate* candidate = globals[f]->getAsAggregate(); + if (candidate && candidate->getOp() == EOpFunction && candidate->getName() == name) { + functions.push_back(candidate); + break; + } + } + } + + typedef std::list TFunctionStack; + TFunctionStack functions; + +protected: + // To catch which function calls are not dead, and hence which functions must be visited. + virtual bool visitAggregate(TVisit, TIntermAggregate* node) + { + if (!traverseAll) + if (node->getOp() == EOpFunctionCall) + addFunctionCall(node); + + return true; // traverse this subtree + } + + // To prune semantically dead paths. + virtual bool visitSelection(TVisit /* visit */, TIntermSelection* node) + { + if (traverseAll) + return true; // traverse all code + + TIntermConstantUnion* constant = node->getCondition()->getAsConstantUnion(); + if (constant) { + // cull the path that is dead + if (constant->getConstArray()[0].getBConst() == true && node->getTrueBlock()) + node->getTrueBlock()->traverse(this); + if (constant->getConstArray()[0].getBConst() == false && node->getFalseBlock()) + node->getFalseBlock()->traverse(this); + + return false; // don't traverse any more, we did it all above + } else + return true; // traverse the whole subtree + } + + // Track live functions as well as uniforms, so that we don't visit dead functions + // and only visit each function once. + void addFunctionCall(TIntermAggregate* call) + { + // // just use the map to ensure we process each function at most once + if (liveFunctions.find(call->getName()) == liveFunctions.end()) { + liveFunctions.insert(call->getName()); + pushFunction(call->getName()); + } + } + + const TIntermediate& intermediate; + typedef std::unordered_set TLiveFunctions; + TLiveFunctions liveFunctions; + bool traverseAll; + +private: + // prevent copy & copy construct + TLiveTraverser(TLiveTraverser&); + TLiveTraverser& operator=(TLiveTraverser&); +}; + +} // namespace glslang diff --git a/android/x86/include/glslang/MachineIndependent/ParseHelper.h b/android/x86/include/glslang/MachineIndependent/ParseHelper.h new file mode 100644 index 00000000..20df6405 --- /dev/null +++ b/android/x86/include/glslang/MachineIndependent/ParseHelper.h @@ -0,0 +1,525 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +// +// This header defines a two-level parse-helper hierarchy, derived from +// TParseVersions: +// - TParseContextBase: sharable across multiple parsers +// - TParseContext: GLSL specific helper +// + +#ifndef _PARSER_HELPER_INCLUDED_ +#define _PARSER_HELPER_INCLUDED_ + +#include +#include + +#include "parseVersions.h" +#include "../Include/ShHandle.h" +#include "SymbolTable.h" +#include "localintermediate.h" +#include "Scan.h" +#include "attribute.h" + +namespace glslang { + +struct TPragma { + TPragma(bool o, bool d) : optimize(o), debug(d) { } + bool optimize; + bool debug; + TPragmaTable pragmaTable; +}; + +class TScanContext; +class TPpContext; + +typedef std::set TIdSetType; + +// +// Sharable code (as well as what's in TParseVersions) across +// parse helpers. +// +class TParseContextBase : public TParseVersions { +public: + TParseContextBase(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins, int version, + EProfile profile, const SpvVersion& spvVersion, EShLanguage language, + TInfoSink& infoSink, bool forwardCompatible, EShMessages messages, + const TString* entryPoint = nullptr) + : TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages), + scopeMangler("::"), + symbolTable(symbolTable), + statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0), + postEntryPointReturn(false), + contextPragma(true, false), + beginInvocationInterlockCount(0), endInvocationInterlockCount(0), + parsingBuiltins(parsingBuiltins), scanContext(nullptr), ppContext(nullptr), + limits(resources.limits), + globalUniformBlock(nullptr), + globalUniformBinding(TQualifier::layoutBindingEnd), + globalUniformSet(TQualifier::layoutSetEnd) + { + if (entryPoint != nullptr) + sourceEntryPointName = *entryPoint; + } + virtual ~TParseContextBase() { } + +#if !defined(GLSLANG_WEB) || defined(GLSLANG_WEB_DEVEL) + virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...); + virtual void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...); + virtual void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...); + virtual void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...); +#endif + + virtual void setLimits(const TBuiltInResource&) = 0; + + void checkIndex(const TSourceLoc&, const TType&, int& index); + + EShLanguage getLanguage() const { return language; } + void setScanContext(TScanContext* c) { scanContext = c; } + TScanContext* getScanContext() const { return scanContext; } + void setPpContext(TPpContext* c) { ppContext = c; } + TPpContext* getPpContext() const { return ppContext; } + + virtual void setLineCallback(const std::function& func) { lineCallback = func; } + virtual void setExtensionCallback(const std::function& func) { extensionCallback = func; } + virtual void setVersionCallback(const std::function& func) { versionCallback = func; } + virtual void setPragmaCallback(const std::function&)>& func) { pragmaCallback = func; } + virtual void setErrorCallback(const std::function& func) { errorCallback = func; } + + virtual void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) = 0; + virtual bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) = 0; + virtual bool lineDirectiveShouldSetNextLine() const = 0; + virtual void handlePragma(const TSourceLoc&, const TVector&) = 0; + + virtual bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) = 0; + + virtual void notifyVersion(int line, int version, const char* type_string) + { + if (versionCallback) + versionCallback(line, version, type_string); + } + virtual void notifyErrorDirective(int line, const char* error_message) + { + if (errorCallback) + errorCallback(line, error_message); + } + virtual void notifyLineDirective(int curLineNo, int newLineNo, bool hasSource, int sourceNum, const char* sourceName) + { + if (lineCallback) + lineCallback(curLineNo, newLineNo, hasSource, sourceNum, sourceName); + } + virtual void notifyExtensionDirective(int line, const char* extension, const char* behavior) + { + if (extensionCallback) + extensionCallback(line, extension, behavior); + } + +#ifdef ENABLE_HLSL + // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL) + virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr); +#endif + + // Potentially rename shader entry point function + void renameShaderFunction(TString*& name) const + { + // Replace the entry point name given in the shader with the real entry point name, + // if there is a substitution. + if (name != nullptr && *name == sourceEntryPointName && intermediate.getEntryPointName().size() > 0) + name = NewPoolTString(intermediate.getEntryPointName().c_str()); + } + + virtual bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*); + virtual void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*); + + const char* const scopeMangler; + + // Basic parsing state, easily accessible to the grammar + + TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile + int statementNestingLevel; // 0 if outside all flow control or compound statements + int loopNestingLevel; // 0 if outside all loops + int structNestingLevel; // 0 if outside blocks and structures + int controlFlowNestingLevel; // 0 if outside all flow control + const TType* currentFunctionType; // the return type of the function that's currently being parsed + bool functionReturnsValue; // true if a non-void function has a return + // if inside a function, true if the function is the entry point and this is after a return statement + bool postEntryPointReturn; + // case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting + TList switchSequenceStack; + // the statementNestingLevel the current switch statement is at, which must match the level of its case statements + TList switchLevel; + struct TPragma contextPragma; + int beginInvocationInterlockCount; + int endInvocationInterlockCount; + +protected: + TParseContextBase(TParseContextBase&); + TParseContextBase& operator=(TParseContextBase&); + + const bool parsingBuiltins; // true if parsing built-in symbols/functions + TVector linkageSymbols; // will be transferred to 'linkage', after all editing is done, order preserving + TScanContext* scanContext; + TPpContext* ppContext; + TBuiltInResource resources; + TLimits& limits; + TString sourceEntryPointName; + + // These, if set, will be called when a line, pragma ... is preprocessed. + // They will be called with any parameters to the original directive. + std::function lineCallback; + std::function&)> pragmaCallback; + std::function versionCallback; + std::function extensionCallback; + std::function errorCallback; + + // see implementation for detail + const TFunction* selectFunction(const TVector, const TFunction&, + std::function, + std::function, + /* output */ bool& tie); + + virtual void parseSwizzleSelector(const TSourceLoc&, const TString&, int size, + TSwizzleSelectors&); + + // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL) + TVariable* globalUniformBlock; // the actual block, inserted into the symbol table + unsigned int globalUniformBinding; // the block's binding number + unsigned int globalUniformSet; // the block's set number + int firstNewMember; // the index of the first member not yet inserted into the symbol table + // override this to set the language-specific name + virtual const char* getGlobalUniformBlockName() const { return ""; } + virtual void setUniformBlockDefaults(TType&) const { } + virtual void finalizeGlobalUniformBlockLayout(TVariable&) { } + virtual void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, TPrefixType prefix, + va_list args); + virtual void trackLinkage(TSymbol& symbol); + virtual void makeEditable(TSymbol*&); + virtual TVariable* getEditableVariable(const char* name); + virtual void finish(); +}; + +// +// Manage the state for when to respect precision qualifiers and when to warn about +// the defaults being different than might be expected. +// +class TPrecisionManager { +public: + TPrecisionManager() : obey(false), warn(false), explicitIntDefault(false), explicitFloatDefault(false){ } + virtual ~TPrecisionManager() {} + + void respectPrecisionQualifiers() { obey = true; } + bool respectingPrecisionQualifiers() const { return obey; } + bool shouldWarnAboutDefaults() const { return warn; } + void defaultWarningGiven() { warn = false; } + void warnAboutDefaults() { warn = true; } + void explicitIntDefaultSeen() + { + explicitIntDefault = true; + if (explicitFloatDefault) + warn = false; + } + void explicitFloatDefaultSeen() + { + explicitFloatDefault = true; + if (explicitIntDefault) + warn = false; + } + +protected: + bool obey; // respect precision qualifiers + bool warn; // need to give a warning about the defaults + bool explicitIntDefault; // user set the default for int/uint + bool explicitFloatDefault; // user set the default for float +}; + +// +// GLSL-specific parse helper. Should have GLSL in the name, but that's +// too big of a change for comparing branches at the moment, and perhaps +// impacts downstream consumers as well. +// +class TParseContext : public TParseContextBase { +public: + TParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins, int version, EProfile, const SpvVersion& spvVersion, EShLanguage, TInfoSink&, + bool forwardCompatible = false, EShMessages messages = EShMsgDefault, + const TString* entryPoint = nullptr); + virtual ~TParseContext(); + + bool obeyPrecisionQualifiers() const { return precisionManager.respectingPrecisionQualifiers(); } + void setPrecisionDefaults(); + + void setLimits(const TBuiltInResource&) override; + bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) override; + void parserError(const char* s); // for bison's yyerror + + void reservedErrorCheck(const TSourceLoc&, const TString&); + void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) override; + bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) override; + bool lineDirectiveShouldSetNextLine() const override; + bool builtInName(const TString&); + + void handlePragma(const TSourceLoc&, const TVector&) override; + TIntermTyped* handleVariable(const TSourceLoc&, TSymbol* symbol, const TString* string); + TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index); + void handleIndexLimits(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index); + +#ifndef GLSLANG_WEB + void makeEditable(TSymbol*&) override; + void ioArrayCheck(const TSourceLoc&, const TType&, const TString& identifier); +#endif + bool isIoResizeArray(const TType&) const; + void fixIoArraySize(const TSourceLoc&, TType&); + void handleIoResizeArrayAccess(const TSourceLoc&, TIntermTyped* base); + void checkIoArraysConsistency(const TSourceLoc&, bool tailOnly = false); + int getIoArrayImplicitSize(const TQualifier&, TString* featureString = nullptr) const; + void checkIoArrayConsistency(const TSourceLoc&, int requiredSize, const char* feature, TType&, const TString&); + + TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right); + TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode); + TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field); + void blockMemberExtensionCheck(const TSourceLoc&, const TIntermTyped* base, int member, const TString& memberName); + TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype); + TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&); + TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*); + TIntermTyped* handleBuiltInFunctionCall(TSourceLoc, TIntermNode* arguments, const TFunction& function); + void computeBuiltinPrecisions(TIntermTyped&, const TFunction&); + TIntermNode* handleReturnValue(const TSourceLoc&, TIntermTyped*); + void checkLocation(const TSourceLoc&, TOperator); + TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*); + void addInputArgumentConversions(const TFunction&, TIntermNode*&) const; + TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const; + void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&); + void nonOpBuiltInCheck(const TSourceLoc&, const TFunction&, TIntermAggregate&); + void userFunctionCallCheck(const TSourceLoc&, TIntermAggregate&); + void samplerConstructorLocationCheck(const TSourceLoc&, const char* token, TIntermNode*); + TFunction* handleConstructorCall(const TSourceLoc&, const TPublicType&); + void handlePrecisionQualifier(const TSourceLoc&, TQualifier&, TPrecisionQualifier); + void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier); + void memorySemanticsCheck(const TSourceLoc&, const TFunction&, const TIntermOperator& callNode); + + void assignError(const TSourceLoc&, const char* op, TString left, TString right); + void unaryOpError(const TSourceLoc&, const char* op, TString operand); + void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right); + void variableCheck(TIntermTyped*& nodePtr); + bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override; + void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override; + void constantValueCheck(TIntermTyped* node, const char* token); + void integerCheck(const TIntermTyped* node, const char* token); + void globalCheck(const TSourceLoc&, const char* token); + bool constructorError(const TSourceLoc&, TIntermNode*, TFunction&, TOperator, TType&); + bool constructorTextureSamplerError(const TSourceLoc&, const TFunction&); + void arraySizeCheck(const TSourceLoc&, TIntermTyped* expr, TArraySize&, const char *sizeType); + bool arrayQualifierError(const TSourceLoc&, const TQualifier&); + bool arrayError(const TSourceLoc&, const TType&); + void arraySizeRequiredCheck(const TSourceLoc&, const TArraySizes&); + void structArrayCheck(const TSourceLoc&, const TType& structure); + void arraySizesCheck(const TSourceLoc&, const TQualifier&, TArraySizes*, const TIntermTyped* initializer, bool lastMember); + void arrayOfArrayVersionCheck(const TSourceLoc&, const TArraySizes*); + bool voidErrorCheck(const TSourceLoc&, const TString&, TBasicType); + void boolCheck(const TSourceLoc&, const TIntermTyped*); + void boolCheck(const TSourceLoc&, const TPublicType&); + void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer); + void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier); + void accStructCheck(const TSourceLoc & loc, const TType & type, const TString & identifier); + void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier); + void memberQualifierCheck(glslang::TPublicType&); + void globalQualifierFixCheck(const TSourceLoc&, TQualifier&); + void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&); + bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType); + void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force); + void setDefaultPrecision(const TSourceLoc&, TPublicType&, TPrecisionQualifier); + int computeSamplerTypeIndex(TSampler&); + TPrecisionQualifier getDefaultPrecision(TPublicType&); + void precisionQualifierCheck(const TSourceLoc&, TBasicType, TQualifier&); + void parameterTypeCheck(const TSourceLoc&, TStorageQualifier qualifier, const TType& type); + bool containsFieldWithBasicType(const TType& type ,TBasicType basicType); + TSymbol* redeclareBuiltinVariable(const TSourceLoc&, const TString&, const TQualifier&, const TShaderQualifiers&); + void redeclareBuiltinBlock(const TSourceLoc&, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes); + void paramCheckFixStorage(const TSourceLoc&, const TStorageQualifier&, TType& type); + void paramCheckFix(const TSourceLoc&, const TQualifier&, TType& type); + void nestedBlockCheck(const TSourceLoc&); + void nestedStructCheck(const TSourceLoc&); + void arrayObjectCheck(const TSourceLoc&, const TType&, const char* op); + void opaqueCheck(const TSourceLoc&, const TType&, const char* op); + void referenceCheck(const TSourceLoc&, const TType&, const char* op); + void storage16BitAssignmentCheck(const TSourceLoc&, const TType&, const char* op); + void specializationCheck(const TSourceLoc&, const TType&, const char* op); + void structTypeCheck(const TSourceLoc&, TPublicType&); + void inductiveLoopCheck(const TSourceLoc&, TIntermNode* init, TIntermLoop* loop); + void arrayLimitCheck(const TSourceLoc&, const TString&, int size); + void limitCheck(const TSourceLoc&, int value, const char* limit, const char* feature); + + void inductiveLoopBodyCheck(TIntermNode*, int loopIndexId, TSymbolTable&); + void constantIndexExpressionCheck(TIntermNode*); + + void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&); + void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&, const TIntermTyped*); + void mergeObjectLayoutQualifiers(TQualifier& dest, const TQualifier& src, bool inheritOnly); + void layoutObjectCheck(const TSourceLoc&, const TSymbol&); + void layoutMemberLocationArrayCheck(const TSourceLoc&, bool memberWithLocation, TArraySizes* arraySizes); + void layoutTypeCheck(const TSourceLoc&, const TType&); + void layoutQualifierCheck(const TSourceLoc&, const TQualifier&); + void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&); + void fixOffset(const TSourceLoc&, TSymbol&); + + const TFunction* findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn); + const TFunction* findFunctionExact(const TSourceLoc& loc, const TFunction& call, bool& builtIn); + const TFunction* findFunction120(const TSourceLoc& loc, const TFunction& call, bool& builtIn); + const TFunction* findFunction400(const TSourceLoc& loc, const TFunction& call, bool& builtIn); + const TFunction* findFunctionExplicitTypes(const TSourceLoc& loc, const TFunction& call, bool& builtIn); + void declareTypeDefaults(const TSourceLoc&, const TPublicType&); + TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, const TPublicType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0); + TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&); + TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&); + TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset); + void inheritMemoryQualifiers(const TQualifier& from, TQualifier& to); + void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0); + void blockStageIoCheck(const TSourceLoc&, const TQualifier&); + void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName); + void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation); + void fixXfbOffsets(TQualifier&, TTypeList&); + void fixBlockUniformOffsets(TQualifier&, TTypeList&); + void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier); + void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&); + void invariantCheck(const TSourceLoc&, const TQualifier&); + void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&); + void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode); + TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body); + +#ifndef GLSLANG_WEB + TAttributeType attributeFromName(const TString& name) const; + TAttributes* makeAttributes(const TString& identifier) const; + TAttributes* makeAttributes(const TString& identifier, TIntermNode* node) const; + TAttributes* mergeAttributes(TAttributes*, TAttributes*) const; + + // Determine selection control from attributes + void handleSelectionAttributes(const TAttributes& attributes, TIntermNode*); + void handleSwitchAttributes(const TAttributes& attributes, TIntermNode*); + // Determine loop control from attributes + void handleLoopAttributes(const TAttributes& attributes, TIntermNode*); +#endif + + void checkAndResizeMeshViewDim(const TSourceLoc&, TType&, bool isBlockMember); + +protected: + void nonInitConstCheck(const TSourceLoc&, TString& identifier, TType& type); + void inheritGlobalDefaults(TQualifier& dst) const; + TVariable* makeInternalVariable(const char* name, const TType&) const; + TVariable* declareNonArray(const TSourceLoc&, const TString& identifier, const TType&); + void declareArray(const TSourceLoc&, const TString& identifier, const TType&, TSymbol*&); + void checkRuntimeSizable(const TSourceLoc&, const TIntermTyped&); + bool isRuntimeLength(const TIntermTyped&) const; + TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable); + TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer); +#ifndef GLSLANG_WEB + void finish() override; +#endif + +public: + // + // Generally, bison productions, the scanner, and the PP need read/write access to these; just give them direct access + // + + // Current state of parsing + bool inMain; // if inside a function, true if the function is main + const TString* blockName; + TQualifier currentBlockQualifier; + TPrecisionQualifier defaultPrecision[EbtNumTypes]; + TBuiltInResource resources; + TLimits& limits; + +protected: + TParseContext(TParseContext&); + TParseContext& operator=(TParseContext&); + + static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2 * 2 * 2 * 2)); // see computeSamplerTypeIndex() + TPrecisionQualifier defaultSamplerPrecision[maxSamplerIndex]; + TPrecisionManager precisionManager; + TQualifier globalBufferDefaults; + TQualifier globalUniformDefaults; + TQualifier globalInputDefaults; + TQualifier globalOutputDefaults; + TString currentCaller; // name of last function body entered (not valid when at global scope) +#ifndef GLSLANG_WEB + int* atomicUintOffsets; // to become an array of the right size to hold an offset per binding point + bool anyIndexLimits; + TIdSetType inductiveLoopIds; + TVector needsIndexLimitationChecking; + + // + // Geometry shader input arrays: + // - array sizing is based on input primitive and/or explicit size + // + // Tessellation control output arrays: + // - array sizing is based on output layout(vertices=...) and/or explicit size + // + // Both: + // - array sizing is retroactive + // - built-in block redeclarations interact with this + // + // Design: + // - use a per-context "resize-list", a list of symbols whose array sizes + // can be fixed + // + // - the resize-list starts empty at beginning of user-shader compilation, it does + // not have built-ins in it + // + // - on built-in array use: copyUp() symbol and add it to the resize-list + // + // - on user array declaration: add it to the resize-list + // + // - on block redeclaration: copyUp() symbol and add it to the resize-list + // * note, that appropriately gives an error if redeclaring a block that + // was already used and hence already copied-up + // + // - on seeing a layout declaration that sizes the array, fix everything in the + // resize-list, giving errors for mismatch + // + // - on seeing an array size declaration, give errors on mismatch between it and previous + // array-sizing declarations + // + TVector ioArraySymbolResizeList; +#endif +}; + +} // end namespace glslang + +#endif // _PARSER_HELPER_INCLUDED_ diff --git a/android/x86/include/glslang/MachineIndependent/RemoveTree.h b/android/x86/include/glslang/MachineIndependent/RemoveTree.h new file mode 100644 index 00000000..1ed01562 --- /dev/null +++ b/android/x86/include/glslang/MachineIndependent/RemoveTree.h @@ -0,0 +1,41 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#pragma once + +namespace glslang { + +void RemoveAllTreeNodes(TIntermNode*); + +} // end namespace glslang diff --git a/android/x86/include/glslang/MachineIndependent/Scan.h b/android/x86/include/glslang/MachineIndependent/Scan.h new file mode 100644 index 00000000..24b75cf7 --- /dev/null +++ b/android/x86/include/glslang/MachineIndependent/Scan.h @@ -0,0 +1,276 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +#ifndef _GLSLANG_SCAN_INCLUDED_ +#define _GLSLANG_SCAN_INCLUDED_ + +#include "Versions.h" + +namespace glslang { + +// Use a global end-of-input character, so no translation is needed across +// layers of encapsulation. Characters are all 8 bit, and positive, so there is +// no aliasing of character 255 onto -1, for example. +const int EndOfInput = -1; + +// +// A character scanner that seamlessly, on read-only strings, reads across an +// array of strings without assuming null termination. +// +class TInputScanner { +public: + TInputScanner(int n, const char* const s[], size_t L[], const char* const* names = nullptr, + int b = 0, int f = 0, bool single = false) : + numSources(n), + // up to this point, common usage is "char*", but now we need positive 8-bit characters + sources(reinterpret_cast(s)), + lengths(L), currentSource(0), currentChar(0), stringBias(b), finale(f), singleLogical(single), + endOfFileReached(false) + { + loc = new TSourceLoc[numSources]; + for (int i = 0; i < numSources; ++i) { + loc[i].init(i - stringBias); + } + if (names != nullptr) { + for (int i = 0; i < numSources; ++i) + loc[i].name = names[i] != nullptr ? NewPoolTString(names[i]) : nullptr; + } + loc[currentSource].line = 1; + logicalSourceLoc.init(1); + logicalSourceLoc.name = loc[0].name; + } + + virtual ~TInputScanner() + { + delete [] loc; + } + + // retrieve the next character and advance one character + int get() + { + int ret = peek(); + if (ret == EndOfInput) + return ret; + ++loc[currentSource].column; + ++logicalSourceLoc.column; + if (ret == '\n') { + ++loc[currentSource].line; + ++logicalSourceLoc.line; + logicalSourceLoc.column = 0; + loc[currentSource].column = 0; + } + advance(); + + return ret; + } + + // retrieve the next character, no advance + int peek() + { + if (currentSource >= numSources) { + endOfFileReached = true; + return EndOfInput; + } + // Make sure we do not read off the end of a string. + // N.B. Sources can have a length of 0. + int sourceToRead = currentSource; + size_t charToRead = currentChar; + while(charToRead >= lengths[sourceToRead]) { + charToRead = 0; + sourceToRead += 1; + if (sourceToRead >= numSources) { + return EndOfInput; + } + } + + // Here, we care about making negative valued characters positive + return sources[sourceToRead][charToRead]; + } + + // go back one character + void unget() + { + // Do not roll back once we've reached the end of the file. + if (endOfFileReached) + return; + + if (currentChar > 0) { + --currentChar; + --loc[currentSource].column; + --logicalSourceLoc.column; + if (loc[currentSource].column < 0) { + // We've moved back past a new line. Find the + // previous newline (or start of the file) to compute + // the column count on the now current line. + size_t chIndex = currentChar; + while (chIndex > 0) { + if (sources[currentSource][chIndex] == '\n') { + break; + } + --chIndex; + } + logicalSourceLoc.column = (int)(currentChar - chIndex); + loc[currentSource].column = (int)(currentChar - chIndex); + } + } else { + do { + --currentSource; + } while (currentSource > 0 && lengths[currentSource] == 0); + if (lengths[currentSource] == 0) { + // set to 0 if we've backed up to the start of an empty string + currentChar = 0; + } else + currentChar = lengths[currentSource] - 1; + } + if (peek() == '\n') { + --loc[currentSource].line; + --logicalSourceLoc.line; + } + } + + // for #line override + void setLine(int newLine) + { + logicalSourceLoc.line = newLine; + loc[getLastValidSourceIndex()].line = newLine; + } + + // for #line override in filename based parsing + void setFile(const char* filename) + { + TString* fn_tstr = NewPoolTString(filename); + logicalSourceLoc.name = fn_tstr; + loc[getLastValidSourceIndex()].name = fn_tstr; + } + + void setFile(const char* filename, int i) + { + TString* fn_tstr = NewPoolTString(filename); + if (i == getLastValidSourceIndex()) { + logicalSourceLoc.name = fn_tstr; + } + loc[i].name = fn_tstr; + } + + void setString(int newString) + { + logicalSourceLoc.string = newString; + loc[getLastValidSourceIndex()].string = newString; + logicalSourceLoc.name = nullptr; + loc[getLastValidSourceIndex()].name = nullptr; + } + + // for #include content indentation + void setColumn(int col) + { + logicalSourceLoc.column = col; + loc[getLastValidSourceIndex()].column = col; + } + + void setEndOfInput() + { + endOfFileReached = true; + currentSource = numSources; + } + + bool atEndOfInput() const { return endOfFileReached; } + + const TSourceLoc& getSourceLoc() const + { + if (singleLogical) { + return logicalSourceLoc; + } else { + return loc[std::max(0, std::min(currentSource, numSources - finale - 1))]; + } + } + // Returns the index (starting from 0) of the most recent valid source string we are reading from. + int getLastValidSourceIndex() const { return std::min(currentSource, numSources - 1); } + + void consumeWhiteSpace(bool& foundNonSpaceTab); + bool consumeComment(); + void consumeWhitespaceComment(bool& foundNonSpaceTab); + bool scanVersion(int& version, EProfile& profile, bool& notFirstToken); + +protected: + + // advance one character + void advance() + { + ++currentChar; + if (currentChar >= lengths[currentSource]) { + ++currentSource; + if (currentSource < numSources) { + loc[currentSource].string = loc[currentSource - 1].string + 1; + loc[currentSource].line = 1; + loc[currentSource].column = 0; + } + while (currentSource < numSources && lengths[currentSource] == 0) { + ++currentSource; + if (currentSource < numSources) { + loc[currentSource].string = loc[currentSource - 1].string + 1; + loc[currentSource].line = 1; + loc[currentSource].column = 0; + } + } + currentChar = 0; + } + } + + int numSources; // number of strings in source + const unsigned char* const *sources; // array of strings; must be converted to positive values on use, to avoid aliasing with -1 as EndOfInput + const size_t *lengths; // length of each string + int currentSource; + size_t currentChar; + + // This is for reporting what string/line an error occurred on, and can be overridden by #line. + // It remembers the last state of each source string as it is left for the next one, so unget() + // can restore that state. + TSourceLoc* loc; // an array + + int stringBias; // the first string that is the user's string number 0 + int finale; // number of internal strings after user's last string + + TSourceLoc logicalSourceLoc; + bool singleLogical; // treats the strings as a single logical string. + // locations will be reported from the first string. + + // Set to true once peek() returns EndOfFile, so that we won't roll back + // once we've reached EndOfFile. + bool endOfFileReached; +}; + +} // end namespace glslang + +#endif // _GLSLANG_SCAN_INCLUDED_ diff --git a/android/x86/include/glslang/MachineIndependent/ScanContext.h b/android/x86/include/glslang/MachineIndependent/ScanContext.h new file mode 100644 index 00000000..74b2b3c7 --- /dev/null +++ b/android/x86/include/glslang/MachineIndependent/ScanContext.h @@ -0,0 +1,93 @@ +// +// Copyright (C) 2013 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +// +// This holds context specific to the GLSL scanner, which +// sits between the preprocessor scanner and parser. +// + +#pragma once + +#include "ParseHelper.h" + +namespace glslang { + +class TPpContext; +class TPpToken; +class TParserToken; + +class TScanContext { +public: + explicit TScanContext(TParseContextBase& pc) : + parseContext(pc), + afterType(false), afterStruct(false), + field(false), afterBuffer(false) { } + virtual ~TScanContext() { } + + static void fillInKeywordMap(); + static void deleteKeywordMap(); + + int tokenize(TPpContext*, TParserToken&); + +protected: + TScanContext(TScanContext&); + TScanContext& operator=(TScanContext&); + + int tokenizeIdentifier(); + int identifierOrType(); + int reservedWord(); + int identifierOrReserved(bool reserved); + int es30ReservedFromGLSL(int version); + int nonreservedKeyword(int esVersion, int nonEsVersion); + int precisionKeyword(); + int matNxM(); + int dMat(); + int firstGenerationImage(bool inEs310); + int secondGenerationImage(); + + TParseContextBase& parseContext; + bool afterType; // true if we've recognized a type, so can only be looking for an identifier + bool afterStruct; // true if we've recognized the STRUCT keyword, so can only be looking for an identifier + bool field; // true if we're on a field, right after a '.' + bool afterBuffer; // true if we've recognized the BUFFER keyword + TSourceLoc loc; + TParserToken* parserToken; + TPpToken* ppToken; + + const char* tokenText; + int keyword; +}; + +} // end namespace glslang diff --git a/android/x86/include/glslang/MachineIndependent/SymbolTable.h b/android/x86/include/glslang/MachineIndependent/SymbolTable.h new file mode 100644 index 00000000..40ca3da5 --- /dev/null +++ b/android/x86/include/glslang/MachineIndependent/SymbolTable.h @@ -0,0 +1,885 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _SYMBOL_TABLE_INCLUDED_ +#define _SYMBOL_TABLE_INCLUDED_ + +// +// Symbol table for parsing. Has these design characteristics: +// +// * Same symbol table can be used to compile many shaders, to preserve +// effort of creating and loading with the large numbers of built-in +// symbols. +// +// --> This requires a copy mechanism, so initial pools used to create +// the shared information can be popped. Done through "clone" +// methods. +// +// * Name mangling will be used to give each function a unique name +// so that symbol table lookups are never ambiguous. This allows +// a simpler symbol table structure. +// +// * Pushing and popping of scope, so symbol table will really be a stack +// of symbol tables. Searched from the top, with new inserts going into +// the top. +// +// * Constants: Compile time constant symbols will keep their values +// in the symbol table. The parser can substitute constants at parse +// time, including doing constant folding and constant propagation. +// +// * No temporaries: Temporaries made from operations (+, --, .xy, etc.) +// are tracked in the intermediate representation, not the symbol table. +// + +#include "../Include/Common.h" +#include "../Include/intermediate.h" +#include "../Include/InfoSink.h" + +namespace glslang { + +// +// Symbol base class. (Can build functions or variables out of these...) +// + +class TVariable; +class TFunction; +class TAnonMember; + +typedef TVector TExtensionList; + +class TSymbol { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + explicit TSymbol(const TString *n) : name(n), extensions(0), writable(true) { } + virtual TSymbol* clone() const = 0; + virtual ~TSymbol() { } // rely on all symbol owned memory coming from the pool + + virtual const TString& getName() const { return *name; } + virtual void changeName(const TString* newName) { name = newName; } + virtual void addPrefix(const char* prefix) + { + TString newName(prefix); + newName.append(*name); + changeName(NewPoolTString(newName.c_str())); + } + virtual const TString& getMangledName() const { return getName(); } + virtual TFunction* getAsFunction() { return 0; } + virtual const TFunction* getAsFunction() const { return 0; } + virtual TVariable* getAsVariable() { return 0; } + virtual const TVariable* getAsVariable() const { return 0; } + virtual const TAnonMember* getAsAnonMember() const { return 0; } + virtual const TType& getType() const = 0; + virtual TType& getWritableType() = 0; + virtual void setUniqueId(int id) { uniqueId = id; } + virtual int getUniqueId() const { return uniqueId; } + virtual void setExtensions(int numExts, const char* const exts[]) + { + assert(extensions == 0); + assert(numExts > 0); + extensions = NewPoolObject(extensions); + for (int e = 0; e < numExts; ++e) + extensions->push_back(exts[e]); + } + virtual int getNumExtensions() const { return extensions == nullptr ? 0 : (int)extensions->size(); } + virtual const char** getExtensions() const { return extensions->data(); } + +#ifndef GLSLANG_WEB + virtual void dump(TInfoSink& infoSink, bool complete = false) const = 0; + void dumpExtensions(TInfoSink& infoSink) const; +#endif + + virtual bool isReadOnly() const { return ! writable; } + virtual void makeReadOnly() { writable = false; } + +protected: + explicit TSymbol(const TSymbol&); + TSymbol& operator=(const TSymbol&); + + const TString *name; + unsigned int uniqueId; // For cross-scope comparing during code generation + + // For tracking what extensions must be present + // (don't use if correct version/profile is present). + TExtensionList* extensions; // an array of pointers to existing constant char strings + + // + // N.B.: Non-const functions that will be generally used should assert on this, + // to avoid overwriting shared symbol-table information. + // + bool writable; +}; + +// +// Variable class, meaning a symbol that's not a function. +// +// There could be a separate class hierarchy for Constant variables; +// Only one of int, bool, or float, (or none) is correct for +// any particular use, but it's easy to do this way, and doesn't +// seem worth having separate classes, and "getConst" can't simply return +// different values for different types polymorphically, so this is +// just simple and pragmatic. +// +class TVariable : public TSymbol { +public: + TVariable(const TString *name, const TType& t, bool uT = false ) + : TSymbol(name), + userType(uT), + constSubtree(nullptr), + memberExtensions(nullptr), + anonId(-1) + { type.shallowCopy(t); } + virtual TVariable* clone() const; + virtual ~TVariable() { } + + virtual TVariable* getAsVariable() { return this; } + virtual const TVariable* getAsVariable() const { return this; } + virtual const TType& getType() const { return type; } + virtual TType& getWritableType() { assert(writable); return type; } + virtual bool isUserType() const { return userType; } + virtual const TConstUnionArray& getConstArray() const { return constArray; } + virtual TConstUnionArray& getWritableConstArray() { assert(writable); return constArray; } + virtual void setConstArray(const TConstUnionArray& array) { constArray = array; } + virtual void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; } + virtual TIntermTyped* getConstSubtree() const { return constSubtree; } + virtual void setAnonId(int i) { anonId = i; } + virtual int getAnonId() const { return anonId; } + + virtual void setMemberExtensions(int member, int numExts, const char* const exts[]) + { + assert(type.isStruct()); + assert(numExts > 0); + if (memberExtensions == nullptr) { + memberExtensions = NewPoolObject(memberExtensions); + memberExtensions->resize(type.getStruct()->size()); + } + for (int e = 0; e < numExts; ++e) + (*memberExtensions)[member].push_back(exts[e]); + } + virtual bool hasMemberExtensions() const { return memberExtensions != nullptr; } + virtual int getNumMemberExtensions(int member) const + { + return memberExtensions == nullptr ? 0 : (int)(*memberExtensions)[member].size(); + } + virtual const char** getMemberExtensions(int member) const { return (*memberExtensions)[member].data(); } + +#ifndef GLSLANG_WEB + virtual void dump(TInfoSink& infoSink, bool complete = false) const; +#endif + +protected: + explicit TVariable(const TVariable&); + TVariable& operator=(const TVariable&); + + TType type; + bool userType; + + // we are assuming that Pool Allocator will free the memory allocated to unionArray + // when this object is destroyed + + TConstUnionArray constArray; // for compile-time constant value + TIntermTyped* constSubtree; // for specialization constant computation + TVector* memberExtensions; // per-member extension list, allocated only when needed + int anonId; // the ID used for anonymous blocks: TODO: see if uniqueId could serve a dual purpose +}; + +// +// The function sub-class of symbols and the parser will need to +// share this definition of a function parameter. +// +struct TParameter { + TString *name; + TType* type; + TIntermTyped* defaultValue; + void copyParam(const TParameter& param) + { + if (param.name) + name = NewPoolTString(param.name->c_str()); + else + name = 0; + type = param.type->clone(); + defaultValue = param.defaultValue; + } + TBuiltInVariable getDeclaredBuiltIn() const { return type->getQualifier().declaredBuiltIn; } +}; + +// +// The function sub-class of a symbol. +// +class TFunction : public TSymbol { +public: + explicit TFunction(TOperator o) : + TSymbol(0), + op(o), + defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0) { } + TFunction(const TString *name, const TType& retType, TOperator tOp = EOpNull) : + TSymbol(name), + mangledName(*name + '('), + op(tOp), + defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0) + { + returnType.shallowCopy(retType); + declaredBuiltIn = retType.getQualifier().builtIn; + } + virtual TFunction* clone() const override; + virtual ~TFunction(); + + virtual TFunction* getAsFunction() override { return this; } + virtual const TFunction* getAsFunction() const override { return this; } + + // Install 'p' as the (non-'this') last parameter. + // Non-'this' parameters are reflected in both the list of parameters and the + // mangled name. + virtual void addParameter(TParameter& p) + { + assert(writable); + parameters.push_back(p); + p.type->appendMangledName(mangledName); + + if (p.defaultValue != nullptr) + defaultParamCount++; + } + + // Install 'this' as the first parameter. + // 'this' is reflected in the list of parameters, but not the mangled name. + virtual void addThisParameter(TType& type, const char* name) + { + TParameter p = { NewPoolTString(name), new TType, nullptr }; + p.type->shallowCopy(type); + parameters.insert(parameters.begin(), p); + } + + virtual void addPrefix(const char* prefix) override + { + TSymbol::addPrefix(prefix); + mangledName.insert(0, prefix); + } + + virtual void removePrefix(const TString& prefix) + { + assert(mangledName.compare(0, prefix.size(), prefix) == 0); + mangledName.erase(0, prefix.size()); + } + + virtual const TString& getMangledName() const override { return mangledName; } + virtual const TType& getType() const override { return returnType; } + virtual TBuiltInVariable getDeclaredBuiltInType() const { return declaredBuiltIn; } + virtual TType& getWritableType() override { return returnType; } + virtual void relateToOperator(TOperator o) { assert(writable); op = o; } + virtual TOperator getBuiltInOp() const { return op; } + virtual void setDefined() { assert(writable); defined = true; } + virtual bool isDefined() const { return defined; } + virtual void setPrototyped() { assert(writable); prototyped = true; } + virtual bool isPrototyped() const { return prototyped; } + virtual void setImplicitThis() { assert(writable); implicitThis = true; } + virtual bool hasImplicitThis() const { return implicitThis; } + virtual void setIllegalImplicitThis() { assert(writable); illegalImplicitThis = true; } + virtual bool hasIllegalImplicitThis() const { return illegalImplicitThis; } + + // Return total number of parameters + virtual int getParamCount() const { return static_cast(parameters.size()); } + // Return number of parameters with default values. + virtual int getDefaultParamCount() const { return defaultParamCount; } + // Return number of fixed parameters (without default values) + virtual int getFixedParamCount() const { return getParamCount() - getDefaultParamCount(); } + + virtual TParameter& operator[](int i) { assert(writable); return parameters[i]; } + virtual const TParameter& operator[](int i) const { return parameters[i]; } + +#ifndef GLSLANG_WEB + virtual void dump(TInfoSink& infoSink, bool complete = false) const override; +#endif + +protected: + explicit TFunction(const TFunction&); + TFunction& operator=(const TFunction&); + + typedef TVector TParamList; + TParamList parameters; + TType returnType; + TBuiltInVariable declaredBuiltIn; + + TString mangledName; + TOperator op; + bool defined; + bool prototyped; + bool implicitThis; // True if this function is allowed to see all members of 'this' + bool illegalImplicitThis; // True if this function is not supposed to have access to dynamic members of 'this', + // even if it finds member variables in the symbol table. + // This is important for a static member function that has member variables in scope, + // but is not allowed to use them, or see hidden symbols instead. + int defaultParamCount; +}; + +// +// Members of anonymous blocks are a kind of TSymbol. They are not hidden in +// the symbol table behind a container; rather they are visible and point to +// their anonymous container. (The anonymous container is found through the +// member, not the other way around.) +// +class TAnonMember : public TSymbol { +public: + TAnonMember(const TString* n, unsigned int m, TVariable& a, int an) : TSymbol(n), anonContainer(a), memberNumber(m), anonId(an) { } + virtual TAnonMember* clone() const override; + virtual ~TAnonMember() { } + + virtual const TAnonMember* getAsAnonMember() const override { return this; } + virtual const TVariable& getAnonContainer() const { return anonContainer; } + virtual unsigned int getMemberNumber() const { return memberNumber; } + + virtual const TType& getType() const override + { + const TTypeList& types = *anonContainer.getType().getStruct(); + return *types[memberNumber].type; + } + + virtual TType& getWritableType() override + { + assert(writable); + const TTypeList& types = *anonContainer.getType().getStruct(); + return *types[memberNumber].type; + } + + virtual void setExtensions(int numExts, const char* const exts[]) override + { + anonContainer.setMemberExtensions(memberNumber, numExts, exts); + } + virtual int getNumExtensions() const override { return anonContainer.getNumMemberExtensions(memberNumber); } + virtual const char** getExtensions() const override { return anonContainer.getMemberExtensions(memberNumber); } + + virtual int getAnonId() const { return anonId; } +#ifndef GLSLANG_WEB + virtual void dump(TInfoSink& infoSink, bool complete = false) const override; +#endif + +protected: + explicit TAnonMember(const TAnonMember&); + TAnonMember& operator=(const TAnonMember&); + + TVariable& anonContainer; + unsigned int memberNumber; + int anonId; +}; + +class TSymbolTableLevel { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + TSymbolTableLevel() : defaultPrecision(0), anonId(0), thisLevel(false) { } + ~TSymbolTableLevel(); + + bool insert(TSymbol& symbol, bool separateNameSpaces) + { + // + // returning true means symbol was added to the table with no semantic errors + // + const TString& name = symbol.getName(); + if (name == "") { + symbol.getAsVariable()->setAnonId(anonId++); + // An empty name means an anonymous container, exposing its members to the external scope. + // Give it a name and insert its members in the symbol table, pointing to the container. + char buf[20]; + snprintf(buf, 20, "%s%d", AnonymousPrefix, symbol.getAsVariable()->getAnonId()); + symbol.changeName(NewPoolTString(buf)); + + return insertAnonymousMembers(symbol, 0); + } else { + // Check for redefinition errors: + // - STL itself will tell us if there is a direct name collision, with name mangling, at this level + // - additionally, check for function-redefining-variable name collisions + const TString& insertName = symbol.getMangledName(); + if (symbol.getAsFunction()) { + // make sure there isn't a variable of this name + if (! separateNameSpaces && level.find(name) != level.end()) + return false; + + // insert, and whatever happens is okay + level.insert(tLevelPair(insertName, &symbol)); + + return true; + } else + return level.insert(tLevelPair(insertName, &symbol)).second; + } + } + + // Add more members to an already inserted aggregate object + bool amend(TSymbol& symbol, int firstNewMember) + { + // See insert() for comments on basic explanation of insert. + // This operates similarly, but more simply. + // Only supporting amend of anonymous blocks so far. + if (IsAnonymous(symbol.getName())) + return insertAnonymousMembers(symbol, firstNewMember); + else + return false; + } + + bool insertAnonymousMembers(TSymbol& symbol, int firstMember) + { + const TTypeList& types = *symbol.getAsVariable()->getType().getStruct(); + for (unsigned int m = firstMember; m < types.size(); ++m) { + TAnonMember* member = new TAnonMember(&types[m].type->getFieldName(), m, *symbol.getAsVariable(), symbol.getAsVariable()->getAnonId()); + if (! level.insert(tLevelPair(member->getMangledName(), member)).second) + return false; + } + + return true; + } + + TSymbol* find(const TString& name) const + { + tLevel::const_iterator it = level.find(name); + if (it == level.end()) + return 0; + else + return (*it).second; + } + + void findFunctionNameList(const TString& name, TVector& list) + { + size_t parenAt = name.find_first_of('('); + TString base(name, 0, parenAt + 1); + + tLevel::const_iterator begin = level.lower_bound(base); + base[parenAt] = ')'; // assume ')' is lexically after '(' + tLevel::const_iterator end = level.upper_bound(base); + for (tLevel::const_iterator it = begin; it != end; ++it) + list.push_back(it->second->getAsFunction()); + } + + // See if there is already a function in the table having the given non-function-style name. + bool hasFunctionName(const TString& name) const + { + tLevel::const_iterator candidate = level.lower_bound(name); + if (candidate != level.end()) { + const TString& candidateName = (*candidate).first; + TString::size_type parenAt = candidateName.find_first_of('('); + if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0) + + return true; + } + + return false; + } + + // See if there is a variable at this level having the given non-function-style name. + // Return true if name is found, and set variable to true if the name was a variable. + bool findFunctionVariableName(const TString& name, bool& variable) const + { + tLevel::const_iterator candidate = level.lower_bound(name); + if (candidate != level.end()) { + const TString& candidateName = (*candidate).first; + TString::size_type parenAt = candidateName.find_first_of('('); + if (parenAt == candidateName.npos) { + // not a mangled name + if (candidateName == name) { + // found a variable name match + variable = true; + return true; + } + } else { + // a mangled name + if (candidateName.compare(0, parenAt, name) == 0) { + // found a function name match + variable = false; + return true; + } + } + } + + return false; + } + + // Use this to do a lazy 'push' of precision defaults the first time + // a precision statement is seen in a new scope. Leave it at 0 for + // when no push was needed. Thus, it is not the current defaults, + // it is what to restore the defaults to when popping a level. + void setPreviousDefaultPrecisions(const TPrecisionQualifier *p) + { + // can call multiple times at one scope, will only latch on first call, + // as we're tracking the previous scope's values, not the current values + if (defaultPrecision != 0) + return; + + defaultPrecision = new TPrecisionQualifier[EbtNumTypes]; + for (int t = 0; t < EbtNumTypes; ++t) + defaultPrecision[t] = p[t]; + } + + void getPreviousDefaultPrecisions(TPrecisionQualifier *p) + { + // can be called for table level pops that didn't set the + // defaults + if (defaultPrecision == 0 || p == 0) + return; + + for (int t = 0; t < EbtNumTypes; ++t) + p[t] = defaultPrecision[t]; + } + + void relateToOperator(const char* name, TOperator op); + void setFunctionExtensions(const char* name, int num, const char* const extensions[]); +#ifndef GLSLANG_WEB + void dump(TInfoSink& infoSink, bool complete = false) const; +#endif + TSymbolTableLevel* clone() const; + void readOnly(); + + void setThisLevel() { thisLevel = true; } + bool isThisLevel() const { return thisLevel; } + +protected: + explicit TSymbolTableLevel(TSymbolTableLevel&); + TSymbolTableLevel& operator=(TSymbolTableLevel&); + + typedef std::map, pool_allocator > > tLevel; + typedef const tLevel::value_type tLevelPair; + typedef std::pair tInsertResult; + + tLevel level; // named mappings + TPrecisionQualifier *defaultPrecision; + int anonId; + bool thisLevel; // True if this level of the symbol table is a structure scope containing member function + // that are supposed to see anonymous access to member variables. +}; + +class TSymbolTable { +public: + TSymbolTable() : uniqueId(0), noBuiltInRedeclarations(false), separateNameSpaces(false), adoptedLevels(0) + { + // + // This symbol table cannot be used until push() is called. + // + } + ~TSymbolTable() + { + // this can be called explicitly; safest to code it so it can be called multiple times + + // don't deallocate levels passed in from elsewhere + while (table.size() > adoptedLevels) + pop(0); + } + + void adoptLevels(TSymbolTable& symTable) + { + for (unsigned int level = 0; level < symTable.table.size(); ++level) { + table.push_back(symTable.table[level]); + ++adoptedLevels; + } + uniqueId = symTable.uniqueId; + noBuiltInRedeclarations = symTable.noBuiltInRedeclarations; + separateNameSpaces = symTable.separateNameSpaces; + } + + // + // While level adopting is generic, the methods below enact a the following + // convention for levels: + // 0: common built-ins shared across all stages, all compiles, only one copy for all symbol tables + // 1: per-stage built-ins, shared across all compiles, but a different copy per stage + // 2: built-ins specific to a compile, like resources that are context-dependent, or redeclared built-ins + // 3: user-shader globals + // +protected: + static const int globalLevel = 3; + bool isSharedLevel(int level) { return level <= 1; } // exclude all per-compile levels + bool isBuiltInLevel(int level) { return level <= 2; } // exclude user globals + bool isGlobalLevel(int level) { return level <= globalLevel; } // include user globals +public: + bool isEmpty() { return table.size() == 0; } + bool atBuiltInLevel() { return isBuiltInLevel(currentLevel()); } + bool atGlobalLevel() { return isGlobalLevel(currentLevel()); } + + void setNoBuiltInRedeclarations() { noBuiltInRedeclarations = true; } + void setSeparateNameSpaces() { separateNameSpaces = true; } + + void push() + { + table.push_back(new TSymbolTableLevel); + } + + // Make a new symbol-table level to represent the scope introduced by a structure + // containing member functions, such that the member functions can find anonymous + // references to member variables. + // + // 'thisSymbol' should have a name of "" to trigger anonymous structure-member + // symbol finds. + void pushThis(TSymbol& thisSymbol) + { + assert(thisSymbol.getName().size() == 0); + table.push_back(new TSymbolTableLevel); + table.back()->setThisLevel(); + insert(thisSymbol); + } + + void pop(TPrecisionQualifier *p) + { + table[currentLevel()]->getPreviousDefaultPrecisions(p); + delete table.back(); + table.pop_back(); + } + + // + // Insert a visible symbol into the symbol table so it can + // be found later by name. + // + // Returns false if the was a name collision. + // + bool insert(TSymbol& symbol) + { + symbol.setUniqueId(++uniqueId); + + // make sure there isn't a function of this variable name + if (! separateNameSpaces && ! symbol.getAsFunction() && table[currentLevel()]->hasFunctionName(symbol.getName())) + return false; + + // check for not overloading or redefining a built-in function + if (noBuiltInRedeclarations) { + if (atGlobalLevel() && currentLevel() > 0) { + if (table[0]->hasFunctionName(symbol.getName())) + return false; + if (currentLevel() > 1 && table[1]->hasFunctionName(symbol.getName())) + return false; + } + } + + return table[currentLevel()]->insert(symbol, separateNameSpaces); + } + + // Add more members to an already inserted aggregate object + bool amend(TSymbol& symbol, int firstNewMember) + { + // See insert() for comments on basic explanation of insert. + // This operates similarly, but more simply. + return table[currentLevel()]->amend(symbol, firstNewMember); + } + + // + // To allocate an internal temporary, which will need to be uniquely + // identified by the consumer of the AST, but never need to + // found by doing a symbol table search by name, hence allowed an + // arbitrary name in the symbol with no worry of collision. + // + void makeInternalVariable(TSymbol& symbol) + { + symbol.setUniqueId(++uniqueId); + } + + // + // Copy a variable or anonymous member's structure from a shared level so that + // it can be added (soon after return) to the symbol table where it can be + // modified without impacting other users of the shared table. + // + TSymbol* copyUpDeferredInsert(TSymbol* shared) + { + if (shared->getAsVariable()) { + TSymbol* copy = shared->clone(); + copy->setUniqueId(shared->getUniqueId()); + return copy; + } else { + const TAnonMember* anon = shared->getAsAnonMember(); + assert(anon); + TVariable* container = anon->getAnonContainer().clone(); + container->changeName(NewPoolTString("")); + container->setUniqueId(anon->getAnonContainer().getUniqueId()); + return container; + } + } + + TSymbol* copyUp(TSymbol* shared) + { + TSymbol* copy = copyUpDeferredInsert(shared); + table[globalLevel]->insert(*copy, separateNameSpaces); + if (shared->getAsVariable()) + return copy; + else { + // return the copy of the anonymous member + return table[globalLevel]->find(shared->getName()); + } + } + + // Normal find of a symbol, that can optionally say whether the symbol was found + // at a built-in level or the current top-scope level. + TSymbol* find(const TString& name, bool* builtIn = 0, bool* currentScope = 0, int* thisDepthP = 0) + { + int level = currentLevel(); + TSymbol* symbol; + int thisDepth = 0; + do { + if (table[level]->isThisLevel()) + ++thisDepth; + symbol = table[level]->find(name); + --level; + } while (symbol == nullptr && level >= 0); + level++; + if (builtIn) + *builtIn = isBuiltInLevel(level); + if (currentScope) + *currentScope = isGlobalLevel(currentLevel()) || level == currentLevel(); // consider shared levels as "current scope" WRT user globals + if (thisDepthP != nullptr) { + if (! table[level]->isThisLevel()) + thisDepth = 0; + *thisDepthP = thisDepth; + } + + return symbol; + } + + // Find of a symbol that returns how many layers deep of nested + // structures-with-member-functions ('this' scopes) deep the symbol was + // found in. + TSymbol* find(const TString& name, int& thisDepth) + { + int level = currentLevel(); + TSymbol* symbol; + thisDepth = 0; + do { + if (table[level]->isThisLevel()) + ++thisDepth; + symbol = table[level]->find(name); + --level; + } while (symbol == 0 && level >= 0); + + if (! table[level + 1]->isThisLevel()) + thisDepth = 0; + + return symbol; + } + + bool isFunctionNameVariable(const TString& name) const + { + if (separateNameSpaces) + return false; + + int level = currentLevel(); + do { + bool variable; + bool found = table[level]->findFunctionVariableName(name, variable); + if (found) + return variable; + --level; + } while (level >= 0); + + return false; + } + + void findFunctionNameList(const TString& name, TVector& list, bool& builtIn) + { + // For user levels, return the set found in the first scope with a match + builtIn = false; + int level = currentLevel(); + do { + table[level]->findFunctionNameList(name, list); + --level; + } while (list.empty() && level >= globalLevel); + + if (! list.empty()) + return; + + // Gather across all built-in levels; they don't hide each other + builtIn = true; + do { + table[level]->findFunctionNameList(name, list); + --level; + } while (level >= 0); + } + + void relateToOperator(const char* name, TOperator op) + { + for (unsigned int level = 0; level < table.size(); ++level) + table[level]->relateToOperator(name, op); + } + + void setFunctionExtensions(const char* name, int num, const char* const extensions[]) + { + for (unsigned int level = 0; level < table.size(); ++level) + table[level]->setFunctionExtensions(name, num, extensions); + } + + void setVariableExtensions(const char* name, int numExts, const char* const extensions[]) + { + TSymbol* symbol = find(TString(name)); + if (symbol == nullptr) + return; + + symbol->setExtensions(numExts, extensions); + } + + void setVariableExtensions(const char* blockName, const char* name, int numExts, const char* const extensions[]) + { + TSymbol* symbol = find(TString(blockName)); + if (symbol == nullptr) + return; + TVariable* variable = symbol->getAsVariable(); + assert(variable != nullptr); + + const TTypeList& structure = *variable->getAsVariable()->getType().getStruct(); + for (int member = 0; member < (int)structure.size(); ++member) { + if (structure[member].type->getFieldName().compare(name) == 0) { + variable->setMemberExtensions(member, numExts, extensions); + return; + } + } + } + + int getMaxSymbolId() { return uniqueId; } +#ifndef GLSLANG_WEB + void dump(TInfoSink& infoSink, bool complete = false) const; +#endif + void copyTable(const TSymbolTable& copyOf); + + void setPreviousDefaultPrecisions(TPrecisionQualifier *p) { table[currentLevel()]->setPreviousDefaultPrecisions(p); } + + void readOnly() + { + for (unsigned int level = 0; level < table.size(); ++level) + table[level]->readOnly(); + } + +protected: + TSymbolTable(TSymbolTable&); + TSymbolTable& operator=(TSymbolTableLevel&); + + int currentLevel() const { return static_cast(table.size()) - 1; } + + std::vector table; + int uniqueId; // for unique identification in code generation + bool noBuiltInRedeclarations; + bool separateNameSpaces; + unsigned int adoptedLevels; +}; + +} // end namespace glslang + +#endif // _SYMBOL_TABLE_INCLUDED_ diff --git a/android/x86/include/glslang/MachineIndependent/Versions.h b/android/x86/include/glslang/MachineIndependent/Versions.h new file mode 100644 index 00000000..98a88e1d --- /dev/null +++ b/android/x86/include/glslang/MachineIndependent/Versions.h @@ -0,0 +1,327 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 LunarG, Inc. +// Copyright (C) 2017 ARM Limited. +// Copyright (C) 2015-2018 Google, Inc. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +#ifndef _VERSIONS_INCLUDED_ +#define _VERSIONS_INCLUDED_ + +#define LAST_ELEMENT_MARKER(x) x + +// +// Help manage multiple profiles, versions, extensions etc. +// + +// +// Profiles are set up for masking operations, so queries can be done on multiple +// profiles at the same time. +// +// Don't maintain an ordinal set of enums (0,1,2,3...) to avoid all possible +// defects from mixing the two different forms. +// +typedef enum { + EBadProfile = 0, + ENoProfile = (1 << 0), // only for desktop, before profiles showed up + ECoreProfile = (1 << 1), + ECompatibilityProfile = (1 << 2), + EEsProfile = (1 << 3), + LAST_ELEMENT_MARKER(EProfileCount), +} EProfile; + +namespace glslang { + +// +// Map from profile enum to externally readable text name. +// +inline const char* ProfileName(EProfile profile) +{ + switch (profile) { + case ENoProfile: return "none"; + case ECoreProfile: return "core"; + case ECompatibilityProfile: return "compatibility"; + case EEsProfile: return "es"; + default: return "unknown profile"; + } +} + +// +// What source rules, validation rules, target language, etc. are needed or +// desired for SPIR-V? +// +// 0 means a target or rule set is not enabled (ignore rules from that entity). +// Non-0 means to apply semantic rules arising from that version of its rule set. +// The union of all requested rule sets will be applied. +// +struct SpvVersion { + SpvVersion() : spv(0), vulkanGlsl(0), vulkan(0), openGl(0) {} + unsigned int spv; // the version of SPIR-V to target, as defined by "word 1" of the SPIR-V binary header + int vulkanGlsl; // the version of GLSL semantics for Vulkan, from GL_KHR_vulkan_glsl, for "#define VULKAN XXX" + int vulkan; // the version of Vulkan, for which SPIR-V execution environment rules to use + int openGl; // the version of GLSL semantics for OpenGL, from GL_ARB_gl_spirv, for "#define GL_SPIRV XXX" +}; + +// +// The behaviors from the GLSL "#extension extension_name : behavior" +// +typedef enum { + EBhMissing = 0, + EBhRequire, + EBhEnable, + EBhWarn, + EBhDisable, + EBhDisablePartial // use as initial state of an extension that is only partially implemented +} TExtensionBehavior; + +// +// Symbolic names for extensions. Strings may be directly used when calling the +// functions, but better to have the compiler do spelling checks. +// +const char* const E_GL_OES_texture_3D = "GL_OES_texture_3D"; +const char* const E_GL_OES_standard_derivatives = "GL_OES_standard_derivatives"; +const char* const E_GL_EXT_frag_depth = "GL_EXT_frag_depth"; +const char* const E_GL_OES_EGL_image_external = "GL_OES_EGL_image_external"; +const char* const E_GL_OES_EGL_image_external_essl3 = "GL_OES_EGL_image_external_essl3"; +const char* const E_GL_EXT_YUV_target = "GL_EXT_YUV_target"; +const char* const E_GL_EXT_shader_texture_lod = "GL_EXT_shader_texture_lod"; +const char* const E_GL_EXT_shadow_samplers = "GL_EXT_shadow_samplers"; + +const char* const E_GL_ARB_texture_rectangle = "GL_ARB_texture_rectangle"; +const char* const E_GL_3DL_array_objects = "GL_3DL_array_objects"; +const char* const E_GL_ARB_shading_language_420pack = "GL_ARB_shading_language_420pack"; +const char* const E_GL_ARB_texture_gather = "GL_ARB_texture_gather"; +const char* const E_GL_ARB_gpu_shader5 = "GL_ARB_gpu_shader5"; +const char* const E_GL_ARB_separate_shader_objects = "GL_ARB_separate_shader_objects"; +const char* const E_GL_ARB_compute_shader = "GL_ARB_compute_shader"; +const char* const E_GL_ARB_tessellation_shader = "GL_ARB_tessellation_shader"; +const char* const E_GL_ARB_enhanced_layouts = "GL_ARB_enhanced_layouts"; +const char* const E_GL_ARB_texture_cube_map_array = "GL_ARB_texture_cube_map_array"; +const char* const E_GL_ARB_texture_multisample = "GL_ARB_texture_multisample"; +const char* const E_GL_ARB_shader_texture_lod = "GL_ARB_shader_texture_lod"; +const char* const E_GL_ARB_explicit_attrib_location = "GL_ARB_explicit_attrib_location"; +const char* const E_GL_ARB_explicit_uniform_location = "GL_ARB_explicit_uniform_location"; +const char* const E_GL_ARB_shader_image_load_store = "GL_ARB_shader_image_load_store"; +const char* const E_GL_ARB_shader_atomic_counters = "GL_ARB_shader_atomic_counters"; +const char* const E_GL_ARB_shader_draw_parameters = "GL_ARB_shader_draw_parameters"; +const char* const E_GL_ARB_shader_group_vote = "GL_ARB_shader_group_vote"; +const char* const E_GL_ARB_derivative_control = "GL_ARB_derivative_control"; +const char* const E_GL_ARB_shader_texture_image_samples = "GL_ARB_shader_texture_image_samples"; +const char* const E_GL_ARB_viewport_array = "GL_ARB_viewport_array"; +const char* const E_GL_ARB_gpu_shader_int64 = "GL_ARB_gpu_shader_int64"; +const char* const E_GL_ARB_gpu_shader_fp64 = "GL_ARB_gpu_shader_fp64"; +const char* const E_GL_ARB_shader_ballot = "GL_ARB_shader_ballot"; +const char* const E_GL_ARB_sparse_texture2 = "GL_ARB_sparse_texture2"; +const char* const E_GL_ARB_sparse_texture_clamp = "GL_ARB_sparse_texture_clamp"; +const char* const E_GL_ARB_shader_stencil_export = "GL_ARB_shader_stencil_export"; +// const char* const E_GL_ARB_cull_distance = "GL_ARB_cull_distance"; // present for 4.5, but need extension control over block members +const char* const E_GL_ARB_post_depth_coverage = "GL_ARB_post_depth_coverage"; +const char* const E_GL_ARB_shader_viewport_layer_array = "GL_ARB_shader_viewport_layer_array"; +const char* const E_GL_ARB_fragment_shader_interlock = "GL_ARB_fragment_shader_interlock"; +const char* const E_GL_ARB_shader_clock = "GL_ARB_shader_clock"; +const char* const E_GL_ARB_uniform_buffer_object = "GL_ARB_uniform_buffer_object"; +const char* const E_GL_ARB_sample_shading = "GL_ARB_sample_shading"; +const char* const E_GL_ARB_shader_bit_encoding = "GL_ARB_shader_bit_encoding"; +const char* const E_GL_ARB_shader_image_size = "GL_ARB_shader_image_size"; +const char* const E_GL_ARB_shader_storage_buffer_object = "GL_ARB_shader_storage_buffer_object"; +const char* const E_GL_ARB_shading_language_packing = "GL_ARB_shading_language_packing"; +const char* const E_GL_ARB_texture_query_lod = "GL_ARB_texture_query_lod"; + +const char* const E_GL_KHR_shader_subgroup_basic = "GL_KHR_shader_subgroup_basic"; +const char* const E_GL_KHR_shader_subgroup_vote = "GL_KHR_shader_subgroup_vote"; +const char* const E_GL_KHR_shader_subgroup_arithmetic = "GL_KHR_shader_subgroup_arithmetic"; +const char* const E_GL_KHR_shader_subgroup_ballot = "GL_KHR_shader_subgroup_ballot"; +const char* const E_GL_KHR_shader_subgroup_shuffle = "GL_KHR_shader_subgroup_shuffle"; +const char* const E_GL_KHR_shader_subgroup_shuffle_relative = "GL_KHR_shader_subgroup_shuffle_relative"; +const char* const E_GL_KHR_shader_subgroup_clustered = "GL_KHR_shader_subgroup_clustered"; +const char* const E_GL_KHR_shader_subgroup_quad = "GL_KHR_shader_subgroup_quad"; +const char* const E_GL_KHR_memory_scope_semantics = "GL_KHR_memory_scope_semantics"; + +const char* const E_GL_EXT_shader_atomic_int64 = "GL_EXT_shader_atomic_int64"; + +const char* const E_GL_EXT_shader_non_constant_global_initializers = "GL_EXT_shader_non_constant_global_initializers"; +const char* const E_GL_EXT_shader_image_load_formatted = "GL_EXT_shader_image_load_formatted"; + +const char* const E_GL_EXT_shader_16bit_storage = "GL_EXT_shader_16bit_storage"; +const char* const E_GL_EXT_shader_8bit_storage = "GL_EXT_shader_8bit_storage"; + + +// EXT extensions +const char* const E_GL_EXT_device_group = "GL_EXT_device_group"; +const char* const E_GL_EXT_multiview = "GL_EXT_multiview"; +const char* const E_GL_EXT_post_depth_coverage = "GL_EXT_post_depth_coverage"; +const char* const E_GL_EXT_control_flow_attributes = "GL_EXT_control_flow_attributes"; +const char* const E_GL_EXT_nonuniform_qualifier = "GL_EXT_nonuniform_qualifier"; +const char* const E_GL_EXT_samplerless_texture_functions = "GL_EXT_samplerless_texture_functions"; +const char* const E_GL_EXT_scalar_block_layout = "GL_EXT_scalar_block_layout"; +const char* const E_GL_EXT_fragment_invocation_density = "GL_EXT_fragment_invocation_density"; +const char* const E_GL_EXT_buffer_reference = "GL_EXT_buffer_reference"; +const char* const E_GL_EXT_buffer_reference2 = "GL_EXT_buffer_reference2"; +const char* const E_GL_EXT_buffer_reference_uvec2 = "GL_EXT_buffer_reference_uvec2"; +const char* const E_GL_EXT_demote_to_helper_invocation = "GL_EXT_demote_to_helper_invocation"; +const char* const E_GL_EXT_shader_realtime_clock = "GL_EXT_shader_realtime_clock"; +const char* const E_GL_EXT_debug_printf = "GL_EXT_debug_printf"; +const char* const E_GL_EXT_ray_tracing = "GL_EXT_ray_tracing"; +const char* const E_GL_EXT_ray_query = "GL_EXT_ray_query"; +const char* const E_GL_EXT_ray_flags_primitive_culling = "GL_EXT_ray_flags_primitive_culling"; + +// Arrays of extensions for the above viewportEXTs duplications + +const char* const post_depth_coverageEXTs[] = { E_GL_ARB_post_depth_coverage, E_GL_EXT_post_depth_coverage }; +const int Num_post_depth_coverageEXTs = sizeof(post_depth_coverageEXTs) / sizeof(post_depth_coverageEXTs[0]); + +// OVR extensions +const char* const E_GL_OVR_multiview = "GL_OVR_multiview"; +const char* const E_GL_OVR_multiview2 = "GL_OVR_multiview2"; + +const char* const OVR_multiview_EXTs[] = { E_GL_OVR_multiview, E_GL_OVR_multiview2 }; +const int Num_OVR_multiview_EXTs = sizeof(OVR_multiview_EXTs) / sizeof(OVR_multiview_EXTs[0]); + +// #line and #include +const char* const E_GL_GOOGLE_cpp_style_line_directive = "GL_GOOGLE_cpp_style_line_directive"; +const char* const E_GL_GOOGLE_include_directive = "GL_GOOGLE_include_directive"; + +const char* const E_GL_AMD_shader_ballot = "GL_AMD_shader_ballot"; +const char* const E_GL_AMD_shader_trinary_minmax = "GL_AMD_shader_trinary_minmax"; +const char* const E_GL_AMD_shader_explicit_vertex_parameter = "GL_AMD_shader_explicit_vertex_parameter"; +const char* const E_GL_AMD_gcn_shader = "GL_AMD_gcn_shader"; +const char* const E_GL_AMD_gpu_shader_half_float = "GL_AMD_gpu_shader_half_float"; +const char* const E_GL_AMD_texture_gather_bias_lod = "GL_AMD_texture_gather_bias_lod"; +const char* const E_GL_AMD_gpu_shader_int16 = "GL_AMD_gpu_shader_int16"; +const char* const E_GL_AMD_shader_image_load_store_lod = "GL_AMD_shader_image_load_store_lod"; +const char* const E_GL_AMD_shader_fragment_mask = "GL_AMD_shader_fragment_mask"; +const char* const E_GL_AMD_gpu_shader_half_float_fetch = "GL_AMD_gpu_shader_half_float_fetch"; + +const char* const E_GL_INTEL_shader_integer_functions2 = "GL_INTEL_shader_integer_functions2"; + +const char* const E_GL_NV_sample_mask_override_coverage = "GL_NV_sample_mask_override_coverage"; +const char* const E_SPV_NV_geometry_shader_passthrough = "GL_NV_geometry_shader_passthrough"; +const char* const E_GL_NV_viewport_array2 = "GL_NV_viewport_array2"; +const char* const E_GL_NV_stereo_view_rendering = "GL_NV_stereo_view_rendering"; +const char* const E_GL_NVX_multiview_per_view_attributes = "GL_NVX_multiview_per_view_attributes"; +const char* const E_GL_NV_shader_atomic_int64 = "GL_NV_shader_atomic_int64"; +const char* const E_GL_NV_conservative_raster_underestimation = "GL_NV_conservative_raster_underestimation"; +const char* const E_GL_NV_shader_noperspective_interpolation = "GL_NV_shader_noperspective_interpolation"; +const char* const E_GL_NV_shader_subgroup_partitioned = "GL_NV_shader_subgroup_partitioned"; +const char* const E_GL_NV_shading_rate_image = "GL_NV_shading_rate_image"; +const char* const E_GL_NV_ray_tracing = "GL_NV_ray_tracing"; +const char* const E_GL_NV_fragment_shader_barycentric = "GL_NV_fragment_shader_barycentric"; +const char* const E_GL_NV_compute_shader_derivatives = "GL_NV_compute_shader_derivatives"; +const char* const E_GL_NV_shader_texture_footprint = "GL_NV_shader_texture_footprint"; +const char* const E_GL_NV_mesh_shader = "GL_NV_mesh_shader"; + +// Arrays of extensions for the above viewportEXTs duplications + +const char* const viewportEXTs[] = { E_GL_ARB_shader_viewport_layer_array, E_GL_NV_viewport_array2 }; +const int Num_viewportEXTs = sizeof(viewportEXTs) / sizeof(viewportEXTs[0]); + +const char* const E_GL_NV_cooperative_matrix = "GL_NV_cooperative_matrix"; +const char* const E_GL_NV_shader_sm_builtins = "GL_NV_shader_sm_builtins"; +const char* const E_GL_NV_integer_cooperative_matrix = "GL_NV_integer_cooperative_matrix"; + +// AEP +const char* const E_GL_ANDROID_extension_pack_es31a = "GL_ANDROID_extension_pack_es31a"; +const char* const E_GL_KHR_blend_equation_advanced = "GL_KHR_blend_equation_advanced"; +const char* const E_GL_OES_sample_variables = "GL_OES_sample_variables"; +const char* const E_GL_OES_shader_image_atomic = "GL_OES_shader_image_atomic"; +const char* const E_GL_OES_shader_multisample_interpolation = "GL_OES_shader_multisample_interpolation"; +const char* const E_GL_OES_texture_storage_multisample_2d_array = "GL_OES_texture_storage_multisample_2d_array"; +const char* const E_GL_EXT_geometry_shader = "GL_EXT_geometry_shader"; +const char* const E_GL_EXT_geometry_point_size = "GL_EXT_geometry_point_size"; +const char* const E_GL_EXT_gpu_shader5 = "GL_EXT_gpu_shader5"; +const char* const E_GL_EXT_primitive_bounding_box = "GL_EXT_primitive_bounding_box"; +const char* const E_GL_EXT_shader_io_blocks = "GL_EXT_shader_io_blocks"; +const char* const E_GL_EXT_tessellation_shader = "GL_EXT_tessellation_shader"; +const char* const E_GL_EXT_tessellation_point_size = "GL_EXT_tessellation_point_size"; +const char* const E_GL_EXT_texture_buffer = "GL_EXT_texture_buffer"; +const char* const E_GL_EXT_texture_cube_map_array = "GL_EXT_texture_cube_map_array"; + +// OES matching AEP +const char* const E_GL_OES_geometry_shader = "GL_OES_geometry_shader"; +const char* const E_GL_OES_geometry_point_size = "GL_OES_geometry_point_size"; +const char* const E_GL_OES_gpu_shader5 = "GL_OES_gpu_shader5"; +const char* const E_GL_OES_primitive_bounding_box = "GL_OES_primitive_bounding_box"; +const char* const E_GL_OES_shader_io_blocks = "GL_OES_shader_io_blocks"; +const char* const E_GL_OES_tessellation_shader = "GL_OES_tessellation_shader"; +const char* const E_GL_OES_tessellation_point_size = "GL_OES_tessellation_point_size"; +const char* const E_GL_OES_texture_buffer = "GL_OES_texture_buffer"; +const char* const E_GL_OES_texture_cube_map_array = "GL_OES_texture_cube_map_array"; + +// EXT +const char* const E_GL_EXT_shader_explicit_arithmetic_types = "GL_EXT_shader_explicit_arithmetic_types"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_int8 = "GL_EXT_shader_explicit_arithmetic_types_int8"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_int16 = "GL_EXT_shader_explicit_arithmetic_types_int16"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_int32 = "GL_EXT_shader_explicit_arithmetic_types_int32"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_int64 = "GL_EXT_shader_explicit_arithmetic_types_int64"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_float16 = "GL_EXT_shader_explicit_arithmetic_types_float16"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_float32 = "GL_EXT_shader_explicit_arithmetic_types_float32"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_float64 = "GL_EXT_shader_explicit_arithmetic_types_float64"; + +const char* const E_GL_EXT_shader_subgroup_extended_types_int8 = "GL_EXT_shader_subgroup_extended_types_int8"; +const char* const E_GL_EXT_shader_subgroup_extended_types_int16 = "GL_EXT_shader_subgroup_extended_types_int16"; +const char* const E_GL_EXT_shader_subgroup_extended_types_int64 = "GL_EXT_shader_subgroup_extended_types_int64"; +const char* const E_GL_EXT_shader_subgroup_extended_types_float16 = "GL_EXT_shader_subgroup_extended_types_float16"; + +// Arrays of extensions for the above AEP duplications + +const char* const AEP_geometry_shader[] = { E_GL_EXT_geometry_shader, E_GL_OES_geometry_shader }; +const int Num_AEP_geometry_shader = sizeof(AEP_geometry_shader)/sizeof(AEP_geometry_shader[0]); + +const char* const AEP_geometry_point_size[] = { E_GL_EXT_geometry_point_size, E_GL_OES_geometry_point_size }; +const int Num_AEP_geometry_point_size = sizeof(AEP_geometry_point_size)/sizeof(AEP_geometry_point_size[0]); + +const char* const AEP_gpu_shader5[] = { E_GL_EXT_gpu_shader5, E_GL_OES_gpu_shader5 }; +const int Num_AEP_gpu_shader5 = sizeof(AEP_gpu_shader5)/sizeof(AEP_gpu_shader5[0]); + +const char* const AEP_primitive_bounding_box[] = { E_GL_EXT_primitive_bounding_box, E_GL_OES_primitive_bounding_box }; +const int Num_AEP_primitive_bounding_box = sizeof(AEP_primitive_bounding_box)/sizeof(AEP_primitive_bounding_box[0]); + +const char* const AEP_shader_io_blocks[] = { E_GL_EXT_shader_io_blocks, E_GL_OES_shader_io_blocks }; +const int Num_AEP_shader_io_blocks = sizeof(AEP_shader_io_blocks)/sizeof(AEP_shader_io_blocks[0]); + +const char* const AEP_tessellation_shader[] = { E_GL_EXT_tessellation_shader, E_GL_OES_tessellation_shader }; +const int Num_AEP_tessellation_shader = sizeof(AEP_tessellation_shader)/sizeof(AEP_tessellation_shader[0]); + +const char* const AEP_tessellation_point_size[] = { E_GL_EXT_tessellation_point_size, E_GL_OES_tessellation_point_size }; +const int Num_AEP_tessellation_point_size = sizeof(AEP_tessellation_point_size)/sizeof(AEP_tessellation_point_size[0]); + +const char* const AEP_texture_buffer[] = { E_GL_EXT_texture_buffer, E_GL_OES_texture_buffer }; +const int Num_AEP_texture_buffer = sizeof(AEP_texture_buffer)/sizeof(AEP_texture_buffer[0]); + +const char* const AEP_texture_cube_map_array[] = { E_GL_EXT_texture_cube_map_array, E_GL_OES_texture_cube_map_array }; +const int Num_AEP_texture_cube_map_array = sizeof(AEP_texture_cube_map_array)/sizeof(AEP_texture_cube_map_array[0]); + +} // end namespace glslang + +#endif // _VERSIONS_INCLUDED_ diff --git a/android/x86/include/glslang/MachineIndependent/attribute.h b/android/x86/include/glslang/MachineIndependent/attribute.h new file mode 100644 index 00000000..38a943d2 --- /dev/null +++ b/android/x86/include/glslang/MachineIndependent/attribute.h @@ -0,0 +1,149 @@ +// +// Copyright (C) 2017 LunarG, Inc. +// Copyright (C) 2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _ATTRIBUTE_INCLUDED_ +#define _ATTRIBUTE_INCLUDED_ + +#include "../Include/Common.h" +#include "../Include/ConstantUnion.h" + +namespace glslang { + + enum TAttributeType { + EatNone, + EatAllow_uav_condition, + EatBranch, + EatCall, + EatDomain, + EatEarlyDepthStencil, + EatFastOpt, + EatFlatten, + EatForceCase, + EatInstance, + EatMaxTessFactor, + EatNumThreads, + EatMaxVertexCount, + EatOutputControlPoints, + EatOutputTopology, + EatPartitioning, + EatPatchConstantFunc, + EatPatchSize, + EatUnroll, + EatLoop, + EatBinding, + EatGlobalBinding, + EatLocation, + EatInputAttachment, + EatBuiltIn, + EatPushConstant, + EatConstantId, + EatDependencyInfinite, + EatDependencyLength, + EatMinIterations, + EatMaxIterations, + EatIterationMultiple, + EatPeelCount, + EatPartialCount, + EatFormatRgba32f, + EatFormatRgba16f, + EatFormatR32f, + EatFormatRgba8, + EatFormatRgba8Snorm, + EatFormatRg32f, + EatFormatRg16f, + EatFormatR11fG11fB10f, + EatFormatR16f, + EatFormatRgba16, + EatFormatRgb10A2, + EatFormatRg16, + EatFormatRg8, + EatFormatR16, + EatFormatR8, + EatFormatRgba16Snorm, + EatFormatRg16Snorm, + EatFormatRg8Snorm, + EatFormatR16Snorm, + EatFormatR8Snorm, + EatFormatRgba32i, + EatFormatRgba16i, + EatFormatRgba8i, + EatFormatR32i, + EatFormatRg32i, + EatFormatRg16i, + EatFormatRg8i, + EatFormatR16i, + EatFormatR8i, + EatFormatRgba32ui, + EatFormatRgba16ui, + EatFormatRgba8ui, + EatFormatR32ui, + EatFormatRgb10a2ui, + EatFormatRg32ui, + EatFormatRg16ui, + EatFormatRg8ui, + EatFormatR16ui, + EatFormatR8ui, + EatFormatUnknown, + EatNonWritable, + EatNonReadable + }; + + class TIntermAggregate; + + struct TAttributeArgs { + TAttributeType name; + const TIntermAggregate* args; + + // Obtain attribute as integer + // Return false if it cannot be obtained + bool getInt(int& value, int argNum = 0) const; + + // Obtain attribute as string, with optional to-lower transform + // Return false if it cannot be obtained + bool getString(TString& value, int argNum = 0, bool convertToLower = true) const; + + // How many arguments were provided to the attribute? + int size() const; + + protected: + const TConstUnion* getConstUnion(TBasicType basicType, int argNum) const; + }; + + typedef TList TAttributes; + +} // end namespace glslang + +#endif // _ATTRIBUTE_INCLUDED_ diff --git a/android/x86/include/glslang/MachineIndependent/gl_types.h b/android/x86/include/glslang/MachineIndependent/gl_types.h new file mode 100644 index 00000000..b6f613bc --- /dev/null +++ b/android/x86/include/glslang/MachineIndependent/gl_types.h @@ -0,0 +1,210 @@ +/* +** Copyright (c) 2013 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +#pragma once + +#define GL_FLOAT 0x1406 +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 + +#define GL_DOUBLE 0x140A +#define GL_DOUBLE_VEC2 0x8FFC +#define GL_DOUBLE_VEC3 0x8FFD +#define GL_DOUBLE_VEC4 0x8FFE + +#define GL_INT 0x1404 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 + +#define GL_UNSIGNED_INT 0x1405 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 + +#define GL_INT64_ARB 0x140E +#define GL_INT64_VEC2_ARB 0x8FE9 +#define GL_INT64_VEC3_ARB 0x8FEA +#define GL_INT64_VEC4_ARB 0x8FEB + +#define GL_UNSIGNED_INT64_ARB 0x140F +#define GL_UNSIGNED_INT64_VEC2_ARB 0x8FE5 +#define GL_UNSIGNED_INT64_VEC3_ARB 0x8FE6 +#define GL_UNSIGNED_INT64_VEC4_ARB 0x8FE7 + +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 + +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A + +#define GL_DOUBLE_MAT2 0x8F46 +#define GL_DOUBLE_MAT3 0x8F47 +#define GL_DOUBLE_MAT4 0x8F48 +#define GL_DOUBLE_MAT2x3 0x8F49 +#define GL_DOUBLE_MAT2x4 0x8F4A +#define GL_DOUBLE_MAT3x2 0x8F4B +#define GL_DOUBLE_MAT3x4 0x8F4C +#define GL_DOUBLE_MAT4x2 0x8F4D +#define GL_DOUBLE_MAT4x3 0x8F4E + +// Those constants are borrowed from extension NV_gpu_shader5 +#define GL_FLOAT16_NV 0x8FF8 +#define GL_FLOAT16_VEC2_NV 0x8FF9 +#define GL_FLOAT16_VEC3_NV 0x8FFA +#define GL_FLOAT16_VEC4_NV 0x8FFB + +#define GL_FLOAT16_MAT2_AMD 0x91C5 +#define GL_FLOAT16_MAT3_AMD 0x91C6 +#define GL_FLOAT16_MAT4_AMD 0x91C7 +#define GL_FLOAT16_MAT2x3_AMD 0x91C8 +#define GL_FLOAT16_MAT2x4_AMD 0x91C9 +#define GL_FLOAT16_MAT3x2_AMD 0x91CA +#define GL_FLOAT16_MAT3x4_AMD 0x91CB +#define GL_FLOAT16_MAT4x2_AMD 0x91CC +#define GL_FLOAT16_MAT4x3_AMD 0x91CD + +#define GL_SAMPLER_1D 0x8B5D +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_SAMPLER_BUFFER 0x8DC2 +#define GL_SAMPLER_1D_ARRAY 0x8DC0 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_SAMPLER_1D_SHADOW 0x8B61 +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_SAMPLER_2D_RECT 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64 +#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 +#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B +#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D +#define GL_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D + +#define GL_FLOAT16_SAMPLER_1D_AMD 0x91CE +#define GL_FLOAT16_SAMPLER_2D_AMD 0x91CF +#define GL_FLOAT16_SAMPLER_3D_AMD 0x91D0 +#define GL_FLOAT16_SAMPLER_CUBE_AMD 0x91D1 +#define GL_FLOAT16_SAMPLER_2D_RECT_AMD 0x91D2 +#define GL_FLOAT16_SAMPLER_1D_ARRAY_AMD 0x91D3 +#define GL_FLOAT16_SAMPLER_2D_ARRAY_AMD 0x91D4 +#define GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_AMD 0x91D5 +#define GL_FLOAT16_SAMPLER_BUFFER_AMD 0x91D6 +#define GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_AMD 0x91D7 +#define GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_ARRAY_AMD 0x91D8 + +#define GL_FLOAT16_SAMPLER_1D_SHADOW_AMD 0x91D9 +#define GL_FLOAT16_SAMPLER_2D_SHADOW_AMD 0x91DA +#define GL_FLOAT16_SAMPLER_2D_RECT_SHADOW_AMD 0x91DB +#define GL_FLOAT16_SAMPLER_1D_ARRAY_SHADOW_AMD 0x91DC +#define GL_FLOAT16_SAMPLER_2D_ARRAY_SHADOW_AMD 0x91DD +#define GL_FLOAT16_SAMPLER_CUBE_SHADOW_AMD 0x91DE +#define GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_SHADOW_AMD 0x91DF + +#define GL_FLOAT16_IMAGE_1D_AMD 0x91E0 +#define GL_FLOAT16_IMAGE_2D_AMD 0x91E1 +#define GL_FLOAT16_IMAGE_3D_AMD 0x91E2 +#define GL_FLOAT16_IMAGE_2D_RECT_AMD 0x91E3 +#define GL_FLOAT16_IMAGE_CUBE_AMD 0x91E4 +#define GL_FLOAT16_IMAGE_1D_ARRAY_AMD 0x91E5 +#define GL_FLOAT16_IMAGE_2D_ARRAY_AMD 0x91E6 +#define GL_FLOAT16_IMAGE_CUBE_MAP_ARRAY_AMD 0x91E7 +#define GL_FLOAT16_IMAGE_BUFFER_AMD 0x91E8 +#define GL_FLOAT16_IMAGE_2D_MULTISAMPLE_AMD 0x91E9 +#define GL_FLOAT16_IMAGE_2D_MULTISAMPLE_ARRAY_AMD 0x91EA + +#define GL_INT_SAMPLER_1D 0x8DC9 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_INT_SAMPLER_2D_RECT 0x8DCD +#define GL_INT_SAMPLER_BUFFER 0x8DD0 +#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 +#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900E + +#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8 +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900F +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A + +#define GL_IMAGE_1D 0x904C +#define GL_IMAGE_2D 0x904D +#define GL_IMAGE_3D 0x904E +#define GL_IMAGE_2D_RECT 0x904F +#define GL_IMAGE_CUBE 0x9050 +#define GL_IMAGE_BUFFER 0x9051 +#define GL_IMAGE_1D_ARRAY 0x9052 +#define GL_IMAGE_2D_ARRAY 0x9053 +#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054 +#define GL_IMAGE_2D_MULTISAMPLE 0x9055 +#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056 +#define GL_INT_IMAGE_1D 0x9057 +#define GL_INT_IMAGE_2D 0x9058 +#define GL_INT_IMAGE_3D 0x9059 +#define GL_INT_IMAGE_2D_RECT 0x905A +#define GL_INT_IMAGE_CUBE 0x905B +#define GL_INT_IMAGE_BUFFER 0x905C +#define GL_INT_IMAGE_1D_ARRAY 0x905D +#define GL_INT_IMAGE_2D_ARRAY 0x905E +#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F +#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060 +#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061 +#define GL_UNSIGNED_INT_IMAGE_1D 0x9062 +#define GL_UNSIGNED_INT_IMAGE_2D 0x9063 +#define GL_UNSIGNED_INT_IMAGE_3D 0x9064 +#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065 +#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066 +#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067 +#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068 +#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069 +#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C + +#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB diff --git a/android/x86/include/glslang/MachineIndependent/glslang_tab.cpp.h b/android/x86/include/glslang/MachineIndependent/glslang_tab.cpp.h new file mode 100644 index 00000000..31c8f902 --- /dev/null +++ b/android/x86/include/glslang/MachineIndependent/glslang_tab.cpp.h @@ -0,0 +1,521 @@ +/* A Bison parser, made by GNU Bison 3.0.4. */ + +/* Bison interface for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +#ifndef YY_YY_GLSLANG_TAB_CPP_H_INCLUDED +# define YY_YY_GLSLANG_TAB_CPP_H_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 1 +#endif +#if YYDEBUG +extern int yydebug; +#endif + +/* Token type. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + enum yytokentype + { + CONST = 258, + BOOL = 259, + INT = 260, + UINT = 261, + FLOAT = 262, + BVEC2 = 263, + BVEC3 = 264, + BVEC4 = 265, + IVEC2 = 266, + IVEC3 = 267, + IVEC4 = 268, + UVEC2 = 269, + UVEC3 = 270, + UVEC4 = 271, + VEC2 = 272, + VEC3 = 273, + VEC4 = 274, + MAT2 = 275, + MAT3 = 276, + MAT4 = 277, + MAT2X2 = 278, + MAT2X3 = 279, + MAT2X4 = 280, + MAT3X2 = 281, + MAT3X3 = 282, + MAT3X4 = 283, + MAT4X2 = 284, + MAT4X3 = 285, + MAT4X4 = 286, + SAMPLER2D = 287, + SAMPLER3D = 288, + SAMPLERCUBE = 289, + SAMPLER2DSHADOW = 290, + SAMPLERCUBESHADOW = 291, + SAMPLER2DARRAY = 292, + SAMPLER2DARRAYSHADOW = 293, + ISAMPLER2D = 294, + ISAMPLER3D = 295, + ISAMPLERCUBE = 296, + ISAMPLER2DARRAY = 297, + USAMPLER2D = 298, + USAMPLER3D = 299, + USAMPLERCUBE = 300, + USAMPLER2DARRAY = 301, + SAMPLER = 302, + SAMPLERSHADOW = 303, + TEXTURE2D = 304, + TEXTURE3D = 305, + TEXTURECUBE = 306, + TEXTURE2DARRAY = 307, + ITEXTURE2D = 308, + ITEXTURE3D = 309, + ITEXTURECUBE = 310, + ITEXTURE2DARRAY = 311, + UTEXTURE2D = 312, + UTEXTURE3D = 313, + UTEXTURECUBE = 314, + UTEXTURE2DARRAY = 315, + ATTRIBUTE = 316, + VARYING = 317, + FLOAT16_T = 318, + FLOAT32_T = 319, + DOUBLE = 320, + FLOAT64_T = 321, + INT64_T = 322, + UINT64_T = 323, + INT32_T = 324, + UINT32_T = 325, + INT16_T = 326, + UINT16_T = 327, + INT8_T = 328, + UINT8_T = 329, + I64VEC2 = 330, + I64VEC3 = 331, + I64VEC4 = 332, + U64VEC2 = 333, + U64VEC3 = 334, + U64VEC4 = 335, + I32VEC2 = 336, + I32VEC3 = 337, + I32VEC4 = 338, + U32VEC2 = 339, + U32VEC3 = 340, + U32VEC4 = 341, + I16VEC2 = 342, + I16VEC3 = 343, + I16VEC4 = 344, + U16VEC2 = 345, + U16VEC3 = 346, + U16VEC4 = 347, + I8VEC2 = 348, + I8VEC3 = 349, + I8VEC4 = 350, + U8VEC2 = 351, + U8VEC3 = 352, + U8VEC4 = 353, + DVEC2 = 354, + DVEC3 = 355, + DVEC4 = 356, + DMAT2 = 357, + DMAT3 = 358, + DMAT4 = 359, + F16VEC2 = 360, + F16VEC3 = 361, + F16VEC4 = 362, + F16MAT2 = 363, + F16MAT3 = 364, + F16MAT4 = 365, + F32VEC2 = 366, + F32VEC3 = 367, + F32VEC4 = 368, + F32MAT2 = 369, + F32MAT3 = 370, + F32MAT4 = 371, + F64VEC2 = 372, + F64VEC3 = 373, + F64VEC4 = 374, + F64MAT2 = 375, + F64MAT3 = 376, + F64MAT4 = 377, + DMAT2X2 = 378, + DMAT2X3 = 379, + DMAT2X4 = 380, + DMAT3X2 = 381, + DMAT3X3 = 382, + DMAT3X4 = 383, + DMAT4X2 = 384, + DMAT4X3 = 385, + DMAT4X4 = 386, + F16MAT2X2 = 387, + F16MAT2X3 = 388, + F16MAT2X4 = 389, + F16MAT3X2 = 390, + F16MAT3X3 = 391, + F16MAT3X4 = 392, + F16MAT4X2 = 393, + F16MAT4X3 = 394, + F16MAT4X4 = 395, + F32MAT2X2 = 396, + F32MAT2X3 = 397, + F32MAT2X4 = 398, + F32MAT3X2 = 399, + F32MAT3X3 = 400, + F32MAT3X4 = 401, + F32MAT4X2 = 402, + F32MAT4X3 = 403, + F32MAT4X4 = 404, + F64MAT2X2 = 405, + F64MAT2X3 = 406, + F64MAT2X4 = 407, + F64MAT3X2 = 408, + F64MAT3X3 = 409, + F64MAT3X4 = 410, + F64MAT4X2 = 411, + F64MAT4X3 = 412, + F64MAT4X4 = 413, + ATOMIC_UINT = 414, + ACCSTRUCTNV = 415, + ACCSTRUCTEXT = 416, + RAYQUERYEXT = 417, + FCOOPMATNV = 418, + ICOOPMATNV = 419, + UCOOPMATNV = 420, + SAMPLERCUBEARRAY = 421, + SAMPLERCUBEARRAYSHADOW = 422, + ISAMPLERCUBEARRAY = 423, + USAMPLERCUBEARRAY = 424, + SAMPLER1D = 425, + SAMPLER1DARRAY = 426, + SAMPLER1DARRAYSHADOW = 427, + ISAMPLER1D = 428, + SAMPLER1DSHADOW = 429, + SAMPLER2DRECT = 430, + SAMPLER2DRECTSHADOW = 431, + ISAMPLER2DRECT = 432, + USAMPLER2DRECT = 433, + SAMPLERBUFFER = 434, + ISAMPLERBUFFER = 435, + USAMPLERBUFFER = 436, + SAMPLER2DMS = 437, + ISAMPLER2DMS = 438, + USAMPLER2DMS = 439, + SAMPLER2DMSARRAY = 440, + ISAMPLER2DMSARRAY = 441, + USAMPLER2DMSARRAY = 442, + SAMPLEREXTERNALOES = 443, + SAMPLEREXTERNAL2DY2YEXT = 444, + ISAMPLER1DARRAY = 445, + USAMPLER1D = 446, + USAMPLER1DARRAY = 447, + F16SAMPLER1D = 448, + F16SAMPLER2D = 449, + F16SAMPLER3D = 450, + F16SAMPLER2DRECT = 451, + F16SAMPLERCUBE = 452, + F16SAMPLER1DARRAY = 453, + F16SAMPLER2DARRAY = 454, + F16SAMPLERCUBEARRAY = 455, + F16SAMPLERBUFFER = 456, + F16SAMPLER2DMS = 457, + F16SAMPLER2DMSARRAY = 458, + F16SAMPLER1DSHADOW = 459, + F16SAMPLER2DSHADOW = 460, + F16SAMPLER1DARRAYSHADOW = 461, + F16SAMPLER2DARRAYSHADOW = 462, + F16SAMPLER2DRECTSHADOW = 463, + F16SAMPLERCUBESHADOW = 464, + F16SAMPLERCUBEARRAYSHADOW = 465, + IMAGE1D = 466, + IIMAGE1D = 467, + UIMAGE1D = 468, + IMAGE2D = 469, + IIMAGE2D = 470, + UIMAGE2D = 471, + IMAGE3D = 472, + IIMAGE3D = 473, + UIMAGE3D = 474, + IMAGE2DRECT = 475, + IIMAGE2DRECT = 476, + UIMAGE2DRECT = 477, + IMAGECUBE = 478, + IIMAGECUBE = 479, + UIMAGECUBE = 480, + IMAGEBUFFER = 481, + IIMAGEBUFFER = 482, + UIMAGEBUFFER = 483, + IMAGE1DARRAY = 484, + IIMAGE1DARRAY = 485, + UIMAGE1DARRAY = 486, + IMAGE2DARRAY = 487, + IIMAGE2DARRAY = 488, + UIMAGE2DARRAY = 489, + IMAGECUBEARRAY = 490, + IIMAGECUBEARRAY = 491, + UIMAGECUBEARRAY = 492, + IMAGE2DMS = 493, + IIMAGE2DMS = 494, + UIMAGE2DMS = 495, + IMAGE2DMSARRAY = 496, + IIMAGE2DMSARRAY = 497, + UIMAGE2DMSARRAY = 498, + F16IMAGE1D = 499, + F16IMAGE2D = 500, + F16IMAGE3D = 501, + F16IMAGE2DRECT = 502, + F16IMAGECUBE = 503, + F16IMAGE1DARRAY = 504, + F16IMAGE2DARRAY = 505, + F16IMAGECUBEARRAY = 506, + F16IMAGEBUFFER = 507, + F16IMAGE2DMS = 508, + F16IMAGE2DMSARRAY = 509, + TEXTURECUBEARRAY = 510, + ITEXTURECUBEARRAY = 511, + UTEXTURECUBEARRAY = 512, + TEXTURE1D = 513, + ITEXTURE1D = 514, + UTEXTURE1D = 515, + TEXTURE1DARRAY = 516, + ITEXTURE1DARRAY = 517, + UTEXTURE1DARRAY = 518, + TEXTURE2DRECT = 519, + ITEXTURE2DRECT = 520, + UTEXTURE2DRECT = 521, + TEXTUREBUFFER = 522, + ITEXTUREBUFFER = 523, + UTEXTUREBUFFER = 524, + TEXTURE2DMS = 525, + ITEXTURE2DMS = 526, + UTEXTURE2DMS = 527, + TEXTURE2DMSARRAY = 528, + ITEXTURE2DMSARRAY = 529, + UTEXTURE2DMSARRAY = 530, + F16TEXTURE1D = 531, + F16TEXTURE2D = 532, + F16TEXTURE3D = 533, + F16TEXTURE2DRECT = 534, + F16TEXTURECUBE = 535, + F16TEXTURE1DARRAY = 536, + F16TEXTURE2DARRAY = 537, + F16TEXTURECUBEARRAY = 538, + F16TEXTUREBUFFER = 539, + F16TEXTURE2DMS = 540, + F16TEXTURE2DMSARRAY = 541, + SUBPASSINPUT = 542, + SUBPASSINPUTMS = 543, + ISUBPASSINPUT = 544, + ISUBPASSINPUTMS = 545, + USUBPASSINPUT = 546, + USUBPASSINPUTMS = 547, + F16SUBPASSINPUT = 548, + F16SUBPASSINPUTMS = 549, + LEFT_OP = 550, + RIGHT_OP = 551, + INC_OP = 552, + DEC_OP = 553, + LE_OP = 554, + GE_OP = 555, + EQ_OP = 556, + NE_OP = 557, + AND_OP = 558, + OR_OP = 559, + XOR_OP = 560, + MUL_ASSIGN = 561, + DIV_ASSIGN = 562, + ADD_ASSIGN = 563, + MOD_ASSIGN = 564, + LEFT_ASSIGN = 565, + RIGHT_ASSIGN = 566, + AND_ASSIGN = 567, + XOR_ASSIGN = 568, + OR_ASSIGN = 569, + SUB_ASSIGN = 570, + STRING_LITERAL = 571, + LEFT_PAREN = 572, + RIGHT_PAREN = 573, + LEFT_BRACKET = 574, + RIGHT_BRACKET = 575, + LEFT_BRACE = 576, + RIGHT_BRACE = 577, + DOT = 578, + COMMA = 579, + COLON = 580, + EQUAL = 581, + SEMICOLON = 582, + BANG = 583, + DASH = 584, + TILDE = 585, + PLUS = 586, + STAR = 587, + SLASH = 588, + PERCENT = 589, + LEFT_ANGLE = 590, + RIGHT_ANGLE = 591, + VERTICAL_BAR = 592, + CARET = 593, + AMPERSAND = 594, + QUESTION = 595, + INVARIANT = 596, + HIGH_PRECISION = 597, + MEDIUM_PRECISION = 598, + LOW_PRECISION = 599, + PRECISION = 600, + PACKED = 601, + RESOURCE = 602, + SUPERP = 603, + FLOATCONSTANT = 604, + INTCONSTANT = 605, + UINTCONSTANT = 606, + BOOLCONSTANT = 607, + IDENTIFIER = 608, + TYPE_NAME = 609, + CENTROID = 610, + IN = 611, + OUT = 612, + INOUT = 613, + STRUCT = 614, + VOID = 615, + WHILE = 616, + BREAK = 617, + CONTINUE = 618, + DO = 619, + ELSE = 620, + FOR = 621, + IF = 622, + DISCARD = 623, + RETURN = 624, + SWITCH = 625, + CASE = 626, + DEFAULT = 627, + UNIFORM = 628, + SHARED = 629, + BUFFER = 630, + FLAT = 631, + SMOOTH = 632, + LAYOUT = 633, + DOUBLECONSTANT = 634, + INT16CONSTANT = 635, + UINT16CONSTANT = 636, + FLOAT16CONSTANT = 637, + INT32CONSTANT = 638, + UINT32CONSTANT = 639, + INT64CONSTANT = 640, + UINT64CONSTANT = 641, + SUBROUTINE = 642, + DEMOTE = 643, + PAYLOADNV = 644, + PAYLOADINNV = 645, + HITATTRNV = 646, + CALLDATANV = 647, + CALLDATAINNV = 648, + PAYLOADEXT = 649, + PAYLOADINEXT = 650, + HITATTREXT = 651, + CALLDATAEXT = 652, + CALLDATAINEXT = 653, + PATCH = 654, + SAMPLE = 655, + NONUNIFORM = 656, + COHERENT = 657, + VOLATILE = 658, + RESTRICT = 659, + READONLY = 660, + WRITEONLY = 661, + DEVICECOHERENT = 662, + QUEUEFAMILYCOHERENT = 663, + WORKGROUPCOHERENT = 664, + SUBGROUPCOHERENT = 665, + NONPRIVATE = 666, + SHADERCALLCOHERENT = 667, + NOPERSPECTIVE = 668, + EXPLICITINTERPAMD = 669, + PERVERTEXNV = 670, + PERPRIMITIVENV = 671, + PERVIEWNV = 672, + PERTASKNV = 673, + PRECISE = 674 + }; +#endif + +/* Value type. */ +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED + +union YYSTYPE +{ +#line 97 "glslang.y" /* yacc.c:1909 */ + + struct { + glslang::TSourceLoc loc; + union { + glslang::TString *string; + int i; + unsigned int u; + long long i64; + unsigned long long u64; + bool b; + double d; + }; + glslang::TSymbol* symbol; + } lex; + struct { + glslang::TSourceLoc loc; + glslang::TOperator op; + union { + TIntermNode* intermNode; + glslang::TIntermNodePair nodePair; + glslang::TIntermTyped* intermTypedNode; + glslang::TAttributes* attributes; + }; + union { + glslang::TPublicType type; + glslang::TFunction* function; + glslang::TParameter param; + glslang::TTypeLoc typeLine; + glslang::TTypeList* typeList; + glslang::TArraySizes* arraySizes; + glslang::TIdentifierList* identifierList; + }; + glslang::TArraySizes* typeParameters; + } interm; + +#line 510 "glslang_tab.cpp.h" /* yacc.c:1909 */ +}; + +typedef union YYSTYPE YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif + + + +int yyparse (glslang::TParseContext* pParseContext); + +#endif /* !YY_YY_GLSLANG_TAB_CPP_H_INCLUDED */ diff --git a/android/x86/include/glslang/MachineIndependent/iomapper.h b/android/x86/include/glslang/MachineIndependent/iomapper.h new file mode 100644 index 00000000..13a8932b --- /dev/null +++ b/android/x86/include/glslang/MachineIndependent/iomapper.h @@ -0,0 +1,300 @@ +// +// Copyright (C) 2016 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef GLSLANG_WEB + +#ifndef _IOMAPPER_INCLUDED +#define _IOMAPPER_INCLUDED + +#include +#include "LiveTraverser.h" +#include +#include +// +// A reflection database and its interface, consistent with the OpenGL API reflection queries. +// + +class TInfoSink; + +namespace glslang { + +class TIntermediate; +struct TVarEntryInfo { + int id; + TIntermSymbol* symbol; + bool live; + int newBinding; + int newSet; + int newLocation; + int newComponent; + int newIndex; + EShLanguage stage; + struct TOrderById { + inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) { return l.id < r.id; } + }; + + struct TOrderByPriority { + // ordering: + // 1) has both binding and set + // 2) has binding but no set + // 3) has no binding but set + // 4) has no binding and no set + inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) { + const TQualifier& lq = l.symbol->getQualifier(); + const TQualifier& rq = r.symbol->getQualifier(); + + // simple rules: + // has binding gives 2 points + // has set gives 1 point + // who has the most points is more important. + int lPoints = (lq.hasBinding() ? 2 : 0) + (lq.hasSet() ? 1 : 0); + int rPoints = (rq.hasBinding() ? 2 : 0) + (rq.hasSet() ? 1 : 0); + + if (lPoints == rPoints) + return l.id < r.id; + return lPoints > rPoints; + } + }; +}; + +// Base class for shared TIoMapResolver services, used by several derivations. +struct TDefaultIoResolverBase : public glslang::TIoMapResolver { +public: + TDefaultIoResolverBase(const TIntermediate& intermediate); + typedef std::vector TSlotSet; + typedef std::unordered_map TSlotSetMap; + + // grow the reflection stage by stage + void notifyBinding(EShLanguage, TVarEntryInfo& /*ent*/) override {} + void notifyInOut(EShLanguage, TVarEntryInfo& /*ent*/) override {} + void beginNotifications(EShLanguage) override {} + void endNotifications(EShLanguage) override {} + void beginResolve(EShLanguage) override {} + void endResolve(EShLanguage) override {} + void beginCollect(EShLanguage) override {} + void endCollect(EShLanguage) override {} + void reserverResourceSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {} + void reserverStorageSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {} + int getBaseBinding(TResourceType res, unsigned int set) const; + const std::vector& getResourceSetBinding() const; + virtual TResourceType getResourceType(const glslang::TType& type) = 0; + bool doAutoBindingMapping() const; + bool doAutoLocationMapping() const; + TSlotSet::iterator findSlot(int set, int slot); + bool checkEmpty(int set, int slot); + bool validateInOut(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; } + int reserveSlot(int set, int slot, int size = 1); + int getFreeSlot(int set, int base, int size = 1); + int resolveSet(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + int resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override; + int resolveInOutComponent(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + int resolveInOutIndex(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + void addStage(EShLanguage stage) override { + if (stage < EShLangCount) + stageMask[stage] = true; + } + uint32_t computeTypeLocationSize(const TType& type, EShLanguage stage); + + TSlotSetMap slots; + bool hasError = false; + +protected: + TDefaultIoResolverBase(TDefaultIoResolverBase&); + TDefaultIoResolverBase& operator=(TDefaultIoResolverBase&); + const TIntermediate& intermediate; + int nextUniformLocation; + int nextInputLocation; + int nextOutputLocation; + bool stageMask[EShLangCount + 1]; + // Return descriptor set specific base if there is one, and the generic base otherwise. + int selectBaseBinding(int base, int descriptorSetBase) const { + return descriptorSetBase != -1 ? descriptorSetBase : base; + } + + static int getLayoutSet(const glslang::TType& type) { + if (type.getQualifier().hasSet()) + return type.getQualifier().layoutSet; + else + return 0; + } + + static bool isSamplerType(const glslang::TType& type) { + return type.getBasicType() == glslang::EbtSampler && type.getSampler().isPureSampler(); + } + + static bool isTextureType(const glslang::TType& type) { + return (type.getBasicType() == glslang::EbtSampler && + (type.getSampler().isTexture() || type.getSampler().isSubpass())); + } + + static bool isUboType(const glslang::TType& type) { + return type.getQualifier().storage == EvqUniform; + } + + static bool isImageType(const glslang::TType& type) { + return type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage(); + } + + static bool isSsboType(const glslang::TType& type) { + return type.getQualifier().storage == EvqBuffer; + } + + // Return true if this is a SRV (shader resource view) type: + static bool isSrvType(const glslang::TType& type) { + return isTextureType(type) || type.getQualifier().storage == EvqBuffer; + } + + // Return true if this is a UAV (unordered access view) type: + static bool isUavType(const glslang::TType& type) { + if (type.getQualifier().isReadOnly()) + return false; + return (type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage()) || + (type.getQualifier().storage == EvqBuffer); + } +}; + +// Defaulf I/O resolver for OpenGL +struct TDefaultGlslIoResolver : public TDefaultIoResolverBase { +public: + typedef std::map TVarSlotMap; // + typedef std::map TSlotMap; // + TDefaultGlslIoResolver(const TIntermediate& intermediate); + bool validateBinding(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; } + TResourceType getResourceType(const glslang::TType& type) override; + int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override; + int resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + int resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + void beginResolve(EShLanguage /*stage*/) override; + void endResolve(EShLanguage stage) override; + void beginCollect(EShLanguage) override; + void endCollect(EShLanguage) override; + void reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override; + void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override; + // in/out symbol and uniform symbol are stored in the same resourceSlotMap, the storage key is used to identify each type of symbol. + // We use stage and storage qualifier to construct a storage key. it can help us identify the same storage resource used in different stage. + // if a resource is a program resource and we don't need know it usage stage, we can use same stage to build storage key. + // Note: both stage and type must less then 0xffff. + int buildStorageKey(EShLanguage stage, TStorageQualifier type) { + assert(static_cast(stage) <= 0x0000ffff && static_cast(type) <= 0x0000ffff); + return (stage << 16) | type; + } + +protected: + // Use for mark pre stage, to get more interface symbol information. + EShLanguage preStage; + // Use for mark current shader stage for resolver + EShLanguage currentStage; + // Slot map for storage resource(location of uniform and interface symbol) It's a program share slot + TSlotMap resourceSlotMap; + // Slot map for other resource(image, ubo, ssbo), It's a program share slot. + TSlotMap storageSlotMap; +}; + +typedef std::map TVarLiveMap; + +// override function "operator=", if a vector being sort, +// when use vc++, the sort function will call : +// pair& operator=(const pair<_Other1, _Other2>& _Right) +// { +// first = _Right.first; +// second = _Right.second; +// return (*this); +// } +// that will make a const type handing on left. +// override this function can avoid a compiler error. +// In the future, if the vc++ compiler can handle such a situation, +// this part of the code will be removed. +struct TVarLivePair : std::pair { + TVarLivePair(std::pair& _Right) : pair(_Right.first, _Right.second) {} + TVarLivePair& operator=(const TVarLivePair& _Right) { + const_cast(first) = _Right.first; + second = _Right.second; + return (*this); + } +}; +typedef std::vector TVarLiveVector; + +// I/O mapper +class TIoMapper { +public: + TIoMapper() {} + virtual ~TIoMapper() {} + // grow the reflection stage by stage + bool virtual addStage(EShLanguage, TIntermediate&, TInfoSink&, TIoMapResolver*); + bool virtual doMap(TIoMapResolver*, TInfoSink&) { return true; } +}; + +// I/O mapper for OpenGL +class TGlslIoMapper : public TIoMapper { +public: + TGlslIoMapper() { + memset(inVarMaps, 0, sizeof(TVarLiveMap*) * EShLangCount); + memset(outVarMaps, 0, sizeof(TVarLiveMap*) * EShLangCount); + memset(uniformVarMap, 0, sizeof(TVarLiveMap*) * EShLangCount); + memset(intermediates, 0, sizeof(TIntermediate*) * EShLangCount); + } + virtual ~TGlslIoMapper() { + for (size_t stage = 0; stage < EShLangCount; stage++) { + if (inVarMaps[stage] != nullptr) { + delete inVarMaps[stage]; + inVarMaps[stage] = nullptr; + } + if (outVarMaps[stage] != nullptr) { + delete outVarMaps[stage]; + outVarMaps[stage] = nullptr; + } + if (uniformVarMap[stage] != nullptr) { + delete uniformVarMap[stage]; + uniformVarMap[stage] = nullptr; + } + if (intermediates[stage] != nullptr) + intermediates[stage] = nullptr; + } + } + // grow the reflection stage by stage + bool addStage(EShLanguage, TIntermediate&, TInfoSink&, TIoMapResolver*) override; + bool doMap(TIoMapResolver*, TInfoSink&) override; + TVarLiveMap *inVarMaps[EShLangCount], *outVarMaps[EShLangCount], + *uniformVarMap[EShLangCount]; + TIntermediate* intermediates[EShLangCount]; + bool hadError = false; +}; + +} // end namespace glslang + +#endif // _IOMAPPER_INCLUDED + +#endif // GLSLANG_WEB diff --git a/android/x86/include/glslang/MachineIndependent/localintermediate.h b/android/x86/include/glslang/MachineIndependent/localintermediate.h new file mode 100644 index 00000000..66f5a88a --- /dev/null +++ b/android/x86/include/glslang/MachineIndependent/localintermediate.h @@ -0,0 +1,1013 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2016 LunarG, Inc. +// Copyright (C) 2017 ARM Limited. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _LOCAL_INTERMEDIATE_INCLUDED_ +#define _LOCAL_INTERMEDIATE_INCLUDED_ + +#include "../Include/intermediate.h" +#include "../Public/ShaderLang.h" +#include "Versions.h" + +#include +#include +#include +#include +#include + +class TInfoSink; + +namespace glslang { + +struct TMatrixSelector { + int coord1; // stay agnostic about column/row; this is parse order + int coord2; +}; + +typedef int TVectorSelector; + +const int MaxSwizzleSelectors = 4; + +template +class TSwizzleSelectors { +public: + TSwizzleSelectors() : size_(0) { } + + void push_back(selectorType comp) + { + if (size_ < MaxSwizzleSelectors) + components[size_++] = comp; + } + void resize(int s) + { + assert(s <= size_); + size_ = s; + } + int size() const { return size_; } + selectorType operator[](int i) const + { + assert(i < MaxSwizzleSelectors); + return components[i]; + } + +private: + int size_; + selectorType components[MaxSwizzleSelectors]; +}; + +// +// Some helper structures for TIntermediate. Their contents are encapsulated +// by TIntermediate. +// + +// Used for call-graph algorithms for detecting recursion, missing bodies, and dead bodies. +// A "call" is a pair: . +// There can be duplicates. General assumption is the list is small. +struct TCall { + TCall(const TString& pCaller, const TString& pCallee) : caller(pCaller), callee(pCallee) { } + TString caller; + TString callee; + bool visited; + bool currentPath; + bool errorGiven; + int calleeBodyPosition; +}; + +// A generic 1-D range. +struct TRange { + TRange(int start, int last) : start(start), last(last) { } + bool overlap(const TRange& rhs) const + { + return last >= rhs.start && start <= rhs.last; + } + int start; + int last; +}; + +// An IO range is a 3-D rectangle; the set of (location, component, index) triples all lying +// within the same location range, component range, and index value. Locations don't alias unless +// all other dimensions of their range overlap. +struct TIoRange { + TIoRange(TRange location, TRange component, TBasicType basicType, int index) + : location(location), component(component), basicType(basicType), index(index) { } + bool overlap(const TIoRange& rhs) const + { + return location.overlap(rhs.location) && component.overlap(rhs.component) && index == rhs.index; + } + TRange location; + TRange component; + TBasicType basicType; + int index; +}; + +// An offset range is a 2-D rectangle; the set of (binding, offset) pairs all lying +// within the same binding and offset range. +struct TOffsetRange { + TOffsetRange(TRange binding, TRange offset) + : binding(binding), offset(offset) { } + bool overlap(const TOffsetRange& rhs) const + { + return binding.overlap(rhs.binding) && offset.overlap(rhs.offset); + } + TRange binding; + TRange offset; +}; + +#ifndef GLSLANG_WEB +// Things that need to be tracked per xfb buffer. +struct TXfbBuffer { + TXfbBuffer() : stride(TQualifier::layoutXfbStrideEnd), implicitStride(0), contains64BitType(false), + contains32BitType(false), contains16BitType(false) { } + std::vector ranges; // byte offsets that have already been assigned + unsigned int stride; + unsigned int implicitStride; + bool contains64BitType; + bool contains32BitType; + bool contains16BitType; +}; +#endif + +// Track a set of strings describing how the module was processed. +// This includes command line options, transforms, etc., ideally inclusive enough +// to reproduce the steps used to transform the input source to the output. +// E.g., see SPIR-V OpModuleProcessed. +// Each "process" or "transform" uses is expressed in the form: +// process arg0 arg1 arg2 ... +// process arg0 arg1 arg2 ... +// where everything is textual, and there can be zero or more arguments +class TProcesses { +public: + TProcesses() {} + ~TProcesses() {} + + void addProcess(const char* process) + { + processes.push_back(process); + } + void addProcess(const std::string& process) + { + processes.push_back(process); + } + void addArgument(int arg) + { + processes.back().append(" "); + std::string argString = std::to_string(arg); + processes.back().append(argString); + } + void addArgument(const char* arg) + { + processes.back().append(" "); + processes.back().append(arg); + } + void addArgument(const std::string& arg) + { + processes.back().append(" "); + processes.back().append(arg); + } + void addIfNonZero(const char* process, int value) + { + if (value != 0) { + addProcess(process); + addArgument(value); + } + } + + const std::vector& getProcesses() const { return processes; } + +private: + std::vector processes; +}; + +class TSymbolTable; +class TSymbol; +class TVariable; + +// +// Texture and Sampler transformation mode. +// +enum ComputeDerivativeMode { + LayoutDerivativeNone, // default layout as SPV_NV_compute_shader_derivatives not enabled + LayoutDerivativeGroupQuads, // derivative_group_quadsNV + LayoutDerivativeGroupLinear, // derivative_group_linearNV +}; + +class TIdMaps { +public: + TMap& operator[](int i) { return maps[i]; } + const TMap& operator[](int i) const { return maps[i]; } +private: + TMap maps[EsiCount]; +}; + + +// +// Set of helper functions to help parse and build the tree. +// +class TIntermediate { +public: + explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) : + language(l), + profile(p), version(v), treeRoot(0), + numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false), + invertY(false), + useStorageBuffer(false), + nanMinMaxClamp(false), + depthReplacing(false) +#ifndef GLSLANG_WEB + , + implicitThisName("@this"), implicitCounterName("@count"), + source(EShSourceNone), + useVulkanMemoryModel(false), + invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet), + inputPrimitive(ElgNone), outputPrimitive(ElgNone), + pixelCenterInteger(false), originUpperLeft(false), + vertexSpacing(EvsNone), vertexOrder(EvoNone), interlockOrdering(EioNone), pointMode(false), earlyFragmentTests(false), + postDepthCoverage(false), depthLayout(EldNone), + hlslFunctionality1(false), + blendEquations(0), xfbMode(false), multiStream(false), + layoutOverrideCoverage(false), + geoPassthroughEXT(false), + numShaderRecordBlocks(0), + computeDerivativeMode(LayoutDerivativeNone), + primitives(TQualifier::layoutNotSet), + numTaskNVBlocks(0), + autoMapBindings(false), + autoMapLocations(false), + flattenUniformArrays(false), + useUnknownFormat(false), + hlslOffsets(false), + hlslIoMapping(false), + useVariablePointers(false), + textureSamplerTransformMode(EShTexSampTransKeep), + needToLegalize(false), + binaryDoubleOutput(false), + usePhysicalStorageBuffer(false), + uniformLocationBase(0) +#endif + { + localSize[0] = 1; + localSize[1] = 1; + localSize[2] = 1; + localSizeNotDefault[0] = false; + localSizeNotDefault[1] = false; + localSizeNotDefault[2] = false; + localSizeSpecId[0] = TQualifier::layoutNotSet; + localSizeSpecId[1] = TQualifier::layoutNotSet; + localSizeSpecId[2] = TQualifier::layoutNotSet; +#ifndef GLSLANG_WEB + xfbBuffers.resize(TQualifier::layoutXfbBufferEnd); + shiftBinding.fill(0); +#endif + } + + void setVersion(int v) { version = v; } + int getVersion() const { return version; } + void setProfile(EProfile p) { profile = p; } + EProfile getProfile() const { return profile; } + void setSpv(const SpvVersion& s) + { + spvVersion = s; + + // client processes + if (spvVersion.vulkan > 0) + processes.addProcess("client vulkan100"); + if (spvVersion.openGl > 0) + processes.addProcess("client opengl100"); + + // target SPV + switch (spvVersion.spv) { + case 0: + break; + case EShTargetSpv_1_0: + break; + case EShTargetSpv_1_1: + processes.addProcess("target-env spirv1.1"); + break; + case EShTargetSpv_1_2: + processes.addProcess("target-env spirv1.2"); + break; + case EShTargetSpv_1_3: + processes.addProcess("target-env spirv1.3"); + break; + case EShTargetSpv_1_4: + processes.addProcess("target-env spirv1.4"); + break; + case EShTargetSpv_1_5: + processes.addProcess("target-env spirv1.5"); + break; + default: + processes.addProcess("target-env spirvUnknown"); + break; + } + + // target-environment processes + switch (spvVersion.vulkan) { + case 0: + break; + case EShTargetVulkan_1_0: + processes.addProcess("target-env vulkan1.0"); + break; + case EShTargetVulkan_1_1: + processes.addProcess("target-env vulkan1.1"); + break; + case EShTargetVulkan_1_2: + processes.addProcess("target-env vulkan1.2"); + break; + default: + processes.addProcess("target-env vulkanUnknown"); + break; + } + if (spvVersion.openGl > 0) + processes.addProcess("target-env opengl"); + } + const SpvVersion& getSpv() const { return spvVersion; } + EShLanguage getStage() const { return language; } + void addRequestedExtension(const char* extension) { requestedExtensions.insert(extension); } + const std::set& getRequestedExtensions() const { return requestedExtensions; } + + void setTreeRoot(TIntermNode* r) { treeRoot = r; } + TIntermNode* getTreeRoot() const { return treeRoot; } + void incrementEntryPointCount() { ++numEntryPoints; } + int getNumEntryPoints() const { return numEntryPoints; } + int getNumErrors() const { return numErrors; } + void addPushConstantCount() { ++numPushConstants; } + void setLimits(const TBuiltInResource& r) { resources = r; } + + bool postProcess(TIntermNode*, EShLanguage); + void removeTree(); + + void setEntryPointName(const char* ep) + { + entryPointName = ep; + processes.addProcess("entry-point"); + processes.addArgument(entryPointName); + } + void setEntryPointMangledName(const char* ep) { entryPointMangledName = ep; } + const std::string& getEntryPointName() const { return entryPointName; } + const std::string& getEntryPointMangledName() const { return entryPointMangledName; } + + void setInvertY(bool invert) + { + invertY = invert; + if (invertY) + processes.addProcess("invert-y"); + } + bool getInvertY() const { return invertY; } + +#ifdef ENABLE_HLSL + void setSource(EShSource s) { source = s; } + EShSource getSource() const { return source; } +#else + void setSource(EShSource s) { assert(s == EShSourceGlsl); } + EShSource getSource() const { return EShSourceGlsl; } +#endif + + bool isRecursive() const { return recursive; } + + TIntermSymbol* addSymbol(const TVariable&); + TIntermSymbol* addSymbol(const TVariable&, const TSourceLoc&); + TIntermSymbol* addSymbol(const TType&, const TSourceLoc&); + TIntermSymbol* addSymbol(const TIntermSymbol&); + TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*); + std::tuple addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1); + TIntermTyped* addUniShapeConversion(TOperator, const TType&, TIntermTyped*); + TIntermTyped* addConversion(TBasicType convertTo, TIntermTyped* node) const; + void addBiShapeConversion(TOperator, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode); + TIntermTyped* addShapeConversion(const TType&, TIntermTyped*); + TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc); + TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc); + TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc); + TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, TSourceLoc); + TIntermTyped* addBuiltInFunctionCall(const TSourceLoc& line, TOperator, bool unary, TIntermNode*, const TType& returnType); + bool canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op = EOpNull) const; + bool isIntegralPromotion(TBasicType from, TBasicType to) const; + bool isFPPromotion(TBasicType from, TBasicType to) const; + bool isIntegralConversion(TBasicType from, TBasicType to) const; + bool isFPConversion(TBasicType from, TBasicType to) const; + bool isFPIntegralConversion(TBasicType from, TBasicType to) const; + TOperator mapTypeToConstructorOp(const TType&) const; + TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right); + TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&); + TIntermAggregate* makeAggregate(TIntermNode* node); + TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&); + TIntermAggregate* makeAggregate(const TSourceLoc&); + TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, TSourceLoc); + bool areAllChildConst(TIntermAggregate* aggrNode); + TIntermSelection* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&); + TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&); + TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); + TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, const TSourceLoc&); + TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(signed char, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(unsigned char, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(signed short, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(unsigned short, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(int, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(unsigned int, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(long long, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(unsigned long long, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(bool, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(double, TBasicType, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(const TString*, const TSourceLoc&, bool literal = false) const; + TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const; + bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false); + TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&); + TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, + const TSourceLoc&, TIntermLoop*&); + TIntermBranch* addBranch(TOperator, const TSourceLoc&); + TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&); + template TIntermTyped* addSwizzle(TSwizzleSelectors&, const TSourceLoc&); + + // Low level functions to add nodes (no conversions or other higher level transformations) + // If a type is provided, the node's type will be set to it. + TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc) const; + TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, const TType&) const; + TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc) const; + TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc, const TType&) const; + + // Constant folding (in Constant.cpp) + TIntermTyped* fold(TIntermAggregate* aggrNode); + TIntermTyped* foldConstructor(TIntermAggregate* aggrNode); + TIntermTyped* foldDereference(TIntermTyped* node, int index, const TSourceLoc&); + TIntermTyped* foldSwizzle(TIntermTyped* node, TSwizzleSelectors& fields, const TSourceLoc&); + + // Tree ops + static const TIntermTyped* findLValueBase(const TIntermTyped*, bool swizzleOkay); + + // Linkage related + void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&); + void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&); + + void setUseStorageBuffer() + { + useStorageBuffer = true; + processes.addProcess("use-storage-buffer"); + } + bool usingStorageBuffer() const { return useStorageBuffer; } + void setDepthReplacing() { depthReplacing = true; } + bool isDepthReplacing() const { return depthReplacing; } + bool setLocalSize(int dim, int size) + { + if (localSizeNotDefault[dim]) + return size == localSize[dim]; + localSizeNotDefault[dim] = true; + localSize[dim] = size; + return true; + } + unsigned int getLocalSize(int dim) const { return localSize[dim]; } + bool setLocalSizeSpecId(int dim, int id) + { + if (localSizeSpecId[dim] != TQualifier::layoutNotSet) + return id == localSizeSpecId[dim]; + localSizeSpecId[dim] = id; + return true; + } + int getLocalSizeSpecId(int dim) const { return localSizeSpecId[dim]; } +#ifdef GLSLANG_WEB + void output(TInfoSink&, bool tree) { } + + bool isEsProfile() const { return false; } + bool getXfbMode() const { return false; } + bool isMultiStream() const { return false; } + TLayoutGeometry getOutputPrimitive() const { return ElgNone; } + bool getPostDepthCoverage() const { return false; } + bool getEarlyFragmentTests() const { return false; } + TLayoutDepth getDepth() const { return EldNone; } + bool getPixelCenterInteger() const { return false; } + void setOriginUpperLeft() { } + bool getOriginUpperLeft() const { return true; } + TInterlockOrdering getInterlockOrdering() const { return EioNone; } + + bool getAutoMapBindings() const { return false; } + bool getAutoMapLocations() const { return false; } + int getNumPushConstants() const { return 0; } + void addShaderRecordCount() { } + void addTaskNVCount() { } + void setUseVulkanMemoryModel() { } + bool usingVulkanMemoryModel() const { return false; } + bool usingPhysicalStorageBuffer() const { return false; } + bool usingVariablePointers() const { return false; } + unsigned getXfbStride(int buffer) const { return 0; } + bool hasLayoutDerivativeModeNone() const { return false; } + ComputeDerivativeMode getLayoutDerivativeModeNone() const { return LayoutDerivativeNone; } +#else + void output(TInfoSink&, bool tree); + + bool isEsProfile() const { return profile == EEsProfile; } + + void setShiftBinding(TResourceType res, unsigned int shift) + { + shiftBinding[res] = shift; + + const char* name = getResourceName(res); + if (name != nullptr) + processes.addIfNonZero(name, shift); + } + + unsigned int getShiftBinding(TResourceType res) const { return shiftBinding[res]; } + + void setShiftBindingForSet(TResourceType res, unsigned int shift, unsigned int set) + { + if (shift == 0) // ignore if there's no shift: it's a no-op. + return; + + shiftBindingForSet[res][set] = shift; + + const char* name = getResourceName(res); + if (name != nullptr) { + processes.addProcess(name); + processes.addArgument(shift); + processes.addArgument(set); + } + } + + int getShiftBindingForSet(TResourceType res, unsigned int set) const + { + const auto shift = shiftBindingForSet[res].find(set); + return shift == shiftBindingForSet[res].end() ? -1 : shift->second; + } + bool hasShiftBindingForSet(TResourceType res) const { return !shiftBindingForSet[res].empty(); } + + void setResourceSetBinding(const std::vector& shift) + { + resourceSetBinding = shift; + if (shift.size() > 0) { + processes.addProcess("resource-set-binding"); + for (int s = 0; s < (int)shift.size(); ++s) + processes.addArgument(shift[s]); + } + } + const std::vector& getResourceSetBinding() const { return resourceSetBinding; } + void setAutoMapBindings(bool map) + { + autoMapBindings = map; + if (autoMapBindings) + processes.addProcess("auto-map-bindings"); + } + bool getAutoMapBindings() const { return autoMapBindings; } + void setAutoMapLocations(bool map) + { + autoMapLocations = map; + if (autoMapLocations) + processes.addProcess("auto-map-locations"); + } + bool getAutoMapLocations() const { return autoMapLocations; } + +#ifdef ENABLE_HLSL + void setFlattenUniformArrays(bool flatten) + { + flattenUniformArrays = flatten; + if (flattenUniformArrays) + processes.addProcess("flatten-uniform-arrays"); + } + bool getFlattenUniformArrays() const { return flattenUniformArrays; } +#endif + void setNoStorageFormat(bool b) + { + useUnknownFormat = b; + if (useUnknownFormat) + processes.addProcess("no-storage-format"); + } + bool getNoStorageFormat() const { return useUnknownFormat; } + void setUseVulkanMemoryModel() + { + useVulkanMemoryModel = true; + processes.addProcess("use-vulkan-memory-model"); + } + bool usingVulkanMemoryModel() const { return useVulkanMemoryModel; } + void setUsePhysicalStorageBuffer() + { + usePhysicalStorageBuffer = true; + } + bool usingPhysicalStorageBuffer() const { return usePhysicalStorageBuffer; } + void setUseVariablePointers() + { + useVariablePointers = true; + processes.addProcess("use-variable-pointers"); + } + bool usingVariablePointers() const { return useVariablePointers; } + +#ifdef ENABLE_HLSL + template T addCounterBufferName(const T& name) const { return name + implicitCounterName; } + bool hasCounterBufferName(const TString& name) const { + size_t len = strlen(implicitCounterName); + return name.size() > len && + name.compare(name.size() - len, len, implicitCounterName) == 0; + } +#endif + + void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; } + int getNumPushConstants() const { return numPushConstants; } + void addShaderRecordCount() { ++numShaderRecordBlocks; } + void addTaskNVCount() { ++numTaskNVBlocks; } + + bool setInvocations(int i) + { + if (invocations != TQualifier::layoutNotSet) + return invocations == i; + invocations = i; + return true; + } + int getInvocations() const { return invocations; } + bool setVertices(int m) + { + if (vertices != TQualifier::layoutNotSet) + return vertices == m; + vertices = m; + return true; + } + int getVertices() const { return vertices; } + bool setInputPrimitive(TLayoutGeometry p) + { + if (inputPrimitive != ElgNone) + return inputPrimitive == p; + inputPrimitive = p; + return true; + } + TLayoutGeometry getInputPrimitive() const { return inputPrimitive; } + bool setVertexSpacing(TVertexSpacing s) + { + if (vertexSpacing != EvsNone) + return vertexSpacing == s; + vertexSpacing = s; + return true; + } + TVertexSpacing getVertexSpacing() const { return vertexSpacing; } + bool setVertexOrder(TVertexOrder o) + { + if (vertexOrder != EvoNone) + return vertexOrder == o; + vertexOrder = o; + return true; + } + TVertexOrder getVertexOrder() const { return vertexOrder; } + void setPointMode() { pointMode = true; } + bool getPointMode() const { return pointMode; } + + bool setInterlockOrdering(TInterlockOrdering o) + { + if (interlockOrdering != EioNone) + return interlockOrdering == o; + interlockOrdering = o; + return true; + } + TInterlockOrdering getInterlockOrdering() const { return interlockOrdering; } + + void setXfbMode() { xfbMode = true; } + bool getXfbMode() const { return xfbMode; } + void setMultiStream() { multiStream = true; } + bool isMultiStream() const { return multiStream; } + bool setOutputPrimitive(TLayoutGeometry p) + { + if (outputPrimitive != ElgNone) + return outputPrimitive == p; + outputPrimitive = p; + return true; + } + TLayoutGeometry getOutputPrimitive() const { return outputPrimitive; } + void setPostDepthCoverage() { postDepthCoverage = true; } + bool getPostDepthCoverage() const { return postDepthCoverage; } + void setEarlyFragmentTests() { earlyFragmentTests = true; } + bool getEarlyFragmentTests() const { return earlyFragmentTests; } + bool setDepth(TLayoutDepth d) + { + if (depthLayout != EldNone) + return depthLayout == d; + depthLayout = d; + return true; + } + TLayoutDepth getDepth() const { return depthLayout; } + void setOriginUpperLeft() { originUpperLeft = true; } + bool getOriginUpperLeft() const { return originUpperLeft; } + void setPixelCenterInteger() { pixelCenterInteger = true; } + bool getPixelCenterInteger() const { return pixelCenterInteger; } + void addBlendEquation(TBlendEquationShift b) { blendEquations |= (1 << b); } + unsigned int getBlendEquations() const { return blendEquations; } + bool setXfbBufferStride(int buffer, unsigned stride) + { + if (xfbBuffers[buffer].stride != TQualifier::layoutXfbStrideEnd) + return xfbBuffers[buffer].stride == stride; + xfbBuffers[buffer].stride = stride; + return true; + } + unsigned getXfbStride(int buffer) const { return xfbBuffers[buffer].stride; } + int addXfbBufferOffset(const TType&); + unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType, bool& contains32BitType, bool& contains16BitType) const; + unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType) const; + void setLayoutOverrideCoverage() { layoutOverrideCoverage = true; } + bool getLayoutOverrideCoverage() const { return layoutOverrideCoverage; } + void setGeoPassthroughEXT() { geoPassthroughEXT = true; } + bool getGeoPassthroughEXT() const { return geoPassthroughEXT; } + void setLayoutDerivativeMode(ComputeDerivativeMode mode) { computeDerivativeMode = mode; } + bool hasLayoutDerivativeModeNone() const { return computeDerivativeMode != LayoutDerivativeNone; } + ComputeDerivativeMode getLayoutDerivativeModeNone() const { return computeDerivativeMode; } + bool setPrimitives(int m) + { + if (primitives != TQualifier::layoutNotSet) + return primitives == m; + primitives = m; + return true; + } + int getPrimitives() const { return primitives; } + const char* addSemanticName(const TString& name) + { + return semanticNameSet.insert(name).first->c_str(); + } + void addUniformLocationOverride(const char* nameStr, int location) + { + std::string name = nameStr; + uniformLocationOverrides[name] = location; + } + + int getUniformLocationOverride(const char* nameStr) const + { + std::string name = nameStr; + auto pos = uniformLocationOverrides.find(name); + if (pos == uniformLocationOverrides.end()) + return -1; + else + return pos->second; + } + + void setUniformLocationBase(int base) { uniformLocationBase = base; } + int getUniformLocationBase() const { return uniformLocationBase; } + + void setNeedsLegalization() { needToLegalize = true; } + bool needsLegalization() const { return needToLegalize; } + + void setBinaryDoubleOutput() { binaryDoubleOutput = true; } + bool getBinaryDoubleOutput() { return binaryDoubleOutput; } +#endif // GLSLANG_WEB + +#ifdef ENABLE_HLSL + void setHlslFunctionality1() { hlslFunctionality1 = true; } + bool getHlslFunctionality1() const { return hlslFunctionality1; } + void setHlslOffsets() + { + hlslOffsets = true; + if (hlslOffsets) + processes.addProcess("hlsl-offsets"); + } + bool usingHlslOffsets() const { return hlslOffsets; } + void setHlslIoMapping(bool b) + { + hlslIoMapping = b; + if (hlslIoMapping) + processes.addProcess("hlsl-iomap"); + } + bool usingHlslIoMapping() { return hlslIoMapping; } +#else + bool getHlslFunctionality1() const { return false; } + bool usingHlslOffsets() const { return false; } + bool usingHlslIoMapping() { return false; } +#endif + + void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee); + void merge(TInfoSink&, TIntermediate&); + void finalCheck(TInfoSink&, bool keepUncalled); + + bool buildConvertOp(TBasicType dst, TBasicType src, TOperator& convertOp) const; + TIntermTyped* createConversion(TBasicType convertTo, TIntermTyped* node) const; + + void addIoAccessed(const TString& name) { ioAccessed.insert(name); } + bool inIoAccessed(const TString& name) const { return ioAccessed.find(name) != ioAccessed.end(); } + + int addUsedLocation(const TQualifier&, const TType&, bool& typeCollision); + int checkLocationRange(int set, const TIoRange& range, const TType&, bool& typeCollision); + int addUsedOffsets(int binding, int offset, int numOffsets); + bool addUsedConstantId(int id); + static int computeTypeLocationSize(const TType&, EShLanguage); + static int computeTypeUniformLocationSize(const TType&); + + static int getBaseAlignmentScalar(const TType&, int& size); + static int getBaseAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor); + static int getScalarAlignment(const TType&, int& size, int& stride, bool rowMajor); + static int getMemberAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor); + static bool improperStraddle(const TType& type, int size, int offset); + static void updateOffset(const TType& parentType, const TType& memberType, int& offset, int& memberSize); + static int getOffset(const TType& type, int index); + static int getBlockSize(const TType& blockType); + static int computeBufferReferenceTypeSize(const TType&); + bool promote(TIntermOperator*); + void setNanMinMaxClamp(bool setting) { nanMinMaxClamp = setting; } + bool getNanMinMaxClamp() const { return nanMinMaxClamp; } + + void setSourceFile(const char* file) { if (file != nullptr) sourceFile = file; } + const std::string& getSourceFile() const { return sourceFile; } + void addSourceText(const char* text, size_t len) { sourceText.append(text, len); } + const std::string& getSourceText() const { return sourceText; } + const std::map& getIncludeText() const { return includeText; } + void addIncludeText(const char* name, const char* text, size_t len) { includeText[name].assign(text,len); } + void addProcesses(const std::vector& p) + { + for (int i = 0; i < (int)p.size(); ++i) + processes.addProcess(p[i]); + } + void addProcess(const std::string& process) { processes.addProcess(process); } + void addProcessArgument(const std::string& arg) { processes.addArgument(arg); } + const std::vector& getProcesses() const { return processes.getProcesses(); } + + // Certain explicit conversions are allowed conditionally +#ifdef GLSLANG_WEB + bool getArithemeticInt8Enabled() const { return false; } + bool getArithemeticInt16Enabled() const { return false; } + bool getArithemeticFloat16Enabled() const { return false; } +#else + bool getArithemeticInt8Enabled() const { + return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || + extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8); + } + bool getArithemeticInt16Enabled() const { + return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || + extensionRequested(E_GL_AMD_gpu_shader_int16) || + extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16); + } + + bool getArithemeticFloat16Enabled() const { + return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || + extensionRequested(E_GL_AMD_gpu_shader_half_float) || + extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16); + } +#endif + +protected: + TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&); + void error(TInfoSink& infoSink, const char*); + void warn(TInfoSink& infoSink, const char*); + void mergeCallGraphs(TInfoSink&, TIntermediate&); + void mergeModes(TInfoSink&, TIntermediate&); + void mergeTrees(TInfoSink&, TIntermediate&); + void seedIdMap(TIdMaps& idMaps, int& maxId); + void remapIds(const TIdMaps& idMaps, int idShift, TIntermediate&); + void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals); + void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects); + void mergeImplicitArraySizes(TType&, const TType&); + void mergeErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, bool crossStage); + void checkCallGraphCycles(TInfoSink&); + void checkCallGraphBodies(TInfoSink&, bool keepUncalled); + void inOutLocationCheck(TInfoSink&); + TIntermAggregate* findLinkerObjects() const; + bool userOutputUsed() const; + bool isSpecializationOperation(const TIntermOperator&) const; + bool isNonuniformPropagating(TOperator) const; + bool promoteUnary(TIntermUnary&); + bool promoteBinary(TIntermBinary&); + void addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable&, const TString&); + bool promoteAggregate(TIntermAggregate&); + void pushSelector(TIntermSequence&, const TVectorSelector&, const TSourceLoc&); + void pushSelector(TIntermSequence&, const TMatrixSelector&, const TSourceLoc&); + bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&); + void performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root); + bool isConversionAllowed(TOperator op, TIntermTyped* node) const; + std::tuple getConversionDestinatonType(TBasicType type0, TBasicType type1, TOperator op) const; + + // JohnK: I think this function should go away. + // This data structure is just a log to pass on to back ends. + // Versioning and extensions are handled in Version.cpp, with a rich + // set of functions for querying stages, versions, extension enable/disabled, etc. +#ifdef GLSLANG_WEB + bool extensionRequested(const char *extension) const { return false; } +#else + bool extensionRequested(const char *extension) const {return requestedExtensions.find(extension) != requestedExtensions.end();} +#endif + + static const char* getResourceName(TResourceType); + + const EShLanguage language; // stage, known at construction time + std::string entryPointName; + std::string entryPointMangledName; + typedef std::list TGraph; + TGraph callGraph; + + EProfile profile; // source profile + int version; // source version + SpvVersion spvVersion; + TIntermNode* treeRoot; + std::set requestedExtensions; // cumulation of all enabled or required extensions; not connected to what subset of the shader used them + TBuiltInResource resources; + int numEntryPoints; + int numErrors; + int numPushConstants; + bool recursive; + bool invertY; + bool useStorageBuffer; + bool nanMinMaxClamp; // true if desiring min/max/clamp to favor non-NaN over NaN + bool depthReplacing; + int localSize[3]; + bool localSizeNotDefault[3]; + int localSizeSpecId[3]; +#ifndef GLSLANG_WEB +public: + const char* const implicitThisName; + const char* const implicitCounterName; +protected: + EShSource source; // source language, known a bit later + bool useVulkanMemoryModel; + int invocations; + int vertices; + TLayoutGeometry inputPrimitive; + TLayoutGeometry outputPrimitive; + bool pixelCenterInteger; + bool originUpperLeft; + TVertexSpacing vertexSpacing; + TVertexOrder vertexOrder; + TInterlockOrdering interlockOrdering; + bool pointMode; + bool earlyFragmentTests; + bool postDepthCoverage; + TLayoutDepth depthLayout; + bool hlslFunctionality1; + int blendEquations; // an 'or'ing of masks of shifts of TBlendEquationShift + bool xfbMode; + std::vector xfbBuffers; // all the data we need to track per xfb buffer + bool multiStream; + bool layoutOverrideCoverage; + bool geoPassthroughEXT; + int numShaderRecordBlocks; + ComputeDerivativeMode computeDerivativeMode; + int primitives; + int numTaskNVBlocks; + + // Base shift values + std::array shiftBinding; + + // Per-descriptor-set shift values + std::array, EResCount> shiftBindingForSet; + + std::vector resourceSetBinding; + bool autoMapBindings; + bool autoMapLocations; + bool flattenUniformArrays; + bool useUnknownFormat; + bool hlslOffsets; + bool hlslIoMapping; + bool useVariablePointers; + + std::set semanticNameSet; + + EShTextureSamplerTransformMode textureSamplerTransformMode; + + bool needToLegalize; + bool binaryDoubleOutput; + bool usePhysicalStorageBuffer; + + std::unordered_map uniformLocationOverrides; + int uniformLocationBase; +#endif + + std::unordered_set usedConstantId; // specialization constant ids used + std::vector usedAtomics; // sets of bindings used by atomic counters + std::vector usedIo[4]; // sets of used locations, one for each of in, out, uniform, and buffers + // set of names of statically read/written I/O that might need extra checking + std::set ioAccessed; + // source code of shader, useful as part of debug information + std::string sourceFile; + std::string sourceText; + + // Included text. First string is a name, second is the included text + std::map includeText; + + // for OpModuleProcessed, or equivalent + TProcesses processes; + +private: + void operator=(TIntermediate&); // prevent assignments +}; + +} // end namespace glslang + +#endif // _LOCAL_INTERMEDIATE_INCLUDED_ diff --git a/android/x86/include/glslang/MachineIndependent/parseVersions.h b/android/x86/include/glslang/MachineIndependent/parseVersions.h new file mode 100644 index 00000000..aa1964fc --- /dev/null +++ b/android/x86/include/glslang/MachineIndependent/parseVersions.h @@ -0,0 +1,236 @@ +// +// Copyright (C) 2015-2018 Google, Inc. +// Copyright (C) 2017 ARM Limited. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +// This is implemented in Versions.cpp + +#ifndef _PARSE_VERSIONS_INCLUDED_ +#define _PARSE_VERSIONS_INCLUDED_ + +#include "../Public/ShaderLang.h" +#include "../Include/InfoSink.h" +#include "Scan.h" + +#include + +namespace glslang { + +// +// Base class for parse helpers. +// This just has version-related information and checking. +// This class should be sufficient for preprocessing. +// +class TParseVersions { +public: + TParseVersions(TIntermediate& interm, int version, EProfile profile, + const SpvVersion& spvVersion, EShLanguage language, TInfoSink& infoSink, + bool forwardCompatible, EShMessages messages) + : +#ifndef GLSLANG_WEB + forwardCompatible(forwardCompatible), + profile(profile), +#endif + infoSink(infoSink), version(version), + language(language), + spvVersion(spvVersion), + intermediate(interm), messages(messages), numErrors(0), currentScanner(0) { } + virtual ~TParseVersions() { } + void requireStage(const TSourceLoc&, EShLanguageMask, const char* featureDesc); + void requireStage(const TSourceLoc&, EShLanguage, const char* featureDesc); +#ifdef GLSLANG_WEB + const EProfile profile = EEsProfile; + bool isEsProfile() const { return true; } + void requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc) + { + if (! (EEsProfile & profileMask)) + error(loc, "not supported with this profile:", featureDesc, ProfileName(profile)); + } + void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions, + const char* const extensions[], const char* featureDesc) + { + if ((EEsProfile & profileMask) && (minVersion == 0 || version < minVersion)) + error(loc, "not supported for this version or the enabled extensions", featureDesc, ""); + } + void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, const char* extension, + const char* featureDesc) + { + profileRequires(loc, profileMask, minVersion, extension ? 1 : 0, &extension, featureDesc); + } + void initializeExtensionBehavior() { } + void checkDeprecated(const TSourceLoc&, int queryProfiles, int depVersion, const char* featureDesc) { } + void requireNotRemoved(const TSourceLoc&, int queryProfiles, int removedVersion, const char* featureDesc) { } + void requireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], + const char* featureDesc) { } + void ppRequireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], + const char* featureDesc) { } + TExtensionBehavior getExtensionBehavior(const char*) { return EBhMissing; } + bool extensionTurnedOn(const char* const extension) { return false; } + bool extensionsTurnedOn(int numExtensions, const char* const extensions[]) { return false; } + void updateExtensionBehavior(int line, const char* const extension, const char* behavior) { } + void updateExtensionBehavior(const char* const extension, TExtensionBehavior) { } + void checkExtensionStage(const TSourceLoc&, const char* const extension) { } + void fullIntegerCheck(const TSourceLoc&, const char* op) { } + void doubleCheck(const TSourceLoc&, const char* op) { } + bool float16Arithmetic() { return false; } + void requireFloat16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc) { } + bool int16Arithmetic() { return false; } + void requireInt16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc) { } + bool int8Arithmetic() { return false; } + void requireInt8Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc) { } + void int64Check(const TSourceLoc&, const char* op, bool builtIn = false) { } + void explicitFloat32Check(const TSourceLoc&, const char* op, bool builtIn = false) { } + void explicitFloat64Check(const TSourceLoc&, const char* op, bool builtIn = false) { } + bool relaxedErrors() const { return false; } + bool suppressWarnings() const { return true; } + bool isForwardCompatible() const { return false; } +#else + bool forwardCompatible; // true if errors are to be given for use of deprecated features + EProfile profile; // the declared profile in the shader (core by default) + bool isEsProfile() const { return profile == EEsProfile; } + void requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc); + void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions, + const char* const extensions[], const char* featureDesc); + void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, const char* extension, + const char* featureDesc); + virtual void initializeExtensionBehavior(); + virtual void checkDeprecated(const TSourceLoc&, int queryProfiles, int depVersion, const char* featureDesc); + virtual void requireNotRemoved(const TSourceLoc&, int queryProfiles, int removedVersion, const char* featureDesc); + virtual void requireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], + const char* featureDesc); + virtual void ppRequireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], + const char* featureDesc); + virtual TExtensionBehavior getExtensionBehavior(const char*); + virtual bool extensionTurnedOn(const char* const extension); + virtual bool extensionsTurnedOn(int numExtensions, const char* const extensions[]); + virtual void updateExtensionBehavior(int line, const char* const extension, const char* behavior); + virtual void updateExtensionBehavior(const char* const extension, TExtensionBehavior); + virtual bool checkExtensionsRequested(const TSourceLoc&, int numExtensions, const char* const extensions[], + const char* featureDesc); + virtual void checkExtensionStage(const TSourceLoc&, const char* const extension); + virtual void fullIntegerCheck(const TSourceLoc&, const char* op); + + virtual void unimplemented(const TSourceLoc&, const char* featureDesc); + virtual void doubleCheck(const TSourceLoc&, const char* op); + virtual void float16Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void float16ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false); + virtual bool float16Arithmetic(); + virtual void requireFloat16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc); + virtual void int16ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false); + virtual bool int16Arithmetic(); + virtual void requireInt16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc); + virtual void int8ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false); + virtual bool int8Arithmetic(); + virtual void requireInt8Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc); + virtual void float16OpaqueCheck(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void int64Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void explicitInt8Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void explicitInt16Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void explicitInt32Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void explicitFloat32Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void explicitFloat64Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void fcoopmatCheck(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void intcoopmatCheck(const TSourceLoc&, const char *op, bool builtIn = false); + bool relaxedErrors() const { return (messages & EShMsgRelaxedErrors) != 0; } + bool suppressWarnings() const { return (messages & EShMsgSuppressWarnings) != 0; } + bool isForwardCompatible() const { return forwardCompatible; } +#endif // GLSLANG_WEB + virtual void spvRemoved(const TSourceLoc&, const char* op); + virtual void vulkanRemoved(const TSourceLoc&, const char* op); + virtual void requireVulkan(const TSourceLoc&, const char* op); + virtual void requireSpv(const TSourceLoc&, const char* op); + + +#if defined(GLSLANG_WEB) && !defined(GLSLANG_WEB_DEVEL) + void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) { addError(); } + void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) { } + void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) { addError(); } + void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) { } +#else + virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) = 0; + virtual void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) = 0; + virtual void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) = 0; + virtual void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) = 0; +#endif + + void addError() { ++numErrors; } + int getNumErrors() const { return numErrors; } + + void setScanner(TInputScanner* scanner) { currentScanner = scanner; } + TInputScanner* getScanner() const { return currentScanner; } + const TSourceLoc& getCurrentLoc() const { return currentScanner->getSourceLoc(); } + void setCurrentLine(int line) { currentScanner->setLine(line); } + void setCurrentColumn(int col) { currentScanner->setColumn(col); } + void setCurrentSourceName(const char* name) { currentScanner->setFile(name); } + void setCurrentString(int string) { currentScanner->setString(string); } + + void getPreamble(std::string&); +#ifdef ENABLE_HLSL + bool isReadingHLSL() const { return (messages & EShMsgReadHlsl) == EShMsgReadHlsl; } + bool hlslEnable16BitTypes() const { return (messages & EShMsgHlslEnable16BitTypes) != 0; } + bool hlslDX9Compatible() const { return (messages & EShMsgHlslDX9Compatible) != 0; } +#else + bool isReadingHLSL() const { return false; } +#endif + + TInfoSink& infoSink; + + // compilation mode + int version; // version, updated by #version in the shader + EShLanguage language; // really the stage + SpvVersion spvVersion; + TIntermediate& intermediate; // helper for making and hooking up pieces of the parse tree + +protected: + TMap extensionBehavior; // for each extension string, what its current behavior is set to + EShMessages messages; // errors/warnings/rule-sets + int numErrors; // number of compile-time errors encountered + TInputScanner* currentScanner; + +private: + explicit TParseVersions(const TParseVersions&); + TParseVersions& operator=(const TParseVersions&); +}; + +} // end namespace glslang + +#endif // _PARSE_VERSIONS_INCLUDED_ diff --git a/android/x86/include/glslang/MachineIndependent/preprocessor/PpContext.h b/android/x86/include/glslang/MachineIndependent/preprocessor/PpContext.h new file mode 100644 index 00000000..714b5ead --- /dev/null +++ b/android/x86/include/glslang/MachineIndependent/preprocessor/PpContext.h @@ -0,0 +1,703 @@ +// +// Copyright (C) 2013 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ + +#ifndef PPCONTEXT_H +#define PPCONTEXT_H + +#include +#include +#include + +#include "../ParseHelper.h" +#include "PpTokens.h" + +/* windows only pragma */ +#ifdef _MSC_VER + #pragma warning(disable : 4127) +#endif + +namespace glslang { + +class TPpToken { +public: + TPpToken() { clear(); } + void clear() + { + space = false; + i64val = 0; + loc.init(); + name[0] = 0; + } + + // Used for comparing macro definitions, so checks what is relevant for that. + bool operator==(const TPpToken& right) const + { + return space == right.space && + ival == right.ival && dval == right.dval && i64val == right.i64val && + strncmp(name, right.name, MaxTokenLength) == 0; + } + bool operator!=(const TPpToken& right) const { return ! operator==(right); } + + TSourceLoc loc; + // True if a space (for white space or a removed comment) should also be + // recognized, in front of the token returned: + bool space; + // Numeric value of the token: + union { + int ival; + double dval; + long long i64val; + }; + // Text string of the token: + char name[MaxTokenLength + 1]; +}; + +class TStringAtomMap { +// +// Implementation is in PpAtom.cpp +// +// Maintain a bi-directional mapping between relevant preprocessor strings and +// "atoms" which a unique integers (small, contiguous, not hash-like) per string. +// +public: + TStringAtomMap(); + + // Map string -> atom. + // Return 0 if no existing string. + int getAtom(const char* s) const + { + auto it = atomMap.find(s); + return it == atomMap.end() ? 0 : it->second; + } + + // Map a new or existing string -> atom, inventing a new atom if necessary. + int getAddAtom(const char* s) + { + int atom = getAtom(s); + if (atom == 0) { + atom = nextAtom++; + addAtomFixed(s, atom); + } + return atom; + } + + // Map atom -> string. + const char* getString(int atom) const { return stringMap[atom]->c_str(); } + +protected: + TStringAtomMap(TStringAtomMap&); + TStringAtomMap& operator=(TStringAtomMap&); + + TUnorderedMap atomMap; + TVector stringMap; // these point into the TString in atomMap + int nextAtom; + + // Bad source characters can lead to bad atoms, so gracefully handle those by + // pre-filling the table with them (to avoid if tests later). + TString badToken; + + // Add bi-directional mappings: + // - string -> atom + // - atom -> string + void addAtomFixed(const char* s, int atom) + { + auto it = atomMap.insert(std::pair(s, atom)).first; + if (stringMap.size() < (size_t)atom + 1) + stringMap.resize(atom + 100, &badToken); + stringMap[atom] = &it->first; + } +}; + +class TInputScanner; + +enum MacroExpandResult { + MacroExpandNotStarted, // macro not expanded, which might not be an error + MacroExpandError, // a clear error occurred while expanding, no expansion + MacroExpandStarted, // macro expansion process has started + MacroExpandUndef // macro is undefined and will be expanded +}; + +// This class is the result of turning a huge pile of C code communicating through globals +// into a class. This was done to allowing instancing to attain thread safety. +// Don't expect too much in terms of OO design. +class TPpContext { +public: + TPpContext(TParseContextBase&, const std::string& rootFileName, TShader::Includer&); + virtual ~TPpContext(); + + void setPreamble(const char* preamble, size_t length); + + int tokenize(TPpToken& ppToken); + int tokenPaste(int token, TPpToken&); + + class tInput { + public: + tInput(TPpContext* p) : done(false), pp(p) { } + virtual ~tInput() { } + + virtual int scan(TPpToken*) = 0; + virtual int getch() = 0; + virtual void ungetch() = 0; + virtual bool peekPasting() { return false; } // true when about to see ## + virtual bool peekContinuedPasting(int) { return false; } // true when non-spaced tokens can paste + virtual bool endOfReplacementList() { return false; } // true when at the end of a macro replacement list (RHS of #define) + virtual bool isMacroInput() { return false; } + + // Will be called when we start reading tokens from this instance + virtual void notifyActivated() {} + // Will be called when we do not read tokens from this instance anymore + virtual void notifyDeleted() {} + protected: + bool done; + TPpContext* pp; + }; + + void setInput(TInputScanner& input, bool versionWillBeError); + + void pushInput(tInput* in) + { + inputStack.push_back(in); + in->notifyActivated(); + } + void popInput() + { + inputStack.back()->notifyDeleted(); + delete inputStack.back(); + inputStack.pop_back(); + } + + // + // From PpTokens.cpp + // + + // Capture the needed parts of a token stream for macro recording/playback. + class TokenStream { + public: + // Manage a stream of these 'Token', which capture the relevant parts + // of a TPpToken, plus its atom. + class Token { + public: + Token(int atom, const TPpToken& ppToken) : + atom(atom), + space(ppToken.space), + i64val(ppToken.i64val), + name(ppToken.name) { } + int get(TPpToken& ppToken) + { + ppToken.clear(); + ppToken.space = space; + ppToken.i64val = i64val; + snprintf(ppToken.name, sizeof(ppToken.name), "%s", name.c_str()); + return atom; + } + bool isAtom(int a) const { return atom == a; } + int getAtom() const { return atom; } + bool nonSpaced() const { return !space; } + protected: + Token() {} + int atom; + bool space; // did a space precede the token? + long long i64val; + TString name; + }; + + TokenStream() : currentPos(0) { } + + void putToken(int token, TPpToken* ppToken); + bool peekToken(int atom) { return !atEnd() && stream[currentPos].isAtom(atom); } + bool peekContinuedPasting(int atom) + { + // This is basically necessary because, for example, the PP + // tokenizer only accepts valid numeric-literals plus suffixes, so + // separates numeric-literals plus bad suffix into two tokens, which + // should get both pasted together as one token when token pasting. + // + // The following code is a bit more generalized than the above example. + if (!atEnd() && atom == PpAtomIdentifier && stream[currentPos].nonSpaced()) { + switch(stream[currentPos].getAtom()) { + case PpAtomConstInt: + case PpAtomConstUint: + case PpAtomConstInt64: + case PpAtomConstUint64: + case PpAtomConstInt16: + case PpAtomConstUint16: + case PpAtomConstFloat: + case PpAtomConstDouble: + case PpAtomConstFloat16: + case PpAtomConstString: + case PpAtomIdentifier: + return true; + default: + break; + } + } + + return false; + } + int getToken(TParseContextBase&, TPpToken*); + bool atEnd() { return currentPos >= stream.size(); } + bool peekTokenizedPasting(bool lastTokenPastes); + bool peekUntokenizedPasting(); + void reset() { currentPos = 0; } + + protected: + TVector stream; + size_t currentPos; + }; + + // + // From Pp.cpp + // + + struct MacroSymbol { + MacroSymbol() : functionLike(0), busy(0), undef(0) { } + TVector args; + TokenStream body; + unsigned functionLike : 1; // 0 means object-like, 1 means function-like + unsigned busy : 1; + unsigned undef : 1; + }; + + typedef TMap TSymbolMap; + TSymbolMap macroDefs; // map atoms to macro definitions + MacroSymbol* lookupMacroDef(int atom) + { + auto existingMacroIt = macroDefs.find(atom); + return (existingMacroIt == macroDefs.end()) ? nullptr : &(existingMacroIt->second); + } + void addMacroDef(int atom, MacroSymbol& macroDef) { macroDefs[atom] = macroDef; } + +protected: + TPpContext(TPpContext&); + TPpContext& operator=(TPpContext&); + + TStringAtomMap atomStrings; + char* preamble; // string to parse, all before line 1 of string 0, it is 0 if no preamble + int preambleLength; + char** strings; // official strings of shader, starting a string 0 line 1 + size_t* lengths; + int numStrings; // how many official strings there are + int currentString; // which string we're currently parsing (-1 for preamble) + + // Scanner data: + int previous_token; + TParseContextBase& parseContext; + + // Get the next token from *stack* of input sources, popping input sources + // that are out of tokens, down until an input source is found that has a token. + // Return EndOfInput when there are no more tokens to be found by doing this. + int scanToken(TPpToken* ppToken) + { + int token = EndOfInput; + + while (! inputStack.empty()) { + token = inputStack.back()->scan(ppToken); + if (token != EndOfInput || inputStack.empty()) + break; + popInput(); + } + + return token; + } + int getChar() { return inputStack.back()->getch(); } + void ungetChar() { inputStack.back()->ungetch(); } + bool peekPasting() { return !inputStack.empty() && inputStack.back()->peekPasting(); } + bool peekContinuedPasting(int a) + { + return !inputStack.empty() && inputStack.back()->peekContinuedPasting(a); + } + bool endOfReplacementList() { return inputStack.empty() || inputStack.back()->endOfReplacementList(); } + bool isMacroInput() { return inputStack.size() > 0 && inputStack.back()->isMacroInput(); } + + static const int maxIfNesting = 65; + + int ifdepth; // current #if-#else-#endif nesting in the cpp.c file (pre-processor) + bool elseSeen[maxIfNesting]; // Keep a track of whether an else has been seen at a particular depth + int elsetracker; // #if-#else and #endif constructs...Counter. + + class tMacroInput : public tInput { + public: + tMacroInput(TPpContext* pp) : tInput(pp), prepaste(false), postpaste(false) { } + virtual ~tMacroInput() + { + for (size_t i = 0; i < args.size(); ++i) + delete args[i]; + for (size_t i = 0; i < expandedArgs.size(); ++i) + delete expandedArgs[i]; + } + + virtual int scan(TPpToken*) override; + virtual int getch() override { assert(0); return EndOfInput; } + virtual void ungetch() override { assert(0); } + bool peekPasting() override { return prepaste; } + bool peekContinuedPasting(int a) override { return mac->body.peekContinuedPasting(a); } + bool endOfReplacementList() override { return mac->body.atEnd(); } + bool isMacroInput() override { return true; } + + MacroSymbol *mac; + TVector args; + TVector expandedArgs; + + protected: + bool prepaste; // true if we are just before ## + bool postpaste; // true if we are right after ## + }; + + class tMarkerInput : public tInput { + public: + tMarkerInput(TPpContext* pp) : tInput(pp) { } + virtual int scan(TPpToken*) override + { + if (done) + return EndOfInput; + done = true; + + return marker; + } + virtual int getch() override { assert(0); return EndOfInput; } + virtual void ungetch() override { assert(0); } + static const int marker = -3; + }; + + class tZeroInput : public tInput { + public: + tZeroInput(TPpContext* pp) : tInput(pp) { } + virtual int scan(TPpToken*) override; + virtual int getch() override { assert(0); return EndOfInput; } + virtual void ungetch() override { assert(0); } + }; + + std::vector inputStack; + bool errorOnVersion; + bool versionSeen; + + // + // from Pp.cpp + // + + // Used to obtain #include content. + TShader::Includer& includer; + + int CPPdefine(TPpToken * ppToken); + int CPPundef(TPpToken * ppToken); + int CPPelse(int matchelse, TPpToken * ppToken); + int extraTokenCheck(int atom, TPpToken* ppToken, int token); + int eval(int token, int precedence, bool shortCircuit, int& res, bool& err, TPpToken * ppToken); + int evalToToken(int token, bool shortCircuit, int& res, bool& err, TPpToken * ppToken); + int CPPif (TPpToken * ppToken); + int CPPifdef(int defined, TPpToken * ppToken); + int CPPinclude(TPpToken * ppToken); + int CPPline(TPpToken * ppToken); + int CPPerror(TPpToken * ppToken); + int CPPpragma(TPpToken * ppToken); + int CPPversion(TPpToken * ppToken); + int CPPextension(TPpToken * ppToken); + int readCPPline(TPpToken * ppToken); + int scanHeaderName(TPpToken* ppToken, char delimit); + TokenStream* PrescanMacroArg(TokenStream&, TPpToken*, bool newLineOkay); + MacroExpandResult MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay); + + // + // From PpTokens.cpp + // + void pushTokenStreamInput(TokenStream&, bool pasting = false); + void UngetToken(int token, TPpToken*); + + class tTokenInput : public tInput { + public: + tTokenInput(TPpContext* pp, TokenStream* t, bool prepasting) : + tInput(pp), + tokens(t), + lastTokenPastes(prepasting) { } + virtual int scan(TPpToken *ppToken) override { return tokens->getToken(pp->parseContext, ppToken); } + virtual int getch() override { assert(0); return EndOfInput; } + virtual void ungetch() override { assert(0); } + virtual bool peekPasting() override { return tokens->peekTokenizedPasting(lastTokenPastes); } + bool peekContinuedPasting(int a) override { return tokens->peekContinuedPasting(a); } + protected: + TokenStream* tokens; + bool lastTokenPastes; // true if the last token in the input is to be pasted, rather than consumed as a token + }; + + class tUngotTokenInput : public tInput { + public: + tUngotTokenInput(TPpContext* pp, int t, TPpToken* p) : tInput(pp), token(t), lval(*p) { } + virtual int scan(TPpToken *) override; + virtual int getch() override { assert(0); return EndOfInput; } + virtual void ungetch() override { assert(0); } + protected: + int token; + TPpToken lval; + }; + + // + // From PpScanner.cpp + // + class tStringInput : public tInput { + public: + tStringInput(TPpContext* pp, TInputScanner& i) : tInput(pp), input(&i) { } + virtual int scan(TPpToken*) override; + + // Scanner used to get source stream characters. + // - Escaped newlines are handled here, invisibly to the caller. + // - All forms of newline are handled, and turned into just a '\n'. + int getch() override + { + int ch = input->get(); + + if (ch == '\\') { + // Move past escaped newlines, as many as sequentially exist + do { + if (input->peek() == '\r' || input->peek() == '\n') { + bool allowed = pp->parseContext.lineContinuationCheck(input->getSourceLoc(), pp->inComment); + if (! allowed && pp->inComment) + return '\\'; + + // escape one newline now + ch = input->get(); + int nextch = input->get(); + if (ch == '\r' && nextch == '\n') + ch = input->get(); + else + ch = nextch; + } else + return '\\'; + } while (ch == '\\'); + } + + // handle any non-escaped newline + if (ch == '\r' || ch == '\n') { + if (ch == '\r' && input->peek() == '\n') + input->get(); + return '\n'; + } + + return ch; + } + + // Scanner used to backup the source stream characters. Newlines are + // handled here, invisibly to the caller, meaning have to undo exactly + // what getch() above does (e.g., don't leave things in the middle of a + // sequence of escaped newlines). + void ungetch() override + { + input->unget(); + + do { + int ch = input->peek(); + if (ch == '\r' || ch == '\n') { + if (ch == '\n') { + // correct for two-character newline + input->unget(); + if (input->peek() != '\r') + input->get(); + } + // now in front of a complete newline, move past an escape character + input->unget(); + if (input->peek() == '\\') + input->unget(); + else { + input->get(); + break; + } + } else + break; + } while (true); + } + + protected: + TInputScanner* input; + }; + + // Holds a reference to included file data, as well as a + // prologue and an epilogue string. This can be scanned using the tInput + // interface and acts as a single source string. + class TokenizableIncludeFile : public tInput { + public: + // Copies prologue and epilogue. The includedFile must remain valid + // until this TokenizableIncludeFile is no longer used. + TokenizableIncludeFile(const TSourceLoc& startLoc, + const std::string& prologue, + TShader::Includer::IncludeResult* includedFile, + const std::string& epilogue, + TPpContext* pp) + : tInput(pp), + prologue_(prologue), + epilogue_(epilogue), + includedFile_(includedFile), + scanner(3, strings, lengths, nullptr, 0, 0, true), + prevScanner(nullptr), + stringInput(pp, scanner) + { + strings[0] = prologue_.data(); + strings[1] = includedFile_->headerData; + strings[2] = epilogue_.data(); + + lengths[0] = prologue_.size(); + lengths[1] = includedFile_->headerLength; + lengths[2] = epilogue_.size(); + + scanner.setLine(startLoc.line); + scanner.setString(startLoc.string); + + scanner.setFile(startLoc.getFilenameStr(), 0); + scanner.setFile(startLoc.getFilenameStr(), 1); + scanner.setFile(startLoc.getFilenameStr(), 2); + } + + // tInput methods: + int scan(TPpToken* t) override { return stringInput.scan(t); } + int getch() override { return stringInput.getch(); } + void ungetch() override { stringInput.ungetch(); } + + void notifyActivated() override + { + prevScanner = pp->parseContext.getScanner(); + pp->parseContext.setScanner(&scanner); + pp->push_include(includedFile_); + } + + void notifyDeleted() override + { + pp->parseContext.setScanner(prevScanner); + pp->pop_include(); + } + + private: + TokenizableIncludeFile& operator=(const TokenizableIncludeFile&); + + // Stores the prologue for this string. + const std::string prologue_; + + // Stores the epilogue for this string. + const std::string epilogue_; + + // Points to the IncludeResult that this TokenizableIncludeFile represents. + TShader::Includer::IncludeResult* includedFile_; + + // Will point to prologue_, includedFile_->headerData and epilogue_ + // This is passed to scanner constructor. + // These do not own the storage and it must remain valid until this + // object has been destroyed. + const char* strings[3]; + // Length of str_, passed to scanner constructor. + size_t lengths[3]; + // Scans over str_. + TInputScanner scanner; + // The previous effective scanner before the scanner in this instance + // has been activated. + TInputScanner* prevScanner; + // Delegate object implementing the tInput interface. + tStringInput stringInput; + }; + + int ScanFromString(char* s); + void missingEndifCheck(); + int lFloatConst(int len, int ch, TPpToken* ppToken); + int characterLiteral(TPpToken* ppToken); + + void push_include(TShader::Includer::IncludeResult* result) + { + currentSourceFile = result->headerName; + includeStack.push(result); + } + + void pop_include() + { + TShader::Includer::IncludeResult* include = includeStack.top(); + includeStack.pop(); + includer.releaseInclude(include); + if (includeStack.empty()) { + currentSourceFile = rootFileName; + } else { + currentSourceFile = includeStack.top()->headerName; + } + } + + bool inComment; + std::string rootFileName; + std::stack includeStack; + std::string currentSourceFile; + + std::istringstream strtodStream; + bool disableEscapeSequences; +}; + +} // end namespace glslang + +#endif // PPCONTEXT_H diff --git a/android/x86/include/glslang/MachineIndependent/preprocessor/PpTokens.h b/android/x86/include/glslang/MachineIndependent/preprocessor/PpTokens.h new file mode 100644 index 00000000..7b0f8155 --- /dev/null +++ b/android/x86/include/glslang/MachineIndependent/preprocessor/PpTokens.h @@ -0,0 +1,179 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ + +#ifndef PARSER_H +#define PARSER_H + +namespace glslang { + +// Multi-character tokens +enum EFixedAtoms { + // single character tokens get their own char value as their token; start here for multi-character tokens + PpAtomMaxSingle = 127, + + // replace bad character tokens with this, to avoid accidental aliasing with the below + PpAtomBadToken, + + // Operators + + PPAtomAddAssign, + PPAtomSubAssign, + PPAtomMulAssign, + PPAtomDivAssign, + PPAtomModAssign, + + PpAtomRight, + PpAtomLeft, + + PpAtomRightAssign, + PpAtomLeftAssign, + PpAtomAndAssign, + PpAtomOrAssign, + PpAtomXorAssign, + + PpAtomAnd, + PpAtomOr, + PpAtomXor, + + PpAtomEQ, + PpAtomNE, + PpAtomGE, + PpAtomLE, + + PpAtomDecrement, + PpAtomIncrement, + + PpAtomColonColon, + + PpAtomPaste, + + // Constants + + PpAtomConstInt, + PpAtomConstUint, + PpAtomConstInt64, + PpAtomConstUint64, + PpAtomConstInt16, + PpAtomConstUint16, + PpAtomConstFloat, + PpAtomConstDouble, + PpAtomConstFloat16, + PpAtomConstString, + + // Identifiers + PpAtomIdentifier, + + // preprocessor "keywords" + + PpAtomDefine, + PpAtomUndef, + + PpAtomIf, + PpAtomIfdef, + PpAtomIfndef, + PpAtomElse, + PpAtomElif, + PpAtomEndif, + + PpAtomLine, + PpAtomPragma, + PpAtomError, + + // #version ... + PpAtomVersion, + PpAtomCore, + PpAtomCompatibility, + PpAtomEs, + + // #extension + PpAtomExtension, + + // __LINE__, __FILE__, __VERSION__ + + PpAtomLineMacro, + PpAtomFileMacro, + PpAtomVersionMacro, + + // #include + PpAtomInclude, + + PpAtomLast, +}; + +} // end namespace glslang + +#endif /* not PARSER_H */ diff --git a/android/x86/include/glslang/MachineIndependent/propagateNoContraction.h b/android/x86/include/glslang/MachineIndependent/propagateNoContraction.h new file mode 100644 index 00000000..8521ad7d --- /dev/null +++ b/android/x86/include/glslang/MachineIndependent/propagateNoContraction.h @@ -0,0 +1,55 @@ +// +// Copyright (C) 2015-2016 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Visit the nodes in the glslang intermediate tree representation to +// propagate 'noContraction' qualifier. +// + +#pragma once + +#include "../Include/intermediate.h" + +namespace glslang { + +// Propagates the 'precise' qualifier for objects (objects marked with +// 'noContraction' qualifier) from the shader source specified 'precise' +// variables to all the involved objects, and add 'noContraction' qualifier for +// the involved arithmetic operations. +// Note that the same qualifier: 'noContraction' is used in both object nodes +// and arithmetic operation nodes, but has different meaning. For object nodes, +// 'noContraction' means the object is 'precise'; and for arithmetic operation +// nodes, it means the operation should not be contracted. +void PropagateNoContraction(const glslang::TIntermediate& intermediate); +}; diff --git a/android/x86/include/glslang/MachineIndependent/reflection.h b/android/x86/include/glslang/MachineIndependent/reflection.h new file mode 100644 index 00000000..0c33de45 --- /dev/null +++ b/android/x86/include/glslang/MachineIndependent/reflection.h @@ -0,0 +1,223 @@ +// +// Copyright (C) 2013-2016 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef GLSLANG_WEB + +#ifndef _REFLECTION_INCLUDED +#define _REFLECTION_INCLUDED + +#include "../Public/ShaderLang.h" +#include "../Include/Types.h" + +#include +#include + +// +// A reflection database and its interface, consistent with the OpenGL API reflection queries. +// + +namespace glslang { + +class TIntermediate; +class TIntermAggregate; +class TReflectionTraverser; + +// The full reflection database +class TReflection { +public: + TReflection(EShReflectionOptions opts, EShLanguage first, EShLanguage last) + : options(opts), firstStage(first), lastStage(last), badReflection(TObjectReflection::badReflection()) + { + for (int dim=0; dim<3; ++dim) + localSize[dim] = 0; + } + + virtual ~TReflection() {} + + // grow the reflection stage by stage + bool addStage(EShLanguage, const TIntermediate&); + + // for mapping a uniform index to a uniform object's description + int getNumUniforms() { return (int)indexToUniform.size(); } + const TObjectReflection& getUniform(int i) const + { + if (i >= 0 && i < (int)indexToUniform.size()) + return indexToUniform[i]; + else + return badReflection; + } + + // for mapping a block index to the block's description + int getNumUniformBlocks() const { return (int)indexToUniformBlock.size(); } + const TObjectReflection& getUniformBlock(int i) const + { + if (i >= 0 && i < (int)indexToUniformBlock.size()) + return indexToUniformBlock[i]; + else + return badReflection; + } + + // for mapping an pipeline input index to the input's description + int getNumPipeInputs() { return (int)indexToPipeInput.size(); } + const TObjectReflection& getPipeInput(int i) const + { + if (i >= 0 && i < (int)indexToPipeInput.size()) + return indexToPipeInput[i]; + else + return badReflection; + } + + // for mapping an pipeline output index to the output's description + int getNumPipeOutputs() { return (int)indexToPipeOutput.size(); } + const TObjectReflection& getPipeOutput(int i) const + { + if (i >= 0 && i < (int)indexToPipeOutput.size()) + return indexToPipeOutput[i]; + else + return badReflection; + } + + // for mapping from an atomic counter to the uniform index + int getNumAtomicCounters() const { return (int)atomicCounterUniformIndices.size(); } + const TObjectReflection& getAtomicCounter(int i) const + { + if (i >= 0 && i < (int)atomicCounterUniformIndices.size()) + return getUniform(atomicCounterUniformIndices[i]); + else + return badReflection; + } + + // for mapping a buffer variable index to a buffer variable object's description + int getNumBufferVariables() { return (int)indexToBufferVariable.size(); } + const TObjectReflection& getBufferVariable(int i) const + { + if (i >= 0 && i < (int)indexToBufferVariable.size()) + return indexToBufferVariable[i]; + else + return badReflection; + } + + // for mapping a storage block index to the storage block's description + int getNumStorageBuffers() const { return (int)indexToBufferBlock.size(); } + const TObjectReflection& getStorageBufferBlock(int i) const + { + if (i >= 0 && i < (int)indexToBufferBlock.size()) + return indexToBufferBlock[i]; + else + return badReflection; + } + + // for mapping any name to its index (block names, uniform names and input/output names) + int getIndex(const char* name) const + { + TNameToIndex::const_iterator it = nameToIndex.find(name); + if (it == nameToIndex.end()) + return -1; + else + return it->second; + } + + // see getIndex(const char*) + int getIndex(const TString& name) const { return getIndex(name.c_str()); } + + + // for mapping any name to its index (only pipe input/output names) + int getPipeIOIndex(const char* name, const bool inOrOut) const + { + TNameToIndex::const_iterator it = inOrOut ? pipeInNameToIndex.find(name) : pipeOutNameToIndex.find(name); + if (it == (inOrOut ? pipeInNameToIndex.end() : pipeOutNameToIndex.end())) + return -1; + else + return it->second; + } + + // see gePipeIOIndex(const char*, const bool) + int getPipeIOIndex(const TString& name, const bool inOrOut) const { return getPipeIOIndex(name.c_str(), inOrOut); } + + // Thread local size + unsigned getLocalSize(int dim) const { return dim <= 2 ? localSize[dim] : 0; } + + void dump(); + +protected: + friend class glslang::TReflectionTraverser; + + void buildCounterIndices(const TIntermediate&); + void buildUniformStageMask(const TIntermediate& intermediate); + void buildAttributeReflection(EShLanguage, const TIntermediate&); + + // Need a TString hash: typedef std::unordered_map TNameToIndex; + typedef std::map TNameToIndex; + typedef std::vector TMapIndexToReflection; + typedef std::vector TIndices; + + TMapIndexToReflection& GetBlockMapForStorage(TStorageQualifier storage) + { + if ((options & EShReflectionSeparateBuffers) && storage == EvqBuffer) + return indexToBufferBlock; + return indexToUniformBlock; + } + TMapIndexToReflection& GetVariableMapForStorage(TStorageQualifier storage) + { + if ((options & EShReflectionSeparateBuffers) && storage == EvqBuffer) + return indexToBufferVariable; + return indexToUniform; + } + + EShReflectionOptions options; + + EShLanguage firstStage; + EShLanguage lastStage; + + TObjectReflection badReflection; // return for queries of -1 or generally out of range; has expected descriptions with in it for this + TNameToIndex nameToIndex; // maps names to indexes; can hold all types of data: uniform/buffer and which function names have been processed + TNameToIndex pipeInNameToIndex; // maps pipe in names to indexes, this is a fix to seperate pipe I/O from uniforms and buffers. + TNameToIndex pipeOutNameToIndex; // maps pipe out names to indexes, this is a fix to seperate pipe I/O from uniforms and buffers. + TMapIndexToReflection indexToUniform; + TMapIndexToReflection indexToUniformBlock; + TMapIndexToReflection indexToBufferVariable; + TMapIndexToReflection indexToBufferBlock; + TMapIndexToReflection indexToPipeInput; + TMapIndexToReflection indexToPipeOutput; + TIndices atomicCounterUniformIndices; + + unsigned int localSize[3]; +}; + +} // end namespace glslang + +#endif // _REFLECTION_INCLUDED + +#endif // GLSLANG_WEB diff --git a/android/x86/include/glslang/Public/ShaderLang.h b/android/x86/include/glslang/Public/ShaderLang.h new file mode 100644 index 00000000..acb2a078 --- /dev/null +++ b/android/x86/include/glslang/Public/ShaderLang.h @@ -0,0 +1,927 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013-2016 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +#ifndef _COMPILER_INTERFACE_INCLUDED_ +#define _COMPILER_INTERFACE_INCLUDED_ + +#include "../Include/ResourceLimits.h" +#include "../MachineIndependent/Versions.h" + +#include +#include + +#ifdef _WIN32 +#define C_DECL __cdecl +//#ifdef SH_EXPORTING +// #define SH_IMPORT_EXPORT __declspec(dllexport) +//#else +// #define SH_IMPORT_EXPORT __declspec(dllimport) +//#endif +#define SH_IMPORT_EXPORT +#else +#define SH_IMPORT_EXPORT +#define C_DECL +#endif + +// +// This is the platform independent interface between an OGL driver +// and the shading language compiler/linker. +// + +#ifdef __cplusplus + extern "C" { +#endif + +// This should always increase, as some paths to do not consume +// a more major number. +// It should increment by one when new functionality is added. +#define GLSLANG_MINOR_VERSION 13 + +// +// Call before doing any other compiler/linker operations. +// +// (Call once per process, not once per thread.) +// +SH_IMPORT_EXPORT int ShInitialize(); + +// +// Call this at process shutdown to clean up memory. +// +SH_IMPORT_EXPORT int ShFinalize(); + +// +// Types of languages the compiler can consume. +// +typedef enum { + EShLangVertex, + EShLangTessControl, + EShLangTessEvaluation, + EShLangGeometry, + EShLangFragment, + EShLangCompute, + EShLangRayGen, + EShLangRayGenNV = EShLangRayGen, + EShLangIntersect, + EShLangIntersectNV = EShLangIntersect, + EShLangAnyHit, + EShLangAnyHitNV = EShLangAnyHit, + EShLangClosestHit, + EShLangClosestHitNV = EShLangClosestHit, + EShLangMiss, + EShLangMissNV = EShLangMiss, + EShLangCallable, + EShLangCallableNV = EShLangCallable, + EShLangTaskNV, + EShLangMeshNV, + LAST_ELEMENT_MARKER(EShLangCount), +} EShLanguage; // would be better as stage, but this is ancient now + +typedef enum { + EShLangVertexMask = (1 << EShLangVertex), + EShLangTessControlMask = (1 << EShLangTessControl), + EShLangTessEvaluationMask = (1 << EShLangTessEvaluation), + EShLangGeometryMask = (1 << EShLangGeometry), + EShLangFragmentMask = (1 << EShLangFragment), + EShLangComputeMask = (1 << EShLangCompute), + EShLangRayGenMask = (1 << EShLangRayGen), + EShLangRayGenNVMask = EShLangRayGenMask, + EShLangIntersectMask = (1 << EShLangIntersect), + EShLangIntersectNVMask = EShLangIntersectMask, + EShLangAnyHitMask = (1 << EShLangAnyHit), + EShLangAnyHitNVMask = EShLangAnyHitMask, + EShLangClosestHitMask = (1 << EShLangClosestHit), + EShLangClosestHitNVMask = EShLangClosestHitMask, + EShLangMissMask = (1 << EShLangMiss), + EShLangMissNVMask = EShLangMissMask, + EShLangCallableMask = (1 << EShLangCallable), + EShLangCallableNVMask = EShLangCallableMask, + EShLangTaskNVMask = (1 << EShLangTaskNV), + EShLangMeshNVMask = (1 << EShLangMeshNV), + LAST_ELEMENT_MARKER(EShLanguageMaskCount), +} EShLanguageMask; + +namespace glslang { + +class TType; + +typedef enum { + EShSourceNone, + EShSourceGlsl, // GLSL, includes ESSL (OpenGL ES GLSL) + EShSourceHlsl, // HLSL + LAST_ELEMENT_MARKER(EShSourceCount), +} EShSource; // if EShLanguage were EShStage, this could be EShLanguage instead + +typedef enum { + EShClientNone, // use when there is no client, e.g. for validation + EShClientVulkan, + EShClientOpenGL, + LAST_ELEMENT_MARKER(EShClientCount), +} EShClient; + +typedef enum { + EShTargetNone, + EShTargetSpv, // SPIR-V (preferred spelling) + EshTargetSpv = EShTargetSpv, // legacy spelling + LAST_ELEMENT_MARKER(EShTargetCount), +} EShTargetLanguage; + +typedef enum { + EShTargetVulkan_1_0 = (1 << 22), // Vulkan 1.0 + EShTargetVulkan_1_1 = (1 << 22) | (1 << 12), // Vulkan 1.1 + EShTargetVulkan_1_2 = (1 << 22) | (2 << 12), // Vulkan 1.2 + EShTargetOpenGL_450 = 450, // OpenGL + LAST_ELEMENT_MARKER(EShTargetClientVersionCount), +} EShTargetClientVersion; + +typedef EShTargetClientVersion EshTargetClientVersion; + +typedef enum { + EShTargetSpv_1_0 = (1 << 16), // SPIR-V 1.0 + EShTargetSpv_1_1 = (1 << 16) | (1 << 8), // SPIR-V 1.1 + EShTargetSpv_1_2 = (1 << 16) | (2 << 8), // SPIR-V 1.2 + EShTargetSpv_1_3 = (1 << 16) | (3 << 8), // SPIR-V 1.3 + EShTargetSpv_1_4 = (1 << 16) | (4 << 8), // SPIR-V 1.4 + EShTargetSpv_1_5 = (1 << 16) | (5 << 8), // SPIR-V 1.5 + LAST_ELEMENT_MARKER(EShTargetLanguageVersionCount), +} EShTargetLanguageVersion; + +struct TInputLanguage { + EShSource languageFamily; // redundant information with other input, this one overrides when not EShSourceNone + EShLanguage stage; // redundant information with other input, this one overrides when not EShSourceNone + EShClient dialect; + int dialectVersion; // version of client's language definition, not the client (when not EShClientNone) +}; + +struct TClient { + EShClient client; + EShTargetClientVersion version; // version of client itself (not the client's input dialect) +}; + +struct TTarget { + EShTargetLanguage language; + EShTargetLanguageVersion version; // version to target, if SPIR-V, defined by "word 1" of the SPIR-V header + bool hlslFunctionality1; // can target hlsl_functionality1 extension(s) +}; + +// All source/client/target versions and settings. +// Can override previous methods of setting, when items are set here. +// Expected to grow, as more are added, rather than growing parameter lists. +struct TEnvironment { + TInputLanguage input; // definition of the input language + TClient client; // what client is the overall compilation being done for? + TTarget target; // what to generate +}; + +const char* StageName(EShLanguage); + +} // end namespace glslang + +// +// Types of output the linker will create. +// +typedef enum { + EShExVertexFragment, + EShExFragment +} EShExecutable; + +// +// Optimization level for the compiler. +// +typedef enum { + EShOptNoGeneration, + EShOptNone, + EShOptSimple, // Optimizations that can be done quickly + EShOptFull, // Optimizations that will take more time + LAST_ELEMENT_MARKER(EshOptLevelCount), +} EShOptimizationLevel; + +// +// Texture and Sampler transformation mode. +// +typedef enum { + EShTexSampTransKeep, // keep textures and samplers as is (default) + EShTexSampTransUpgradeTextureRemoveSampler, // change texture w/o embeded sampler into sampled texture and throw away all samplers + LAST_ELEMENT_MARKER(EShTexSampTransCount), +} EShTextureSamplerTransformMode; + +// +// Message choices for what errors and warnings are given. +// +enum EShMessages { + EShMsgDefault = 0, // default is to give all required errors and extra warnings + EShMsgRelaxedErrors = (1 << 0), // be liberal in accepting input + EShMsgSuppressWarnings = (1 << 1), // suppress all warnings, except those required by the specification + EShMsgAST = (1 << 2), // print the AST intermediate representation + EShMsgSpvRules = (1 << 3), // issue messages for SPIR-V generation + EShMsgVulkanRules = (1 << 4), // issue messages for Vulkan-requirements of GLSL for SPIR-V + EShMsgOnlyPreprocessor = (1 << 5), // only print out errors produced by the preprocessor + EShMsgReadHlsl = (1 << 6), // use HLSL parsing rules and semantics + EShMsgCascadingErrors = (1 << 7), // get cascading errors; risks error-recovery issues, instead of an early exit + EShMsgKeepUncalled = (1 << 8), // for testing, don't eliminate uncalled functions + EShMsgHlslOffsets = (1 << 9), // allow block offsets to follow HLSL rules instead of GLSL rules + EShMsgDebugInfo = (1 << 10), // save debug information + EShMsgHlslEnable16BitTypes = (1 << 11), // enable use of 16-bit types in SPIR-V for HLSL + EShMsgHlslLegalization = (1 << 12), // enable HLSL Legalization messages + EShMsgHlslDX9Compatible = (1 << 13), // enable HLSL DX9 compatible mode (right now only for samplers) + EShMsgBuiltinSymbolTable = (1 << 14), // print the builtin symbol table + LAST_ELEMENT_MARKER(EShMsgCount), +}; + +// +// Options for building reflection +// +typedef enum { + EShReflectionDefault = 0, // default is original behaviour before options were added + EShReflectionStrictArraySuffix = (1 << 0), // reflection will follow stricter rules for array-of-structs suffixes + EShReflectionBasicArraySuffix = (1 << 1), // arrays of basic types will be appended with [0] as in GL reflection + EShReflectionIntermediateIO = (1 << 2), // reflect inputs and outputs to program, even with no vertex shader + EShReflectionSeparateBuffers = (1 << 3), // buffer variables and buffer blocks are reflected separately + EShReflectionAllBlockVariables = (1 << 4), // reflect all variables in blocks, even if they are inactive + EShReflectionUnwrapIOBlocks = (1 << 5), // unwrap input/output blocks the same as with uniform blocks + LAST_ELEMENT_MARKER(EShReflectionCount), +} EShReflectionOptions; + +// +// Build a table for bindings. This can be used for locating +// attributes, uniforms, globals, etc., as needed. +// +typedef struct { + const char* name; + int binding; +} ShBinding; + +typedef struct { + int numBindings; + ShBinding* bindings; // array of bindings +} ShBindingTable; + +// +// ShHandle held by but opaque to the driver. It is allocated, +// managed, and de-allocated by the compiler/linker. It's contents +// are defined by and used by the compiler and linker. For example, +// symbol table information and object code passed from the compiler +// to the linker can be stored where ShHandle points. +// +// If handle creation fails, 0 will be returned. +// +typedef void* ShHandle; + +// +// Driver calls these to create and destroy compiler/linker +// objects. +// +SH_IMPORT_EXPORT ShHandle ShConstructCompiler(const EShLanguage, int debugOptions); // one per shader +SH_IMPORT_EXPORT ShHandle ShConstructLinker(const EShExecutable, int debugOptions); // one per shader pair +SH_IMPORT_EXPORT ShHandle ShConstructUniformMap(); // one per uniform namespace (currently entire program object) +SH_IMPORT_EXPORT void ShDestruct(ShHandle); + +// +// The return value of ShCompile is boolean, non-zero indicating +// success. +// +// The info-log should be written by ShCompile into +// ShHandle, so it can answer future queries. +// +SH_IMPORT_EXPORT int ShCompile( + const ShHandle, + const char* const shaderStrings[], + const int numStrings, + const int* lengths, + const EShOptimizationLevel, + const TBuiltInResource *resources, + int debugOptions, + int defaultVersion = 110, // use 100 for ES environment, overridden by #version in shader + bool forwardCompatible = false, // give errors for use of deprecated features + EShMessages messages = EShMsgDefault // warnings and errors + ); + +SH_IMPORT_EXPORT int ShLinkExt( + const ShHandle, // linker object + const ShHandle h[], // compiler objects to link together + const int numHandles); + +// +// ShSetEncrpytionMethod is a place-holder for specifying +// how source code is encrypted. +// +SH_IMPORT_EXPORT void ShSetEncryptionMethod(ShHandle); + +// +// All the following return 0 if the information is not +// available in the object passed down, or the object is bad. +// +SH_IMPORT_EXPORT const char* ShGetInfoLog(const ShHandle); +SH_IMPORT_EXPORT const void* ShGetExecutable(const ShHandle); +SH_IMPORT_EXPORT int ShSetVirtualAttributeBindings(const ShHandle, const ShBindingTable*); // to detect user aliasing +SH_IMPORT_EXPORT int ShSetFixedAttributeBindings(const ShHandle, const ShBindingTable*); // to force any physical mappings +// +// Tell the linker to never assign a vertex attribute to this list of physical attributes +// +SH_IMPORT_EXPORT int ShExcludeAttributes(const ShHandle, int *attributes, int count); + +// +// Returns the location ID of the named uniform. +// Returns -1 if error. +// +SH_IMPORT_EXPORT int ShGetUniformLocation(const ShHandle uniformMap, const char* name); + +#ifdef __cplusplus + } // end extern "C" +#endif + +//////////////////////////////////////////////////////////////////////////////////////////// +// +// Deferred-Lowering C++ Interface +// ----------------------------------- +// +// Below is a new alternate C++ interface, which deprecates the above +// opaque handle-based interface. +// +// The below is further designed to handle multiple compilation units per stage, where +// the intermediate results, including the parse tree, are preserved until link time, +// rather than the above interface which is designed to have each compilation unit +// lowered at compile time. In the above model, linking occurs on the lowered results, +// whereas in this model intra-stage linking can occur at the parse tree +// (treeRoot in TIntermediate) level, and then a full stage can be lowered. +// + +#include +#include +#include + +class TCompiler; +class TInfoSink; + +namespace glslang { + +const char* GetEsslVersionString(); +const char* GetGlslVersionString(); +int GetKhronosToolId(); + +class TIntermediate; +class TProgram; +class TPoolAllocator; + +// Call this exactly once per process before using anything else +bool InitializeProcess(); + +// Call once per process to tear down everything +void FinalizeProcess(); + +// Resource type for IO resolver +enum TResourceType { + EResSampler, + EResTexture, + EResImage, + EResUbo, + EResSsbo, + EResUav, + EResCount +}; + +// Make one TShader per shader that you will link into a program. Then +// - provide the shader through setStrings() or setStringsWithLengths() +// - optionally call setEnv*(), see below for more detail +// - optionally use setPreamble() to set a special shader string that will be +// processed before all others but won't affect the validity of #version +// - optionally call addProcesses() for each setting/transform, +// see comment for class TProcesses +// - call parse(): source language and target environment must be selected +// either by correct setting of EShMessages sent to parse(), or by +// explicitly calling setEnv*() +// - query the info logs +// +// N.B.: Does not yet support having the same TShader instance being linked into +// multiple programs. +// +// N.B.: Destruct a linked program *before* destructing the shaders linked into it. +// +class TShader { +public: + explicit TShader(EShLanguage); + virtual ~TShader(); + void setStrings(const char* const* s, int n); + void setStringsWithLengths(const char* const* s, const int* l, int n); + void setStringsWithLengthsAndNames( + const char* const* s, const int* l, const char* const* names, int n); + void setPreamble(const char* s) { preamble = s; } + void setEntryPoint(const char* entryPoint); + void setSourceEntryPoint(const char* sourceEntryPointName); + void addProcesses(const std::vector&); + + // IO resolver binding data: see comments in ShaderLang.cpp + void setShiftBinding(TResourceType res, unsigned int base); + void setShiftSamplerBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftTextureBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftImageBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftUboBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftUavBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftCbufferBinding(unsigned int base); // synonym for setShiftUboBinding + void setShiftSsboBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftBindingForSet(TResourceType res, unsigned int base, unsigned int set); + void setResourceSetBinding(const std::vector& base); + void setAutoMapBindings(bool map); + void setAutoMapLocations(bool map); + void addUniformLocationOverride(const char* name, int loc); + void setUniformLocationBase(int base); + void setInvertY(bool invert); +#ifdef ENABLE_HLSL + void setHlslIoMapping(bool hlslIoMap); + void setFlattenUniformArrays(bool flatten); +#endif + void setNoStorageFormat(bool useUnknownFormat); + void setNanMinMaxClamp(bool nanMinMaxClamp); + void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode); + + // For setting up the environment (cleared to nothingness in the constructor). + // These must be called so that parsing is done for the right source language and + // target environment, either indirectly through TranslateEnvironment() based on + // EShMessages et. al., or directly by the user. + // + // setEnvInput: The input source language and stage. If generating code for a + // specific client, the input client semantics to use and the + // version of the that client's input semantics to use, otherwise + // use EShClientNone and version of 0, e.g. for validation mode. + // Note 'version' does not describe the target environment, + // just the version of the source dialect to compile under. + // + // See the definitions of TEnvironment, EShSource, EShLanguage, + // and EShClient for choices and more detail. + // + // setEnvClient: The client that will be hosting the execution, and it's version. + // Note 'version' is not the version of the languages involved, but + // the version of the client environment. + // Use EShClientNone and version of 0 if there is no client, e.g. + // for validation mode. + // + // See EShTargetClientVersion for choices. + // + // setEnvTarget: The language to translate to when generating code, and that + // language's version. + // Use EShTargetNone and version of 0 if there is no client, e.g. + // for validation mode. + // + void setEnvInput(EShSource lang, EShLanguage envStage, EShClient client, int version) + { + environment.input.languageFamily = lang; + environment.input.stage = envStage; + environment.input.dialect = client; + environment.input.dialectVersion = version; + } + void setEnvClient(EShClient client, EShTargetClientVersion version) + { + environment.client.client = client; + environment.client.version = version; + } + void setEnvTarget(EShTargetLanguage lang, EShTargetLanguageVersion version) + { + environment.target.language = lang; + environment.target.version = version; + } + + void getStrings(const char* const* &s, int& n) { s = strings; n = numStrings; } + +#ifdef ENABLE_HLSL + void setEnvTargetHlslFunctionality1() { environment.target.hlslFunctionality1 = true; } + bool getEnvTargetHlslFunctionality1() const { return environment.target.hlslFunctionality1; } +#else + bool getEnvTargetHlslFunctionality1() const { return false; } +#endif + + // Interface to #include handlers. + // + // To support #include, a client of Glslang does the following: + // 1. Call setStringsWithNames to set the source strings and associated + // names. For example, the names could be the names of the files + // containing the shader sources. + // 2. Call parse with an Includer. + // + // When the Glslang parser encounters an #include directive, it calls + // the Includer's include method with the requested include name + // together with the current string name. The returned IncludeResult + // contains the fully resolved name of the included source, together + // with the source text that should replace the #include directive + // in the source stream. After parsing that source, Glslang will + // release the IncludeResult object. + class Includer { + public: + // An IncludeResult contains the resolved name and content of a source + // inclusion. + struct IncludeResult { + IncludeResult(const std::string& headerName, const char* const headerData, const size_t headerLength, void* userData) : + headerName(headerName), headerData(headerData), headerLength(headerLength), userData(userData) { } + // For a successful inclusion, the fully resolved name of the requested + // include. For example, in a file system-based includer, full resolution + // should convert a relative path name into an absolute path name. + // For a failed inclusion, this is an empty string. + const std::string headerName; + // The content and byte length of the requested inclusion. The + // Includer producing this IncludeResult retains ownership of the + // storage. + // For a failed inclusion, the header + // field points to a string containing error details. + const char* const headerData; + const size_t headerLength; + // Include resolver's context. + void* userData; + protected: + IncludeResult& operator=(const IncludeResult&); + IncludeResult(); + }; + + // For both include methods below: + // + // Resolves an inclusion request by name, current source name, + // and include depth. + // On success, returns an IncludeResult containing the resolved name + // and content of the include. + // On failure, returns a nullptr, or an IncludeResult + // with an empty string for the headerName and error details in the + // header field. + // The Includer retains ownership of the contents + // of the returned IncludeResult value, and those contents must + // remain valid until the releaseInclude method is called on that + // IncludeResult object. + // + // Note "local" vs. "system" is not an "either/or": "local" is an + // extra thing to do over "system". Both might get called, as per + // the C++ specification. + + // For the "system" or <>-style includes; search the "system" paths. + virtual IncludeResult* includeSystem(const char* /*headerName*/, + const char* /*includerName*/, + size_t /*inclusionDepth*/) { return nullptr; } + + // For the "local"-only aspect of a "" include. Should not search in the + // "system" paths, because on returning a failure, the parser will + // call includeSystem() to look in the "system" locations. + virtual IncludeResult* includeLocal(const char* /*headerName*/, + const char* /*includerName*/, + size_t /*inclusionDepth*/) { return nullptr; } + + // Signals that the parser will no longer use the contents of the + // specified IncludeResult. + virtual void releaseInclude(IncludeResult*) = 0; + virtual ~Includer() {} + }; + + // Fail all Includer searches + class ForbidIncluder : public Includer { + public: + virtual void releaseInclude(IncludeResult*) override { } + }; + + bool parse(const TBuiltInResource*, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, + bool forwardCompatible, EShMessages, Includer&); + + bool parse(const TBuiltInResource* res, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, + bool forwardCompatible, EShMessages messages) + { + TShader::ForbidIncluder includer; + return parse(res, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, messages, includer); + } + + // Equivalent to parse() without a default profile and without forcing defaults. + bool parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages) + { + return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages); + } + + bool parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages, + Includer& includer) + { + return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages, includer); + } + + // NOTE: Doing just preprocessing to obtain a correct preprocessed shader string + // is not an officially supported or fully working path. + bool preprocess(const TBuiltInResource* builtInResources, + int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, + bool forwardCompatible, EShMessages message, std::string* outputString, + Includer& includer); + + const char* getInfoLog(); + const char* getInfoDebugLog(); + EShLanguage getStage() const { return stage; } + TIntermediate* getIntermediate() const { return intermediate; } + +protected: + TPoolAllocator* pool; + EShLanguage stage; + TCompiler* compiler; + TIntermediate* intermediate; + TInfoSink* infoSink; + // strings and lengths follow the standard for glShaderSource: + // strings is an array of numStrings pointers to string data. + // lengths can be null, but if not it is an array of numStrings + // integers containing the length of the associated strings. + // if lengths is null or lengths[n] < 0 the associated strings[n] is + // assumed to be null-terminated. + // stringNames is the optional names for all the strings. If stringNames + // is null, then none of the strings has name. If a certain element in + // stringNames is null, then the corresponding string does not have name. + const char* const* strings; // explicit code to compile, see previous comment + const int* lengths; + const char* const* stringNames; + int numStrings; // size of the above arrays + const char* preamble; // string of implicit code to compile before the explicitly provided code + + // a function in the source string can be renamed FROM this TO the name given in setEntryPoint. + std::string sourceEntryPointName; + + TEnvironment environment; + + friend class TProgram; + +private: + TShader& operator=(TShader&); +}; + +#ifndef GLSLANG_WEB + +// +// A reflection database and its interface, consistent with the OpenGL API reflection queries. +// + +// Data needed for just a single object at the granularity exchanged by the reflection API +class TObjectReflection { +public: + TObjectReflection(const std::string& pName, const TType& pType, int pOffset, int pGLDefineType, int pSize, int pIndex); + + const TType* getType() const { return type; } + int getBinding() const; + void dump() const; + static TObjectReflection badReflection() { return TObjectReflection(); } + + std::string name; + int offset; + int glDefineType; + int size; // data size in bytes for a block, array size for a (non-block) object that's an array + int index; + int counterIndex; + int numMembers; + int arrayStride; // stride of an array variable + int topLevelArrayStride; // stride of the top-level variable in a storage buffer member + EShLanguageMask stages; + +protected: + TObjectReflection() + : offset(-1), glDefineType(-1), size(-1), index(-1), counterIndex(-1), numMembers(-1), arrayStride(0), + topLevelArrayStride(0), stages(EShLanguageMask(0)), type(nullptr) + { + } + + const TType* type; +}; + +class TReflection; +class TIoMapper; +struct TVarEntryInfo; + +// Allows to customize the binding layout after linking. +// All used uniform variables will invoke at least validateBinding. +// If validateBinding returned true then the other resolveBinding, +// resolveSet, and resolveLocation are invoked to resolve the binding +// and descriptor set index respectively. +// +// Invocations happen in a particular order: +// 1) all shader inputs +// 2) all shader outputs +// 3) all uniforms with binding and set already defined +// 4) all uniforms with binding but no set defined +// 5) all uniforms with set but no binding defined +// 6) all uniforms with no binding and no set defined +// +// mapIO will use this resolver in two phases. The first +// phase is a notification phase, calling the corresponging +// notifiy callbacks, this phase ends with a call to endNotifications. +// Phase two starts directly after the call to endNotifications +// and calls all other callbacks to validate and to get the +// bindings, sets, locations, component and color indices. +// +// NOTE: that still limit checks are applied to bindings and sets +// and may result in an error. +class TIoMapResolver +{ +public: + virtual ~TIoMapResolver() {} + + // Should return true if the resulting/current binding would be okay. + // Basic idea is to do aliasing binding checks with this. + virtual bool validateBinding(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current binding should be overridden. + // Return -1 if the current binding (including no binding) should be kept. + virtual int resolveBinding(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current set should be overridden. + // Return -1 if the current set (including no set) should be kept. + virtual int resolveSet(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current location should be overridden. + // Return -1 if the current location (including no location) should be kept. + virtual int resolveUniformLocation(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return true if the resulting/current setup would be okay. + // Basic idea is to do aliasing checks and reject invalid semantic names. + virtual bool validateInOut(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current location should be overridden. + // Return -1 if the current location (including no location) should be kept. + virtual int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current component index should be overridden. + // Return -1 if the current component index (including no index) should be kept. + virtual int resolveInOutComponent(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current color index should be overridden. + // Return -1 if the current color index (including no index) should be kept. + virtual int resolveInOutIndex(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Notification of a uniform variable + virtual void notifyBinding(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Notification of a in or out variable + virtual void notifyInOut(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Called by mapIO when it starts its notify pass for the given stage + virtual void beginNotifications(EShLanguage stage) = 0; + // Called by mapIO when it has finished the notify pass + virtual void endNotifications(EShLanguage stage) = 0; + // Called by mipIO when it starts its resolve pass for the given stage + virtual void beginResolve(EShLanguage stage) = 0; + // Called by mapIO when it has finished the resolve pass + virtual void endResolve(EShLanguage stage) = 0; + // Called by mapIO when it starts its symbol collect for teh given stage + virtual void beginCollect(EShLanguage stage) = 0; + // Called by mapIO when it has finished the symbol collect + virtual void endCollect(EShLanguage stage) = 0; + // Called by TSlotCollector to resolve storage locations or bindings + virtual void reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) = 0; + // Called by TSlotCollector to resolve resource locations or bindings + virtual void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) = 0; + // Called by mapIO.addStage to set shader stage mask to mark a stage be added to this pipeline + virtual void addStage(EShLanguage stage) = 0; +}; + +#endif // GLSLANG_WEB + +// Make one TProgram per set of shaders that will get linked together. Add all +// the shaders that are to be linked together. After calling shader.parse() +// for all shaders, call link(). +// +// N.B.: Destruct a linked program *before* destructing the shaders linked into it. +// +class TProgram { +public: + TProgram(); + virtual ~TProgram(); + void addShader(TShader* shader) { stages[shader->stage].push_back(shader); } + std::list& getShaders(EShLanguage stage) { return stages[stage]; } + // Link Validation interface + bool link(EShMessages); + const char* getInfoLog(); + const char* getInfoDebugLog(); + + TIntermediate* getIntermediate(EShLanguage stage) const { return intermediate[stage]; } + +#ifndef GLSLANG_WEB + + // Reflection Interface + + // call first, to do liveness analysis, index mapping, etc.; returns false on failure + bool buildReflection(int opts = EShReflectionDefault); + unsigned getLocalSize(int dim) const; // return dim'th local size + int getReflectionIndex(const char *name) const; + int getReflectionPipeIOIndex(const char* name, const bool inOrOut) const; + int getNumUniformVariables() const; + const TObjectReflection& getUniform(int index) const; + int getNumUniformBlocks() const; + const TObjectReflection& getUniformBlock(int index) const; + int getNumPipeInputs() const; + const TObjectReflection& getPipeInput(int index) const; + int getNumPipeOutputs() const; + const TObjectReflection& getPipeOutput(int index) const; + int getNumBufferVariables() const; + const TObjectReflection& getBufferVariable(int index) const; + int getNumBufferBlocks() const; + const TObjectReflection& getBufferBlock(int index) const; + int getNumAtomicCounters() const; + const TObjectReflection& getAtomicCounter(int index) const; + + // Legacy Reflection Interface - expressed in terms of above interface + + // can be used for glGetProgramiv(GL_ACTIVE_UNIFORMS) + int getNumLiveUniformVariables() const { return getNumUniformVariables(); } + + // can be used for glGetProgramiv(GL_ACTIVE_UNIFORM_BLOCKS) + int getNumLiveUniformBlocks() const { return getNumUniformBlocks(); } + + // can be used for glGetProgramiv(GL_ACTIVE_ATTRIBUTES) + int getNumLiveAttributes() const { return getNumPipeInputs(); } + + // can be used for glGetUniformIndices() + int getUniformIndex(const char *name) const { return getReflectionIndex(name); } + + int getPipeIOIndex(const char *name, const bool inOrOut) const + { return getReflectionPipeIOIndex(name, inOrOut); } + + // can be used for "name" part of glGetActiveUniform() + const char *getUniformName(int index) const { return getUniform(index).name.c_str(); } + + // returns the binding number + int getUniformBinding(int index) const { return getUniform(index).getBinding(); } + + // returns Shaders Stages where a Uniform is present + EShLanguageMask getUniformStages(int index) const { return getUniform(index).stages; } + + // can be used for glGetActiveUniformsiv(GL_UNIFORM_BLOCK_INDEX) + int getUniformBlockIndex(int index) const { return getUniform(index).index; } + + // can be used for glGetActiveUniformsiv(GL_UNIFORM_TYPE) + int getUniformType(int index) const { return getUniform(index).glDefineType; } + + // can be used for glGetActiveUniformsiv(GL_UNIFORM_OFFSET) + int getUniformBufferOffset(int index) const { return getUniform(index).offset; } + + // can be used for glGetActiveUniformsiv(GL_UNIFORM_SIZE) + int getUniformArraySize(int index) const { return getUniform(index).size; } + + // returns a TType* + const TType *getUniformTType(int index) const { return getUniform(index).getType(); } + + // can be used for glGetActiveUniformBlockName() + const char *getUniformBlockName(int index) const { return getUniformBlock(index).name.c_str(); } + + // can be used for glGetActiveUniformBlockiv(UNIFORM_BLOCK_DATA_SIZE) + int getUniformBlockSize(int index) const { return getUniformBlock(index).size; } + + // returns the block binding number + int getUniformBlockBinding(int index) const { return getUniformBlock(index).getBinding(); } + + // returns block index of associated counter. + int getUniformBlockCounterIndex(int index) const { return getUniformBlock(index).counterIndex; } + + // returns a TType* + const TType *getUniformBlockTType(int index) const { return getUniformBlock(index).getType(); } + + // can be used for glGetActiveAttrib() + const char *getAttributeName(int index) const { return getPipeInput(index).name.c_str(); } + + // can be used for glGetActiveAttrib() + int getAttributeType(int index) const { return getPipeInput(index).glDefineType; } + + // returns a TType* + const TType *getAttributeTType(int index) const { return getPipeInput(index).getType(); } + + void dumpReflection(); + // I/O mapping: apply base offsets and map live unbound variables + // If resolver is not provided it uses the previous approach + // and respects auto assignment and offsets. + bool mapIO(TIoMapResolver* pResolver = nullptr, TIoMapper* pIoMapper = nullptr); +#endif + +protected: + bool linkStage(EShLanguage, EShMessages); + + TPoolAllocator* pool; + std::list stages[EShLangCount]; + TIntermediate* intermediate[EShLangCount]; + bool newedIntermediate[EShLangCount]; // track which intermediate were "new" versus reusing a singleton unit in a stage + TInfoSink* infoSink; +#ifndef GLSLANG_WEB + TReflection* reflection; +#endif + bool linked; + +private: + TProgram(TProgram&); + TProgram& operator=(TProgram&); +}; + +} // end namespace glslang + +#endif // _COMPILER_INTERFACE_INCLUDED_ diff --git a/android/x86/include/glslang/SPIRV/GLSL.ext.AMD.h b/android/x86/include/glslang/SPIRV/GLSL.ext.AMD.h new file mode 100644 index 00000000..009d2f1c --- /dev/null +++ b/android/x86/include/glslang/SPIRV/GLSL.ext.AMD.h @@ -0,0 +1,108 @@ +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextAMD_H +#define GLSLextAMD_H + +static const int GLSLextAMDVersion = 100; +static const int GLSLextAMDRevision = 7; + +// SPV_AMD_shader_ballot +static const char* const E_SPV_AMD_shader_ballot = "SPV_AMD_shader_ballot"; + +enum ShaderBallotAMD { + ShaderBallotBadAMD = 0, // Don't use + + SwizzleInvocationsAMD = 1, + SwizzleInvocationsMaskedAMD = 2, + WriteInvocationAMD = 3, + MbcntAMD = 4, + + ShaderBallotCountAMD +}; + +// SPV_AMD_shader_trinary_minmax +static const char* const E_SPV_AMD_shader_trinary_minmax = "SPV_AMD_shader_trinary_minmax"; + +enum ShaderTrinaryMinMaxAMD { + ShaderTrinaryMinMaxBadAMD = 0, // Don't use + + FMin3AMD = 1, + UMin3AMD = 2, + SMin3AMD = 3, + FMax3AMD = 4, + UMax3AMD = 5, + SMax3AMD = 6, + FMid3AMD = 7, + UMid3AMD = 8, + SMid3AMD = 9, + + ShaderTrinaryMinMaxCountAMD +}; + +// SPV_AMD_shader_explicit_vertex_parameter +static const char* const E_SPV_AMD_shader_explicit_vertex_parameter = "SPV_AMD_shader_explicit_vertex_parameter"; + +enum ShaderExplicitVertexParameterAMD { + ShaderExplicitVertexParameterBadAMD = 0, // Don't use + + InterpolateAtVertexAMD = 1, + + ShaderExplicitVertexParameterCountAMD +}; + +// SPV_AMD_gcn_shader +static const char* const E_SPV_AMD_gcn_shader = "SPV_AMD_gcn_shader"; + +enum GcnShaderAMD { + GcnShaderBadAMD = 0, // Don't use + + CubeFaceIndexAMD = 1, + CubeFaceCoordAMD = 2, + TimeAMD = 3, + + GcnShaderCountAMD +}; + +// SPV_AMD_gpu_shader_half_float +static const char* const E_SPV_AMD_gpu_shader_half_float = "SPV_AMD_gpu_shader_half_float"; + +// SPV_AMD_texture_gather_bias_lod +static const char* const E_SPV_AMD_texture_gather_bias_lod = "SPV_AMD_texture_gather_bias_lod"; + +// SPV_AMD_gpu_shader_int16 +static const char* const E_SPV_AMD_gpu_shader_int16 = "SPV_AMD_gpu_shader_int16"; + +// SPV_AMD_shader_image_load_store_lod +static const char* const E_SPV_AMD_shader_image_load_store_lod = "SPV_AMD_shader_image_load_store_lod"; + +// SPV_AMD_shader_fragment_mask +static const char* const E_SPV_AMD_shader_fragment_mask = "SPV_AMD_shader_fragment_mask"; + +// SPV_AMD_gpu_shader_half_float_fetch +static const char* const E_SPV_AMD_gpu_shader_half_float_fetch = "SPV_AMD_gpu_shader_half_float_fetch"; + +#endif // #ifndef GLSLextAMD_H diff --git a/android/x86/include/glslang/SPIRV/GLSL.ext.EXT.h b/android/x86/include/glslang/SPIRV/GLSL.ext.EXT.h new file mode 100644 index 00000000..40164b61 --- /dev/null +++ b/android/x86/include/glslang/SPIRV/GLSL.ext.EXT.h @@ -0,0 +1,39 @@ +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextEXT_H +#define GLSLextEXT_H + +static const int GLSLextEXTVersion = 100; +static const int GLSLextEXTRevision = 2; + +static const char* const E_SPV_EXT_shader_stencil_export = "SPV_EXT_shader_stencil_export"; +static const char* const E_SPV_EXT_shader_viewport_index_layer = "SPV_EXT_shader_viewport_index_layer"; +static const char* const E_SPV_EXT_fragment_fully_covered = "SPV_EXT_fragment_fully_covered"; +static const char* const E_SPV_EXT_fragment_invocation_density = "SPV_EXT_fragment_invocation_density"; +static const char* const E_SPV_EXT_demote_to_helper_invocation = "SPV_EXT_demote_to_helper_invocation"; + +#endif // #ifndef GLSLextEXT_H diff --git a/android/x86/include/glslang/SPIRV/GLSL.ext.KHR.h b/android/x86/include/glslang/SPIRV/GLSL.ext.KHR.h new file mode 100644 index 00000000..d783a8f2 --- /dev/null +++ b/android/x86/include/glslang/SPIRV/GLSL.ext.KHR.h @@ -0,0 +1,51 @@ +/* +** Copyright (c) 2014-2020 The Khronos Group Inc. +** Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextKHR_H +#define GLSLextKHR_H + +static const int GLSLextKHRVersion = 100; +static const int GLSLextKHRRevision = 2; + +static const char* const E_SPV_KHR_shader_ballot = "SPV_KHR_shader_ballot"; +static const char* const E_SPV_KHR_subgroup_vote = "SPV_KHR_subgroup_vote"; +static const char* const E_SPV_KHR_device_group = "SPV_KHR_device_group"; +static const char* const E_SPV_KHR_multiview = "SPV_KHR_multiview"; +static const char* const E_SPV_KHR_shader_draw_parameters = "SPV_KHR_shader_draw_parameters"; +static const char* const E_SPV_KHR_16bit_storage = "SPV_KHR_16bit_storage"; +static const char* const E_SPV_KHR_8bit_storage = "SPV_KHR_8bit_storage"; +static const char* const E_SPV_KHR_storage_buffer_storage_class = "SPV_KHR_storage_buffer_storage_class"; +static const char* const E_SPV_KHR_post_depth_coverage = "SPV_KHR_post_depth_coverage"; +static const char* const E_SPV_KHR_vulkan_memory_model = "SPV_KHR_vulkan_memory_model"; +static const char* const E_SPV_EXT_physical_storage_buffer = "SPV_EXT_physical_storage_buffer"; +static const char* const E_SPV_KHR_physical_storage_buffer = "SPV_KHR_physical_storage_buffer"; +static const char* const E_SPV_EXT_fragment_shader_interlock = "SPV_EXT_fragment_shader_interlock"; +static const char* const E_SPV_KHR_shader_clock = "SPV_KHR_shader_clock"; +static const char* const E_SPV_KHR_non_semantic_info = "SPV_KHR_non_semantic_info"; +static const char* const E_SPV_KHR_ray_tracing = "SPV_KHR_ray_tracing"; +static const char* const E_SPV_KHR_ray_query = "SPV_KHR_ray_query"; +#endif // #ifndef GLSLextKHR_H diff --git a/android/x86/include/glslang/SPIRV/GLSL.ext.NV.h b/android/x86/include/glslang/SPIRV/GLSL.ext.NV.h new file mode 100644 index 00000000..50146da1 --- /dev/null +++ b/android/x86/include/glslang/SPIRV/GLSL.ext.NV.h @@ -0,0 +1,81 @@ +/* +** Copyright (c) 2014-2017 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextNV_H +#define GLSLextNV_H + +enum BuiltIn; +enum Decoration; +enum Op; +enum Capability; + +static const int GLSLextNVVersion = 100; +static const int GLSLextNVRevision = 11; + +//SPV_NV_sample_mask_override_coverage +const char* const E_SPV_NV_sample_mask_override_coverage = "SPV_NV_sample_mask_override_coverage"; + +//SPV_NV_geometry_shader_passthrough +const char* const E_SPV_NV_geometry_shader_passthrough = "SPV_NV_geometry_shader_passthrough"; + +//SPV_NV_viewport_array2 +const char* const E_SPV_NV_viewport_array2 = "SPV_NV_viewport_array2"; +const char* const E_ARB_shader_viewport_layer_array = "SPV_ARB_shader_viewport_layer_array"; + +//SPV_NV_stereo_view_rendering +const char* const E_SPV_NV_stereo_view_rendering = "SPV_NV_stereo_view_rendering"; + +//SPV_NVX_multiview_per_view_attributes +const char* const E_SPV_NVX_multiview_per_view_attributes = "SPV_NVX_multiview_per_view_attributes"; + +//SPV_NV_shader_subgroup_partitioned +const char* const E_SPV_NV_shader_subgroup_partitioned = "SPV_NV_shader_subgroup_partitioned"; + +//SPV_NV_fragment_shader_barycentric +const char* const E_SPV_NV_fragment_shader_barycentric = "SPV_NV_fragment_shader_barycentric"; + +//SPV_NV_compute_shader_derivatives +const char* const E_SPV_NV_compute_shader_derivatives = "SPV_NV_compute_shader_derivatives"; + +//SPV_NV_shader_image_footprint +const char* const E_SPV_NV_shader_image_footprint = "SPV_NV_shader_image_footprint"; + +//SPV_NV_mesh_shader +const char* const E_SPV_NV_mesh_shader = "SPV_NV_mesh_shader"; + +//SPV_NV_raytracing +const char* const E_SPV_NV_ray_tracing = "SPV_NV_ray_tracing"; + +//SPV_NV_shading_rate +const char* const E_SPV_NV_shading_rate = "SPV_NV_shading_rate"; + +//SPV_NV_cooperative_matrix +const char* const E_SPV_NV_cooperative_matrix = "SPV_NV_cooperative_matrix"; + +//SPV_NV_shader_sm_builtins +const char* const E_SPV_NV_shader_sm_builtins = "SPV_NV_shader_sm_builtins"; + +#endif // #ifndef GLSLextNV_H diff --git a/android/x86/include/glslang/SPIRV/GLSL.std.450.h b/android/x86/include/glslang/SPIRV/GLSL.std.450.h new file mode 100644 index 00000000..df31092b --- /dev/null +++ b/android/x86/include/glslang/SPIRV/GLSL.std.450.h @@ -0,0 +1,131 @@ +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLstd450_H +#define GLSLstd450_H + +static const int GLSLstd450Version = 100; +static const int GLSLstd450Revision = 1; + +enum GLSLstd450 { + GLSLstd450Bad = 0, // Don't use + + GLSLstd450Round = 1, + GLSLstd450RoundEven = 2, + GLSLstd450Trunc = 3, + GLSLstd450FAbs = 4, + GLSLstd450SAbs = 5, + GLSLstd450FSign = 6, + GLSLstd450SSign = 7, + GLSLstd450Floor = 8, + GLSLstd450Ceil = 9, + GLSLstd450Fract = 10, + + GLSLstd450Radians = 11, + GLSLstd450Degrees = 12, + GLSLstd450Sin = 13, + GLSLstd450Cos = 14, + GLSLstd450Tan = 15, + GLSLstd450Asin = 16, + GLSLstd450Acos = 17, + GLSLstd450Atan = 18, + GLSLstd450Sinh = 19, + GLSLstd450Cosh = 20, + GLSLstd450Tanh = 21, + GLSLstd450Asinh = 22, + GLSLstd450Acosh = 23, + GLSLstd450Atanh = 24, + GLSLstd450Atan2 = 25, + + GLSLstd450Pow = 26, + GLSLstd450Exp = 27, + GLSLstd450Log = 28, + GLSLstd450Exp2 = 29, + GLSLstd450Log2 = 30, + GLSLstd450Sqrt = 31, + GLSLstd450InverseSqrt = 32, + + GLSLstd450Determinant = 33, + GLSLstd450MatrixInverse = 34, + + GLSLstd450Modf = 35, // second operand needs an OpVariable to write to + GLSLstd450ModfStruct = 36, // no OpVariable operand + GLSLstd450FMin = 37, + GLSLstd450UMin = 38, + GLSLstd450SMin = 39, + GLSLstd450FMax = 40, + GLSLstd450UMax = 41, + GLSLstd450SMax = 42, + GLSLstd450FClamp = 43, + GLSLstd450UClamp = 44, + GLSLstd450SClamp = 45, + GLSLstd450FMix = 46, + GLSLstd450IMix = 47, // Reserved + GLSLstd450Step = 48, + GLSLstd450SmoothStep = 49, + + GLSLstd450Fma = 50, + GLSLstd450Frexp = 51, // second operand needs an OpVariable to write to + GLSLstd450FrexpStruct = 52, // no OpVariable operand + GLSLstd450Ldexp = 53, + + GLSLstd450PackSnorm4x8 = 54, + GLSLstd450PackUnorm4x8 = 55, + GLSLstd450PackSnorm2x16 = 56, + GLSLstd450PackUnorm2x16 = 57, + GLSLstd450PackHalf2x16 = 58, + GLSLstd450PackDouble2x32 = 59, + GLSLstd450UnpackSnorm2x16 = 60, + GLSLstd450UnpackUnorm2x16 = 61, + GLSLstd450UnpackHalf2x16 = 62, + GLSLstd450UnpackSnorm4x8 = 63, + GLSLstd450UnpackUnorm4x8 = 64, + GLSLstd450UnpackDouble2x32 = 65, + + GLSLstd450Length = 66, + GLSLstd450Distance = 67, + GLSLstd450Cross = 68, + GLSLstd450Normalize = 69, + GLSLstd450FaceForward = 70, + GLSLstd450Reflect = 71, + GLSLstd450Refract = 72, + + GLSLstd450FindILsb = 73, + GLSLstd450FindSMsb = 74, + GLSLstd450FindUMsb = 75, + + GLSLstd450InterpolateAtCentroid = 76, + GLSLstd450InterpolateAtSample = 77, + GLSLstd450InterpolateAtOffset = 78, + + GLSLstd450NMin = 79, + GLSLstd450NMax = 80, + GLSLstd450NClamp = 81, + + GLSLstd450Count +}; + +#endif // #ifndef GLSLstd450_H diff --git a/android/x86/include/glslang/SPIRV/GlslangToSpv.h b/android/x86/include/glslang/SPIRV/GlslangToSpv.h new file mode 100644 index 00000000..3907be43 --- /dev/null +++ b/android/x86/include/glslang/SPIRV/GlslangToSpv.h @@ -0,0 +1,61 @@ +// +// Copyright (C) 2014 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#pragma once + +#if defined(_MSC_VER) && _MSC_VER >= 1900 + #pragma warning(disable : 4464) // relative include path contains '..' +#endif + +#include "SpvTools.h" +#include "glslang/Include/intermediate.h" + +#include +#include + +#include "Logger.h" + +namespace glslang { + +void GetSpirvVersion(std::string&); +int GetSpirvGeneratorVersion(); +void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, + SpvOptions* options = nullptr); +void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger* logger, SpvOptions* options = nullptr); +void OutputSpvBin(const std::vector& spirv, const char* baseName); +void OutputSpvHex(const std::vector& spirv, const char* baseName, const char* varName); + +} diff --git a/android/x86/include/glslang/SPIRV/Logger.h b/android/x86/include/glslang/SPIRV/Logger.h new file mode 100644 index 00000000..411367c0 --- /dev/null +++ b/android/x86/include/glslang/SPIRV/Logger.h @@ -0,0 +1,83 @@ +// +// Copyright (C) 2016 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef GLSLANG_SPIRV_LOGGER_H +#define GLSLANG_SPIRV_LOGGER_H + +#include +#include + +namespace spv { + +// A class for holding all SPIR-V build status messages, including +// missing/TBD functionalities, warnings, and errors. +class SpvBuildLogger { +public: + SpvBuildLogger() {} + +#ifdef GLSLANG_WEB + void tbdFunctionality(const std::string& f) { } + void missingFunctionality(const std::string& f) { } + void warning(const std::string& w) { } + void error(const std::string& e) { errors.push_back(e); } + std::string getAllMessages() { return ""; } +#else + + // Registers a TBD functionality. + void tbdFunctionality(const std::string& f); + // Registers a missing functionality. + void missingFunctionality(const std::string& f); + + // Logs a warning. + void warning(const std::string& w) { warnings.push_back(w); } + // Logs an error. + void error(const std::string& e) { errors.push_back(e); } + + // Returns all messages accumulated in the order of: + // TBD functionalities, missing functionalities, warnings, errors. + std::string getAllMessages() const; +#endif + +private: + SpvBuildLogger(const SpvBuildLogger&); + + std::vector tbdFeatures; + std::vector missingFeatures; + std::vector warnings; + std::vector errors; +}; + +} // end spv namespace + +#endif // GLSLANG_SPIRV_LOGGER_H diff --git a/android/x86/include/glslang/SPIRV/NonSemanticDebugPrintf.h b/android/x86/include/glslang/SPIRV/NonSemanticDebugPrintf.h new file mode 100644 index 00000000..83796d75 --- /dev/null +++ b/android/x86/include/glslang/SPIRV/NonSemanticDebugPrintf.h @@ -0,0 +1,50 @@ +// Copyright (c) 2020 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and/or associated documentation files (the +// "Materials"), to deal in the Materials without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Materials, and to +// permit persons to whom the Materials are furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS +// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS +// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT +// https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +// + +#ifndef SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ +#define SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + NonSemanticDebugPrintfRevision = 1, + NonSemanticDebugPrintfRevision_BitWidthPadding = 0x7fffffff +}; + +enum NonSemanticDebugPrintfInstructions { + NonSemanticDebugPrintfDebugPrintf = 1, + NonSemanticDebugPrintfInstructionsMax = 0x7fffffff +}; + + +#ifdef __cplusplus +} +#endif + +#endif // SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ diff --git a/android/x86/include/glslang/SPIRV/SPVRemapper.h b/android/x86/include/glslang/SPIRV/SPVRemapper.h new file mode 100644 index 00000000..d6b9c346 --- /dev/null +++ b/android/x86/include/glslang/SPIRV/SPVRemapper.h @@ -0,0 +1,304 @@ +// +// Copyright (C) 2015 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef SPIRVREMAPPER_H +#define SPIRVREMAPPER_H + +#include +#include +#include +#include + +namespace spv { + +// MSVC defines __cplusplus as an older value, even when it supports almost all of 11. +// We handle that here by making our own symbol. +#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1700) +# define use_cpp11 1 +#endif + +class spirvbin_base_t +{ +public: + enum Options { + NONE = 0, + STRIP = (1<<0), + MAP_TYPES = (1<<1), + MAP_NAMES = (1<<2), + MAP_FUNCS = (1<<3), + DCE_FUNCS = (1<<4), + DCE_VARS = (1<<5), + DCE_TYPES = (1<<6), + OPT_LOADSTORE = (1<<7), + OPT_FWD_LS = (1<<8), // EXPERIMENTAL: PRODUCES INVALID SCHEMA-0 SPIRV + MAP_ALL = (MAP_TYPES | MAP_NAMES | MAP_FUNCS), + DCE_ALL = (DCE_FUNCS | DCE_VARS | DCE_TYPES), + OPT_ALL = (OPT_LOADSTORE), + + ALL_BUT_STRIP = (MAP_ALL | DCE_ALL | OPT_ALL), + DO_EVERYTHING = (STRIP | ALL_BUT_STRIP) + }; +}; + +} // namespace SPV + +#if !defined (use_cpp11) +#include +#include + +namespace spv { +class spirvbin_t : public spirvbin_base_t +{ +public: + spirvbin_t(int /*verbose = 0*/) { } + + void remap(std::vector& /*spv*/, unsigned int /*opts = 0*/) + { + printf("Tool not compiled for C++11, which is required for SPIR-V remapping.\n"); + exit(5); + } +}; + +} // namespace SPV + +#else // defined (use_cpp11) + +#include +#include +#include +#include +#include +#include +#include + +#include "spirv.hpp" +#include "spvIR.h" + +namespace spv { + +// class to hold SPIR-V binary data for remapping, DCE, and debug stripping +class spirvbin_t : public spirvbin_base_t +{ +public: + spirvbin_t(int verbose = 0) : entryPoint(spv::NoResult), largestNewId(0), verbose(verbose), errorLatch(false) + { } + + virtual ~spirvbin_t() { } + + // remap on an existing binary in memory + void remap(std::vector& spv, std::uint32_t opts = DO_EVERYTHING); + + // Type for error/log handler functions + typedef std::function errorfn_t; + typedef std::function logfn_t; + + // Register error/log handling functions (can be lambda fn / functor / etc) + static void registerErrorHandler(errorfn_t handler) { errorHandler = handler; } + static void registerLogHandler(logfn_t handler) { logHandler = handler; } + +protected: + // This can be overridden to provide other message behavior if needed + virtual void msg(int minVerbosity, int indent, const std::string& txt) const; + +private: + // Local to global, or global to local ID map + typedef std::unordered_map idmap_t; + typedef std::unordered_set idset_t; + typedef std::unordered_map blockmap_t; + + void remap(std::uint32_t opts = DO_EVERYTHING); + + // Map of names to IDs + typedef std::unordered_map namemap_t; + + typedef std::uint32_t spirword_t; + + typedef std::pair range_t; + typedef std::function idfn_t; + typedef std::function instfn_t; + + // Special Values for ID map: + static const spv::Id unmapped; // unchanged from default value + static const spv::Id unused; // unused ID + static const int header_size; // SPIR header = 5 words + + class id_iterator_t; + + // For mapping type entries between different shaders + typedef std::vector typeentry_t; + typedef std::map globaltypes_t; + + // A set that preserves position order, and a reverse map + typedef std::set posmap_t; + typedef std::unordered_map posmap_rev_t; + + // Maps and ID to the size of its base type, if known. + typedef std::unordered_map typesize_map_t; + + // handle error + void error(const std::string& txt) const { errorLatch = true; errorHandler(txt); } + + bool isConstOp(spv::Op opCode) const; + bool isTypeOp(spv::Op opCode) const; + bool isStripOp(spv::Op opCode) const; + bool isFlowCtrl(spv::Op opCode) const; + range_t literalRange(spv::Op opCode) const; + range_t typeRange(spv::Op opCode) const; + range_t constRange(spv::Op opCode) const; + unsigned typeSizeInWords(spv::Id id) const; + unsigned idTypeSizeInWords(spv::Id id) const; + + spv::Id& asId(unsigned word) { return spv[word]; } + const spv::Id& asId(unsigned word) const { return spv[word]; } + spv::Op asOpCode(unsigned word) const { return opOpCode(spv[word]); } + std::uint32_t asOpCodeHash(unsigned word); + spv::Decoration asDecoration(unsigned word) const { return spv::Decoration(spv[word]); } + unsigned asWordCount(unsigned word) const { return opWordCount(spv[word]); } + spv::Id asTypeConstId(unsigned word) const { return asId(word + (isTypeOp(asOpCode(word)) ? 1 : 2)); } + unsigned idPos(spv::Id id) const; + + static unsigned opWordCount(spirword_t data) { return data >> spv::WordCountShift; } + static spv::Op opOpCode(spirword_t data) { return spv::Op(data & spv::OpCodeMask); } + + // Header access & set methods + spirword_t magic() const { return spv[0]; } // return magic number + spirword_t bound() const { return spv[3]; } // return Id bound from header + spirword_t bound(spirword_t b) { return spv[3] = b; } + spirword_t genmagic() const { return spv[2]; } // generator magic + spirword_t genmagic(spirword_t m) { return spv[2] = m; } + spirword_t schemaNum() const { return spv[4]; } // schema number from header + + // Mapping fns: get + spv::Id localId(spv::Id id) const { return idMapL[id]; } + + // Mapping fns: set + inline spv::Id localId(spv::Id id, spv::Id newId); + void countIds(spv::Id id); + + // Return next unused new local ID. + // NOTE: boost::dynamic_bitset would be more efficient due to find_next(), + // which std::vector doens't have. + inline spv::Id nextUnusedId(spv::Id id); + + void buildLocalMaps(); + std::string literalString(unsigned word) const; // Return literal as a std::string + int literalStringWords(const std::string& str) const { return (int(str.size())+4)/4; } + + bool isNewIdMapped(spv::Id newId) const { return isMapped(newId); } + bool isOldIdUnmapped(spv::Id oldId) const { return localId(oldId) == unmapped; } + bool isOldIdUnused(spv::Id oldId) const { return localId(oldId) == unused; } + bool isOldIdMapped(spv::Id oldId) const { return !isOldIdUnused(oldId) && !isOldIdUnmapped(oldId); } + bool isFunction(spv::Id oldId) const { return fnPos.find(oldId) != fnPos.end(); } + + // bool matchType(const globaltypes_t& globalTypes, spv::Id lt, spv::Id gt) const; + // spv::Id findType(const globaltypes_t& globalTypes, spv::Id lt) const; + std::uint32_t hashType(unsigned typeStart) const; + + spirvbin_t& process(instfn_t, idfn_t, unsigned begin = 0, unsigned end = 0); + int processInstruction(unsigned word, instfn_t, idfn_t); + + void validate() const; + void mapTypeConst(); + void mapFnBodies(); + void optLoadStore(); + void dceFuncs(); + void dceVars(); + void dceTypes(); + void mapNames(); + void foldIds(); // fold IDs to smallest space + void forwardLoadStores(); // load store forwarding (EXPERIMENTAL) + void offsetIds(); // create relative offset IDs + + void applyMap(); // remap per local name map + void mapRemainder(); // map any IDs we haven't touched yet + void stripDebug(); // strip all debug info + void stripDeadRefs(); // strips debug info for now-dead references after DCE + void strip(); // remove debug symbols + + std::vector spv; // SPIR words + + namemap_t nameMap; // ID names from OpName + + // Since we want to also do binary ops, we can't use std::vector. we could use + // boost::dynamic_bitset, but we're trying to avoid a boost dependency. + typedef std::uint64_t bits_t; + std::vector mapped; // which new IDs have been mapped + static const int mBits = sizeof(bits_t) * 4; + + bool isMapped(spv::Id id) const { return id < maxMappedId() && ((mapped[id/mBits] & (1LL<<(id%mBits))) != 0); } + void setMapped(spv::Id id) { resizeMapped(id); mapped[id/mBits] |= (1LL<<(id%mBits)); } + void resizeMapped(spv::Id id) { if (id >= maxMappedId()) mapped.resize(id/mBits+1, 0); } + size_t maxMappedId() const { return mapped.size() * mBits; } + + // Add a strip range for a given instruction starting at 'start' + // Note: avoiding brace initializers to please older versions os MSVC. + void stripInst(unsigned start) { stripRange.push_back(range_t(start, start + asWordCount(start))); } + + // Function start and end. use unordered_map because we'll have + // many fewer functions than IDs. + std::unordered_map fnPos; + + // Which functions are called, anywhere in the module, with a call count + std::unordered_map fnCalls; + + posmap_t typeConstPos; // word positions that define types & consts (ordered) + posmap_rev_t idPosR; // reverse map from IDs to positions + typesize_map_t idTypeSizeMap; // maps each ID to its type size, if known. + + std::vector idMapL; // ID {M}ap from {L}ocal to {G}lobal IDs + + spv::Id entryPoint; // module entry point + spv::Id largestNewId; // biggest new ID we have mapped anything to + + // Sections of the binary to strip, given as [begin,end) + std::vector stripRange; + + // processing options: + std::uint32_t options; + int verbose; // verbosity level + + // Error latch: this is set if the error handler is ever executed. It would be better to + // use a try/catch block and throw, but that's not desired for certain environments, so + // this is the alternative. + mutable bool errorLatch; + + static errorfn_t errorHandler; + static logfn_t logHandler; +}; + +} // namespace SPV + +#endif // defined (use_cpp11) +#endif // SPIRVREMAPPER_H diff --git a/android/x86/include/glslang/SPIRV/SpvBuilder.h b/android/x86/include/glslang/SPIRV/SpvBuilder.h new file mode 100644 index 00000000..71b90d60 --- /dev/null +++ b/android/x86/include/glslang/SPIRV/SpvBuilder.h @@ -0,0 +1,838 @@ +// +// Copyright (C) 2014-2015 LunarG, Inc. +// Copyright (C) 2015-2020 Google, Inc. +// Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// "Builder" is an interface to fully build SPIR-V IR. Allocate one of +// these to build (a thread safe) internal SPIR-V representation (IR), +// and then dump it as a binary stream according to the SPIR-V specification. +// +// A Builder has a 1:1 relationship with a SPIR-V module. +// + +#pragma once +#ifndef SpvBuilder_H +#define SpvBuilder_H + +#include "Logger.h" +#include "spirv.hpp" +#include "spvIR.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace spv { + +typedef enum { + Spv_1_0 = (1 << 16), + Spv_1_1 = (1 << 16) | (1 << 8), + Spv_1_2 = (1 << 16) | (2 << 8), + Spv_1_3 = (1 << 16) | (3 << 8), + Spv_1_4 = (1 << 16) | (4 << 8), + Spv_1_5 = (1 << 16) | (5 << 8), +} SpvVersion; + +class Builder { +public: + Builder(unsigned int spvVersion, unsigned int userNumber, SpvBuildLogger* logger); + virtual ~Builder(); + + static const int maxMatrixSize = 4; + + unsigned int getSpvVersion() const { return spvVersion; } + + void setSource(spv::SourceLanguage lang, int version) + { + source = lang; + sourceVersion = version; + } + spv::Id getStringId(const std::string& str) + { + auto sItr = stringIds.find(str); + if (sItr != stringIds.end()) + return sItr->second; + spv::Id strId = getUniqueId(); + Instruction* fileString = new Instruction(strId, NoType, OpString); + const char* file_c_str = str.c_str(); + fileString->addStringOperand(file_c_str); + strings.push_back(std::unique_ptr(fileString)); + module.mapInstruction(fileString); + stringIds[file_c_str] = strId; + return strId; + } + void setSourceFile(const std::string& file) + { + sourceFileStringId = getStringId(file); + } + void setSourceText(const std::string& text) { sourceText = text; } + void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); } + void addModuleProcessed(const std::string& p) { moduleProcesses.push_back(p.c_str()); } + void setEmitOpLines() { emitOpLines = true; } + void addExtension(const char* ext) { extensions.insert(ext); } + void removeExtension(const char* ext) + { + extensions.erase(ext); + } + void addIncorporatedExtension(const char* ext, SpvVersion incorporatedVersion) + { + if (getSpvVersion() < static_cast(incorporatedVersion)) + addExtension(ext); + } + void promoteIncorporatedExtension(const char* baseExt, const char* promoExt, SpvVersion incorporatedVersion) + { + removeExtension(baseExt); + addIncorporatedExtension(promoExt, incorporatedVersion); + } + void addInclude(const std::string& name, const std::string& text) + { + spv::Id incId = getStringId(name); + includeFiles[incId] = &text; + } + Id import(const char*); + void setMemoryModel(spv::AddressingModel addr, spv::MemoryModel mem) + { + addressModel = addr; + memoryModel = mem; + } + + void addCapability(spv::Capability cap) { capabilities.insert(cap); } + + // To get a new for anything needing a new one. + Id getUniqueId() { return ++uniqueId; } + + // To get a set of new s, e.g., for a set of function parameters + Id getUniqueIds(int numIds) + { + Id id = uniqueId + 1; + uniqueId += numIds; + return id; + } + + // Generate OpLine for non-filename-based #line directives (ie no filename + // seen yet): Log the current line, and if different than the last one, + // issue a new OpLine using the new line and current source file name. + void setLine(int line); + + // If filename null, generate OpLine for non-filename-based line directives, + // else do filename-based: Log the current line and file, and if different + // than the last one, issue a new OpLine using the new line and file + // name. + void setLine(int line, const char* filename); + // Low-level OpLine. See setLine() for a layered helper. + void addLine(Id fileName, int line, int column); + + // For creating new types (will return old type if the requested one was already made). + Id makeVoidType(); + Id makeBoolType(); + Id makePointer(StorageClass, Id pointee); + Id makeForwardPointer(StorageClass); + Id makePointerFromForwardPointer(StorageClass, Id forwardPointerType, Id pointee); + Id makeIntegerType(int width, bool hasSign); // generic + Id makeIntType(int width) { return makeIntegerType(width, true); } + Id makeUintType(int width) { return makeIntegerType(width, false); } + Id makeFloatType(int width); + Id makeStructType(const std::vector& members, const char*); + Id makeStructResultType(Id type0, Id type1); + Id makeVectorType(Id component, int size); + Id makeMatrixType(Id component, int cols, int rows); + Id makeArrayType(Id element, Id sizeId, int stride); // 0 stride means no stride decoration + Id makeRuntimeArray(Id element); + Id makeFunctionType(Id returnType, const std::vector& paramTypes); + Id makeImageType(Id sampledType, Dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format); + Id makeSamplerType(); + Id makeSampledImageType(Id imageType); + Id makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols); + + // accelerationStructureNV type + Id makeAccelerationStructureType(); + // rayQueryEXT type + Id makeRayQueryType(); + + // For querying about types. + Id getTypeId(Id resultId) const { return module.getTypeId(resultId); } + Id getDerefTypeId(Id resultId) const; + Op getOpCode(Id id) const { return module.getInstruction(id)->getOpCode(); } + Op getTypeClass(Id typeId) const { return getOpCode(typeId); } + Op getMostBasicTypeClass(Id typeId) const; + int getNumComponents(Id resultId) const { return getNumTypeComponents(getTypeId(resultId)); } + int getNumTypeConstituents(Id typeId) const; + int getNumTypeComponents(Id typeId) const { return getNumTypeConstituents(typeId); } + Id getScalarTypeId(Id typeId) const; + Id getContainedTypeId(Id typeId) const; + Id getContainedTypeId(Id typeId, int) const; + StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); } + ImageFormat getImageTypeFormat(Id typeId) const + { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); } + + bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); } + bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); } + bool isVector(Id resultId) const { return isVectorType(getTypeId(resultId)); } + bool isMatrix(Id resultId) const { return isMatrixType(getTypeId(resultId)); } + bool isCooperativeMatrix(Id resultId)const { return isCooperativeMatrixType(getTypeId(resultId)); } + bool isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); } + bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); } + + bool isBoolType(Id typeId) + { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); } + bool isIntType(Id typeId) const + { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; } + bool isUintType(Id typeId) const + { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; } + bool isFloatType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat; } + bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; } + bool isScalarType(Id typeId) const + { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt || + getTypeClass(typeId) == OpTypeBool; } + bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; } + bool isMatrixType(Id typeId) const { return getTypeClass(typeId) == OpTypeMatrix; } + bool isStructType(Id typeId) const { return getTypeClass(typeId) == OpTypeStruct; } + bool isArrayType(Id typeId) const { return getTypeClass(typeId) == OpTypeArray; } +#ifdef GLSLANG_WEB + bool isCooperativeMatrixType(Id typeId)const { return false; } +#else + bool isCooperativeMatrixType(Id typeId)const { return getTypeClass(typeId) == OpTypeCooperativeMatrixNV; } +#endif + bool isAggregateType(Id typeId) const + { return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); } + bool isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; } + bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; } + bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; } + bool containsType(Id typeId, Op typeOp, unsigned int width) const; + bool containsPhysicalStorageBufferOrArray(Id typeId) const; + + bool isConstantOpCode(Op opcode) const; + bool isSpecConstantOpCode(Op opcode) const; + bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); } + bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; } + bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); } + unsigned int getConstantScalar(Id resultId) const + { return module.getInstruction(resultId)->getImmediateOperand(0); } + StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); } + + int getScalarTypeWidth(Id typeId) const + { + Id scalarTypeId = getScalarTypeId(typeId); + assert(getTypeClass(scalarTypeId) == OpTypeInt || getTypeClass(scalarTypeId) == OpTypeFloat); + return module.getInstruction(scalarTypeId)->getImmediateOperand(0); + } + + int getTypeNumColumns(Id typeId) const + { + assert(isMatrixType(typeId)); + return getNumTypeConstituents(typeId); + } + int getNumColumns(Id resultId) const { return getTypeNumColumns(getTypeId(resultId)); } + int getTypeNumRows(Id typeId) const + { + assert(isMatrixType(typeId)); + return getNumTypeComponents(getContainedTypeId(typeId)); + } + int getNumRows(Id resultId) const { return getTypeNumRows(getTypeId(resultId)); } + + Dim getTypeDimensionality(Id typeId) const + { + assert(isImageType(typeId)); + return (Dim)module.getInstruction(typeId)->getImmediateOperand(1); + } + Id getImageType(Id resultId) const + { + Id typeId = getTypeId(resultId); + assert(isImageType(typeId) || isSampledImageType(typeId)); + return isSampledImageType(typeId) ? module.getInstruction(typeId)->getIdOperand(0) : typeId; + } + bool isArrayedImageType(Id typeId) const + { + assert(isImageType(typeId)); + return module.getInstruction(typeId)->getImmediateOperand(3) != 0; + } + + // For making new constants (will return old constant if the requested one was already made). + Id makeBoolConstant(bool b, bool specConstant = false); + Id makeInt8Constant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); } + Id makeUint8Constant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(8), u, specConstant); } + Id makeInt16Constant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(16), (unsigned)i, specConstant); } + Id makeUint16Constant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(16), u, specConstant); } + Id makeIntConstant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); } + Id makeUintConstant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(32), u, specConstant); } + Id makeInt64Constant(long long i, bool specConstant = false) + { return makeInt64Constant(makeIntType(64), (unsigned long long)i, specConstant); } + Id makeUint64Constant(unsigned long long u, bool specConstant = false) + { return makeInt64Constant(makeUintType(64), u, specConstant); } + Id makeFloatConstant(float f, bool specConstant = false); + Id makeDoubleConstant(double d, bool specConstant = false); + Id makeFloat16Constant(float f16, bool specConstant = false); + Id makeFpConstant(Id type, double d, bool specConstant = false); + + // Turn the array of constants into a proper spv constant of the requested type. + Id makeCompositeConstant(Id type, const std::vector& comps, bool specConst = false); + + // Methods for adding information outside the CFG. + Instruction* addEntryPoint(ExecutionModel, Function*, const char* name); + void addExecutionMode(Function*, ExecutionMode mode, int value1 = -1, int value2 = -1, int value3 = -1); + void addName(Id, const char* name); + void addMemberName(Id, int member, const char* name); + void addDecoration(Id, Decoration, int num = -1); + void addDecoration(Id, Decoration, const char*); + void addDecorationId(Id id, Decoration, Id idDecoration); + void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1); + void addMemberDecoration(Id, unsigned int member, Decoration, const char*); + + // At the end of what block do the next create*() instructions go? + void setBuildPoint(Block* bp) { buildPoint = bp; } + Block* getBuildPoint() const { return buildPoint; } + + // Make the entry-point function. The returned pointer is only valid + // for the lifetime of this builder. + Function* makeEntryPoint(const char*); + + // Make a shader-style function, and create its entry block if entry is non-zero. + // Return the function, pass back the entry. + // The returned pointer is only valid for the lifetime of this builder. + Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, + const std::vector& paramTypes, const std::vector>& precisions, Block **entry = 0); + + // Create a return. An 'implicit' return is one not appearing in the source + // code. In the case of an implicit return, no post-return block is inserted. + void makeReturn(bool implicit, Id retVal = 0); + + // Generate all the code needed to finish up a function. + void leaveFunction(); + + // Create a discard. + void makeDiscard(); + + // Create a global or function local or IO variable. + Id createVariable(StorageClass, Id type, const char* name = 0, Id initializer = NoResult); + + // Create an intermediate with an undefined value. + Id createUndefined(Id type); + + // Store into an Id and return the l-value + void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + + // Load from an Id and return it + Id createLoad(Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + + // Create an OpAccessChain instruction + Id createAccessChain(StorageClass, Id base, const std::vector& offsets); + + // Create an OpArrayLength instruction + Id createArrayLength(Id base, unsigned int member); + + // Create an OpCooperativeMatrixLengthNV instruction + Id createCooperativeMatrixLength(Id type); + + // Create an OpCompositeExtract instruction + Id createCompositeExtract(Id composite, Id typeId, unsigned index); + Id createCompositeExtract(Id composite, Id typeId, const std::vector& indexes); + Id createCompositeInsert(Id object, Id composite, Id typeId, unsigned index); + Id createCompositeInsert(Id object, Id composite, Id typeId, const std::vector& indexes); + + Id createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex); + Id createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex); + + void createNoResultOp(Op); + void createNoResultOp(Op, Id operand); + void createNoResultOp(Op, const std::vector& operands); + void createNoResultOp(Op, const std::vector& operands); + void createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask); + void createMemoryBarrier(unsigned executionScope, unsigned memorySemantics); + Id createUnaryOp(Op, Id typeId, Id operand); + Id createBinOp(Op, Id typeId, Id operand1, Id operand2); + Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3); + Id createOp(Op, Id typeId, const std::vector& operands); + Id createOp(Op, Id typeId, const std::vector& operands); + Id createFunctionCall(spv::Function*, const std::vector&); + Id createSpecConstantOp(Op, Id typeId, const std::vector& operands, const std::vector& literals); + + // Take an rvalue (source) and a set of channels to extract from it to + // make a new rvalue, which is returned. + Id createRvalueSwizzle(Decoration precision, Id typeId, Id source, const std::vector& channels); + + // Take a copy of an lvalue (target) and a source of components, and set the + // source components into the lvalue where the 'channels' say to put them. + // An updated version of the target is returned. + // (No true lvalue or stores are used.) + Id createLvalueSwizzle(Id typeId, Id target, Id source, const std::vector& channels); + + // If both the id and precision are valid, the id + // gets tagged with the requested precision. + // The passed in id is always the returned id, to simplify use patterns. + Id setPrecision(Id id, Decoration precision) + { + if (precision != NoPrecision && id != NoResult) + addDecoration(id, precision); + + return id; + } + + // Can smear a scalar to a vector for the following forms: + // - promoteScalar(scalar, vector) // smear scalar to width of vector + // - promoteScalar(vector, scalar) // smear scalar to width of vector + // - promoteScalar(pointer, scalar) // smear scalar to width of what pointer points to + // - promoteScalar(scalar, scalar) // do nothing + // Other forms are not allowed. + // + // Generally, the type of 'scalar' does not need to be the same type as the components in 'vector'. + // The type of the created vector is a vector of components of the same type as the scalar. + // + // Note: One of the arguments will change, with the result coming back that way rather than + // through the return value. + void promoteScalar(Decoration precision, Id& left, Id& right); + + // Make a value by smearing the scalar to fill the type. + // vectorType should be the correct type for making a vector of scalarVal. + // (No conversions are done.) + Id smearScalar(Decoration precision, Id scalarVal, Id vectorType); + + // Create a call to a built-in function. + Id createBuiltinCall(Id resultType, Id builtins, int entryPoint, const std::vector& args); + + // List of parameters used to create a texture operation + struct TextureParameters { + Id sampler; + Id coords; + Id bias; + Id lod; + Id Dref; + Id offset; + Id offsets; + Id gradX; + Id gradY; + Id sample; + Id component; + Id texelOut; + Id lodClamp; + Id granularity; + Id coarse; + bool nonprivate; + bool volatil; + }; + + // Select the correct texture operation based on all inputs, and emit the correct instruction + Id createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, + bool noImplicit, const TextureParameters&, ImageOperandsMask); + + // Emit the OpTextureQuery* instruction that was passed in. + // Figure out the right return value and type, and return it. + Id createTextureQueryCall(Op, const TextureParameters&, bool isUnsignedResult); + + Id createSamplePositionCall(Decoration precision, Id, Id); + + Id createBitFieldExtractCall(Decoration precision, Id, Id, Id, bool isSigned); + Id createBitFieldInsertCall(Decoration precision, Id, Id, Id, Id); + + // Reduction comparison for composites: For equal and not-equal resulting in a scalar. + Id createCompositeCompare(Decoration precision, Id, Id, bool /* true if for equal, false if for not-equal */); + + // OpCompositeConstruct + Id createCompositeConstruct(Id typeId, const std::vector& constituents); + + // vector or scalar constructor + Id createConstructor(Decoration precision, const std::vector& sources, Id resultTypeId); + + // matrix constructor + Id createMatrixConstructor(Decoration precision, const std::vector& sources, Id constructee); + + // Helper to use for building nested control flow with if-then-else. + class If { + public: + If(Id condition, unsigned int ctrl, Builder& builder); + ~If() {} + + void makeBeginElse(); + void makeEndIf(); + + private: + If(const If&); + If& operator=(If&); + + Builder& builder; + Id condition; + unsigned int control; + Function* function; + Block* headerBlock; + Block* thenBlock; + Block* elseBlock; + Block* mergeBlock; + }; + + // Make a switch statement. A switch has 'numSegments' of pieces of code, not containing + // any case/default labels, all separated by one or more case/default labels. Each possible + // case value v is a jump to the caseValues[v] segment. The defaultSegment is also in this + // number space. How to compute the value is given by 'condition', as in switch(condition). + // + // The SPIR-V Builder will maintain the stack of post-switch merge blocks for nested switches. + // + // Use a defaultSegment < 0 if there is no default segment (to branch to post switch). + // + // Returns the right set of basic blocks to start each code segment with, so that the caller's + // recursion stack can hold the memory for it. + // + void makeSwitch(Id condition, unsigned int control, int numSegments, const std::vector& caseValues, + const std::vector& valueToSegment, int defaultSegment, std::vector& segmentBB); + + // Add a branch to the innermost switch's merge block. + void addSwitchBreak(); + + // Move to the next code segment, passing in the return argument in makeSwitch() + void nextSwitchSegment(std::vector& segmentBB, int segment); + + // Finish off the innermost switch. + void endSwitch(std::vector& segmentBB); + + struct LoopBlocks { + LoopBlocks(Block& head, Block& body, Block& merge, Block& continue_target) : + head(head), body(body), merge(merge), continue_target(continue_target) { } + Block &head, &body, &merge, &continue_target; + private: + LoopBlocks(); + LoopBlocks& operator=(const LoopBlocks&) = delete; + }; + + // Start a new loop and prepare the builder to generate code for it. Until + // closeLoop() is called for this loop, createLoopContinue() and + // createLoopExit() will target its corresponding blocks. + LoopBlocks& makeNewLoop(); + + // Create a new block in the function containing the build point. Memory is + // owned by the function object. + Block& makeNewBlock(); + + // Add a branch to the continue_target of the current (innermost) loop. + void createLoopContinue(); + + // Add an exit (e.g. "break") from the innermost loop that we're currently + // in. + void createLoopExit(); + + // Close the innermost loop that you're in + void closeLoop(); + + // + // Access chain design for an R-Value vs. L-Value: + // + // There is a single access chain the builder is building at + // any particular time. Such a chain can be used to either to a load or + // a store, when desired. + // + // Expressions can be r-values, l-values, or both, or only r-values: + // a[b.c].d = .... // l-value + // ... = a[b.c].d; // r-value, that also looks like an l-value + // ++a[b.c].d; // r-value and l-value + // (x + y)[2]; // r-value only, can't possibly be l-value + // + // Computing an r-value means generating code. Hence, + // r-values should only be computed when they are needed, not speculatively. + // + // Computing an l-value means saving away information for later use in the compiler, + // no code is generated until the l-value is later dereferenced. It is okay + // to speculatively generate an l-value, just not okay to speculatively dereference it. + // + // The base of the access chain (the left-most variable or expression + // from which everything is based) can be set either as an l-value + // or as an r-value. Most efficient would be to set an l-value if one + // is available. If an expression was evaluated, the resulting r-value + // can be set as the chain base. + // + // The users of this single access chain can save and restore if they + // want to nest or manage multiple chains. + // + + struct AccessChain { + Id base; // for l-values, pointer to the base object, for r-values, the base object + std::vector indexChain; + Id instr; // cache the instruction that generates this access chain + std::vector swizzle; // each std::vector element selects the next GLSL component number + Id component; // a dynamic component index, can coexist with a swizzle, + // done after the swizzle, NoResult if not present + Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied; + // NoType unless a swizzle or component is present + bool isRValue; // true if 'base' is an r-value, otherwise, base is an l-value + unsigned int alignment; // bitwise OR of alignment values passed in. Accumulates worst alignment. + // Only tracks base and (optional) component selection alignment. + + // Accumulate whether anything in the chain of structures has coherent decorations. + struct CoherentFlags { + CoherentFlags() { clear(); } +#ifdef GLSLANG_WEB + void clear() { } + bool isVolatile() const { return false; } + CoherentFlags operator |=(const CoherentFlags &other) { return *this; } +#else + bool isVolatile() const { return volatil; } + bool anyCoherent() const { + return coherent || devicecoherent || queuefamilycoherent || workgroupcoherent || + subgroupcoherent || shadercallcoherent; + } + + unsigned coherent : 1; + unsigned devicecoherent : 1; + unsigned queuefamilycoherent : 1; + unsigned workgroupcoherent : 1; + unsigned subgroupcoherent : 1; + unsigned shadercallcoherent : 1; + unsigned nonprivate : 1; + unsigned volatil : 1; + unsigned isImage : 1; + + void clear() { + coherent = 0; + devicecoherent = 0; + queuefamilycoherent = 0; + workgroupcoherent = 0; + subgroupcoherent = 0; + shadercallcoherent = 0; + nonprivate = 0; + volatil = 0; + isImage = 0; + } + + CoherentFlags operator |=(const CoherentFlags &other) { + coherent |= other.coherent; + devicecoherent |= other.devicecoherent; + queuefamilycoherent |= other.queuefamilycoherent; + workgroupcoherent |= other.workgroupcoherent; + subgroupcoherent |= other.subgroupcoherent; + shadercallcoherent |= other.shadercallcoherent; + nonprivate |= other.nonprivate; + volatil |= other.volatil; + isImage |= other.isImage; + return *this; + } +#endif + }; + CoherentFlags coherentFlags; + }; + + // + // the SPIR-V builder maintains a single active chain that + // the following methods operate on + // + + // for external save and restore + AccessChain getAccessChain() { return accessChain; } + void setAccessChain(AccessChain newChain) { accessChain = newChain; } + + // clear accessChain + void clearAccessChain(); + + // set new base as an l-value base + void setAccessChainLValue(Id lValue) + { + assert(isPointer(lValue)); + accessChain.base = lValue; + } + + // set new base value as an r-value + void setAccessChainRValue(Id rValue) + { + accessChain.isRValue = true; + accessChain.base = rValue; + } + + // push offset onto the end of the chain + void accessChainPush(Id offset, AccessChain::CoherentFlags coherentFlags, unsigned int alignment) + { + accessChain.indexChain.push_back(offset); + accessChain.coherentFlags |= coherentFlags; + accessChain.alignment |= alignment; + } + + // push new swizzle onto the end of any existing swizzle, merging into a single swizzle + void accessChainPushSwizzle(std::vector& swizzle, Id preSwizzleBaseType, + AccessChain::CoherentFlags coherentFlags, unsigned int alignment); + + // push a dynamic component selection onto the access chain, only applicable with a + // non-trivial swizzle or no swizzle + void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, + unsigned int alignment) + { + if (accessChain.swizzle.size() != 1) { + accessChain.component = component; + if (accessChain.preSwizzleBaseType == NoType) + accessChain.preSwizzleBaseType = preSwizzleBaseType; + } + accessChain.coherentFlags |= coherentFlags; + accessChain.alignment |= alignment; + } + + // use accessChain and swizzle to store value + void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + + // use accessChain and swizzle to load an r-value + Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType, + spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, + unsigned int alignment = 0); + + // Return whether or not the access chain can be represented in SPIR-V + // as an l-value. + // E.g., a[3].yx cannot be, while a[3].y and a[3].y[x] can be. + bool isSpvLvalue() const { return accessChain.swizzle.size() <= 1; } + + // get the direct pointer for an l-value + Id accessChainGetLValue(); + + // Get the inferred SPIR-V type of the result of the current access chain, + // based on the type of the base and the chain of dereferences. + Id accessChainGetInferredType(); + + // Add capabilities, extensions, remove unneeded decorations, etc., + // based on the resulting SPIR-V. + void postProcess(); + + // Prune unreachable blocks in the CFG and remove unneeded decorations. + void postProcessCFG(); + +#ifndef GLSLANG_WEB + // Add capabilities, extensions based on instructions in the module. + void postProcessFeatures(); + // Hook to visit each instruction in a block in a function + void postProcess(Instruction&); + // Hook to visit each non-32-bit sized float/int operation in a block. + void postProcessType(const Instruction&, spv::Id typeId); +#endif + + void dump(std::vector&) const; + + void createBranch(Block* block); + void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock); + void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, + const std::vector& operands); + + // Sets to generate opcode for specialization constants. + void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; } + // Sets to generate opcode for non-specialization constants (normal mode). + void setToNormalCodeGenMode() { generatingOpCodeForSpecConst = false; } + // Check if the builder is generating code for spec constants. + bool isInSpecConstCodeGenMode() { return generatingOpCodeForSpecConst; } + + protected: + Id makeIntConstant(Id typeId, unsigned value, bool specConstant); + Id makeInt64Constant(Id typeId, unsigned long long value, bool specConstant); + Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value); + Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2); + Id findCompositeConstant(Op typeClass, Id typeId, const std::vector& comps); + Id findStructConstant(Id typeId, const std::vector& comps); + Id collapseAccessChain(); + void remapDynamicSwizzle(); + void transferAccessChainSwizzle(bool dynamic); + void simplifyAccessChainSwizzle(); + void createAndSetNoPredecessorBlock(const char*); + void createSelectionMerge(Block* mergeBlock, unsigned int control); + void dumpSourceInstructions(std::vector&) const; + void dumpSourceInstructions(const spv::Id fileId, const std::string& text, std::vector&) const; + void dumpInstructions(std::vector&, const std::vector >&) const; + void dumpModuleProcesses(std::vector&) const; + spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) + const; + + unsigned int spvVersion; // the version of SPIR-V to emit in the header + SourceLanguage source; + int sourceVersion; + spv::Id sourceFileStringId; + std::string sourceText; + int currentLine; + const char* currentFile; + bool emitOpLines; + std::set extensions; + std::vector sourceExtensions; + std::vector moduleProcesses; + AddressingModel addressModel; + MemoryModel memoryModel; + std::set capabilities; + int builderNumber; + Module module; + Block* buildPoint; + Id uniqueId; + Function* entryPointFunction; + bool generatingOpCodeForSpecConst; + AccessChain accessChain; + + // special blocks of instructions for output + std::vector > strings; + std::vector > imports; + std::vector > entryPoints; + std::vector > executionModes; + std::vector > names; + std::vector > decorations; + std::vector > constantsTypesGlobals; + std::vector > externals; + std::vector > functions; + + // not output, internally used for quick & dirty canonical (unique) creation + + // map type opcodes to constant inst. + std::unordered_map> groupedConstants; + // map struct-id to constant instructions + std::unordered_map> groupedStructConstants; + // map type opcodes to type instructions + std::unordered_map> groupedTypes; + + // stack of switches + std::stack switchMerges; + + // Our loop stack. + std::stack loops; + + // map from strings to their string ids + std::unordered_map stringIds; + + // map from include file name ids to their contents + std::map includeFiles; + + // The stream for outputting warnings and errors. + SpvBuildLogger* logger; +}; // end Builder class + +}; // end spv namespace + +#endif // SpvBuilder_H diff --git a/android/x86/include/glslang/SPIRV/SpvTools.h b/android/x86/include/glslang/SPIRV/SpvTools.h new file mode 100644 index 00000000..59c914da --- /dev/null +++ b/android/x86/include/glslang/SPIRV/SpvTools.h @@ -0,0 +1,82 @@ +// +// Copyright (C) 2014-2016 LunarG, Inc. +// Copyright (C) 2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Call into SPIRV-Tools to disassemble, validate, and optimize. +// + +#pragma once +#ifndef GLSLANG_SPV_TOOLS_H +#define GLSLANG_SPV_TOOLS_H + +#ifdef ENABLE_OPT +#include +#include +#endif + +#include "glslang/MachineIndependent/localintermediate.h" +#include "Logger.h" + +namespace glslang { + +struct SpvOptions { + SpvOptions() : generateDebugInfo(false), disableOptimizer(true), + optimizeSize(false), disassemble(false), validate(false) { } + bool generateDebugInfo; + bool disableOptimizer; + bool optimizeSize; + bool disassemble; + bool validate; +}; + +#ifdef ENABLE_OPT + +// Use the SPIRV-Tools disassembler to print SPIR-V. +void SpirvToolsDisassemble(std::ostream& out, const std::vector& spirv); + +// Apply the SPIRV-Tools validator to generated SPIR-V. +void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger*, bool prelegalization); + +// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of +// legalizing HLSL SPIR-V. +void SpirvToolsLegalize(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger*, const SpvOptions*); + +#endif + +} // end namespace glslang + +#endif // GLSLANG_SPV_TOOLS_H diff --git a/android/x86/include/glslang/SPIRV/bitutils.h b/android/x86/include/glslang/SPIRV/bitutils.h new file mode 100644 index 00000000..22e44cec --- /dev/null +++ b/android/x86/include/glslang/SPIRV/bitutils.h @@ -0,0 +1,81 @@ +// Copyright (c) 2015-2016 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef LIBSPIRV_UTIL_BITUTILS_H_ +#define LIBSPIRV_UTIL_BITUTILS_H_ + +#include +#include + +namespace spvutils { + +// Performs a bitwise copy of source to the destination type Dest. +template +Dest BitwiseCast(Src source) { + Dest dest; + static_assert(sizeof(source) == sizeof(dest), + "BitwiseCast: Source and destination must have the same size"); + std::memcpy(static_cast(&dest), &source, sizeof(dest)); + return dest; +} + +// SetBits returns an integer of type with bits set +// for position through , counting from the least +// significant bit. In particular when Num == 0, no positions are set to 1. +// A static assert will be triggered if First + Num > sizeof(T) * 8, that is, +// a bit that will not fit in the underlying type is set. +template +struct SetBits { + static_assert(First < sizeof(T) * 8, + "Tried to set a bit that is shifted too far."); + const static T get = (T(1) << First) | SetBits::get; +}; + +template +struct SetBits { + const static T get = T(0); +}; + +// This is all compile-time so we can put our tests right here. +static_assert(SetBits::get == uint32_t(0x00000000), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x00000001), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x80000000), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x00000006), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0xc0000000), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x7FFFFFFF), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0xFFFFFFFF), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0xFFFF0000), + "SetBits failed"); + +static_assert(SetBits::get == uint64_t(0x0000000000000001LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0x8000000000000000LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0xc000000000000000LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0x0000000080000000LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0x00000000FFFF0000LL), + "SetBits failed"); + +} // namespace spvutils + +#endif // LIBSPIRV_UTIL_BITUTILS_H_ diff --git a/android/x86/include/glslang/SPIRV/disassemble.h b/android/x86/include/glslang/SPIRV/disassemble.h new file mode 100644 index 00000000..b6a46357 --- /dev/null +++ b/android/x86/include/glslang/SPIRV/disassemble.h @@ -0,0 +1,53 @@ +// +// Copyright (C) 2014-2015 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Disassembler for SPIR-V. +// + +#pragma once +#ifndef disassembler_H +#define disassembler_H + +#include +#include + +namespace spv { + + // disassemble with glslang custom disassembler + void Disassemble(std::ostream& out, const std::vector&); + +} // end namespace spv + +#endif // disassembler_H diff --git a/android/x86/include/glslang/SPIRV/doc.h b/android/x86/include/glslang/SPIRV/doc.h new file mode 100644 index 00000000..293256a2 --- /dev/null +++ b/android/x86/include/glslang/SPIRV/doc.h @@ -0,0 +1,258 @@ +// +// Copyright (C) 2014-2015 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Parameterize the SPIR-V enumerants. +// + +#pragma once + +#include "spirv.hpp" + +#include + +namespace spv { + +// Fill in all the parameters +void Parameterize(); + +// Return the English names of all the enums. +const char* SourceString(int); +const char* AddressingString(int); +const char* MemoryString(int); +const char* ExecutionModelString(int); +const char* ExecutionModeString(int); +const char* StorageClassString(int); +const char* DecorationString(int); +const char* BuiltInString(int); +const char* DimensionString(int); +const char* SelectControlString(int); +const char* LoopControlString(int); +const char* FunctionControlString(int); +const char* SamplerAddressingModeString(int); +const char* SamplerFilterModeString(int); +const char* ImageFormatString(int); +const char* ImageChannelOrderString(int); +const char* ImageChannelTypeString(int); +const char* ImageChannelDataTypeString(int type); +const char* ImageOperandsString(int format); +const char* ImageOperands(int); +const char* FPFastMathString(int); +const char* FPRoundingModeString(int); +const char* LinkageTypeString(int); +const char* FuncParamAttrString(int); +const char* AccessQualifierString(int); +const char* MemorySemanticsString(int); +const char* MemoryAccessString(int); +const char* ExecutionScopeString(int); +const char* GroupOperationString(int); +const char* KernelEnqueueFlagsString(int); +const char* KernelProfilingInfoString(int); +const char* CapabilityString(int); +const char* OpcodeString(int); +const char* ScopeString(int mem); + +// For grouping opcodes into subsections +enum OpcodeClass { + OpClassMisc, + OpClassDebug, + OpClassAnnotate, + OpClassExtension, + OpClassMode, + OpClassType, + OpClassConstant, + OpClassMemory, + OpClassFunction, + OpClassImage, + OpClassConvert, + OpClassComposite, + OpClassArithmetic, + OpClassBit, + OpClassRelationalLogical, + OpClassDerivative, + OpClassFlowControl, + OpClassAtomic, + OpClassPrimitive, + OpClassBarrier, + OpClassGroup, + OpClassDeviceSideEnqueue, + OpClassPipe, + + OpClassCount, + OpClassMissing // all instructions start out as missing +}; + +// For parameterizing operands. +enum OperandClass { + OperandNone, + OperandId, + OperandVariableIds, + OperandOptionalLiteral, + OperandOptionalLiteralString, + OperandVariableLiterals, + OperandVariableIdLiteral, + OperandVariableLiteralId, + OperandLiteralNumber, + OperandLiteralString, + OperandSource, + OperandExecutionModel, + OperandAddressing, + OperandMemory, + OperandExecutionMode, + OperandStorage, + OperandDimensionality, + OperandSamplerAddressingMode, + OperandSamplerFilterMode, + OperandSamplerImageFormat, + OperandImageChannelOrder, + OperandImageChannelDataType, + OperandImageOperands, + OperandFPFastMath, + OperandFPRoundingMode, + OperandLinkageType, + OperandAccessQualifier, + OperandFuncParamAttr, + OperandDecoration, + OperandBuiltIn, + OperandSelect, + OperandLoop, + OperandFunction, + OperandMemorySemantics, + OperandMemoryAccess, + OperandScope, + OperandGroupOperation, + OperandKernelEnqueueFlags, + OperandKernelProfilingInfo, + OperandCapability, + + OperandOpcode, + + OperandCount +}; + +// Any specific enum can have a set of capabilities that allow it: +typedef std::vector EnumCaps; + +// Parameterize a set of operands with their OperandClass(es) and descriptions. +class OperandParameters { +public: + OperandParameters() { } + void push(OperandClass oc, const char* d, bool opt = false) + { + opClass.push_back(oc); + desc.push_back(d); + optional.push_back(opt); + } + void setOptional(); + OperandClass getClass(int op) const { return opClass[op]; } + const char* getDesc(int op) const { return desc[op]; } + bool isOptional(int op) const { return optional[op]; } + int getNum() const { return (int)opClass.size(); } + +protected: + std::vector opClass; + std::vector desc; + std::vector optional; +}; + +// Parameterize an enumerant +class EnumParameters { +public: + EnumParameters() : desc(0) { } + const char* desc; +}; + +// Parameterize a set of enumerants that form an enum +class EnumDefinition : public EnumParameters { +public: + EnumDefinition() : + ceiling(0), bitmask(false), getName(0), enumParams(0), operandParams(0) { } + void set(int ceil, const char* (*name)(int), EnumParameters* ep, bool mask = false) + { + ceiling = ceil; + getName = name; + bitmask = mask; + enumParams = ep; + } + void setOperands(OperandParameters* op) { operandParams = op; } + int ceiling; // ceiling of enumerants + bool bitmask; // true if these enumerants combine into a bitmask + const char* (*getName)(int); // a function that returns the name for each enumerant value (or shift) + EnumParameters* enumParams; // parameters for each individual enumerant + OperandParameters* operandParams; // sets of operands +}; + +// Parameterize an instruction's logical format, including its known set of operands, +// per OperandParameters above. +class InstructionParameters { +public: + InstructionParameters() : + opDesc("TBD"), + opClass(OpClassMissing), + typePresent(true), // most normal, only exceptions have to be spelled out + resultPresent(true) // most normal, only exceptions have to be spelled out + { } + + void setResultAndType(bool r, bool t) + { + resultPresent = r; + typePresent = t; + } + + bool hasResult() const { return resultPresent != 0; } + bool hasType() const { return typePresent != 0; } + + const char* opDesc; + OpcodeClass opClass; + OperandParameters operands; + +protected: + int typePresent : 1; + int resultPresent : 1; +}; + +// The set of objects that hold all the instruction/operand +// parameterization information. +extern InstructionParameters InstructionDesc[]; + +// These hold definitions of the enumerants used for operands +extern EnumDefinition OperandClassParams[]; + +const char* GetOperandDesc(OperandClass operand); +void PrintImmediateRow(int imm, const char* name, const EnumParameters* enumParams, bool caps, bool hex = false); +const char* AccessQualifierString(int attr); + +void PrintOperands(const OperandParameters& operands, int reservedOperands); + +} // end namespace spv diff --git a/android/x86/include/glslang/SPIRV/hex_float.h b/android/x86/include/glslang/SPIRV/hex_float.h new file mode 100644 index 00000000..8be8e9f7 --- /dev/null +++ b/android/x86/include/glslang/SPIRV/hex_float.h @@ -0,0 +1,1078 @@ +// Copyright (c) 2015-2016 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef LIBSPIRV_UTIL_HEX_FLOAT_H_ +#define LIBSPIRV_UTIL_HEX_FLOAT_H_ + +#include +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) && _MSC_VER < 1800 +namespace std { +bool isnan(double f) +{ + return ::_isnan(f) != 0; +} +bool isinf(double f) +{ + return ::_finite(f) == 0; +} +} +#endif + +#include "bitutils.h" + +namespace spvutils { + +class Float16 { + public: + Float16(uint16_t v) : val(v) {} + Float16() {} + static bool isNan(const Float16& val) { + return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) != 0); + } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(const Float16& val) { + return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) == 0); + } + Float16(const Float16& other) { val = other.val; } + uint16_t get_value() const { return val; } + + // Returns the maximum normal value. + static Float16 max() { return Float16(0x7bff); } + // Returns the lowest normal value. + static Float16 lowest() { return Float16(0xfbff); } + + private: + uint16_t val; +}; + +// To specialize this type, you must override uint_type to define +// an unsigned integer that can fit your floating point type. +// You must also add a isNan function that returns true if +// a value is Nan. +template +struct FloatProxyTraits { + typedef void uint_type; +}; + +template <> +struct FloatProxyTraits { + typedef uint32_t uint_type; + static bool isNan(float f) { return std::isnan(f); } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(float f) { return std::isinf(f); } + // Returns the maximum normal value. + static float max() { return std::numeric_limits::max(); } + // Returns the lowest normal value. + static float lowest() { return std::numeric_limits::lowest(); } +}; + +template <> +struct FloatProxyTraits { + typedef uint64_t uint_type; + static bool isNan(double f) { return std::isnan(f); } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(double f) { return std::isinf(f); } + // Returns the maximum normal value. + static double max() { return std::numeric_limits::max(); } + // Returns the lowest normal value. + static double lowest() { return std::numeric_limits::lowest(); } +}; + +template <> +struct FloatProxyTraits { + typedef uint16_t uint_type; + static bool isNan(Float16 f) { return Float16::isNan(f); } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(Float16 f) { return Float16::isInfinity(f); } + // Returns the maximum normal value. + static Float16 max() { return Float16::max(); } + // Returns the lowest normal value. + static Float16 lowest() { return Float16::lowest(); } +}; + +// Since copying a floating point number (especially if it is NaN) +// does not guarantee that bits are preserved, this class lets us +// store the type and use it as a float when necessary. +template +class FloatProxy { + public: + typedef typename FloatProxyTraits::uint_type uint_type; + + // Since this is to act similar to the normal floats, + // do not initialize the data by default. + FloatProxy() {} + + // Intentionally non-explicit. This is a proxy type so + // implicit conversions allow us to use it more transparently. + FloatProxy(T val) { data_ = BitwiseCast(val); } + + // Intentionally non-explicit. This is a proxy type so + // implicit conversions allow us to use it more transparently. + FloatProxy(uint_type val) { data_ = val; } + + // This is helpful to have and is guaranteed not to stomp bits. + FloatProxy operator-() const { + return static_cast(data_ ^ + (uint_type(0x1) << (sizeof(T) * 8 - 1))); + } + + // Returns the data as a floating point value. + T getAsFloat() const { return BitwiseCast(data_); } + + // Returns the raw data. + uint_type data() const { return data_; } + + // Returns true if the value represents any type of NaN. + bool isNan() { return FloatProxyTraits::isNan(getAsFloat()); } + // Returns true if the value represents any type of infinity. + bool isInfinity() { return FloatProxyTraits::isInfinity(getAsFloat()); } + + // Returns the maximum normal value. + static FloatProxy max() { + return FloatProxy(FloatProxyTraits::max()); + } + // Returns the lowest normal value. + static FloatProxy lowest() { + return FloatProxy(FloatProxyTraits::lowest()); + } + + private: + uint_type data_; +}; + +template +bool operator==(const FloatProxy& first, const FloatProxy& second) { + return first.data() == second.data(); +} + +// Reads a FloatProxy value as a normal float from a stream. +template +std::istream& operator>>(std::istream& is, FloatProxy& value) { + T float_val; + is >> float_val; + value = FloatProxy(float_val); + return is; +} + +// This is an example traits. It is not meant to be used in practice, but will +// be the default for any non-specialized type. +template +struct HexFloatTraits { + // Integer type that can store this hex-float. + typedef void uint_type; + // Signed integer type that can store this hex-float. + typedef void int_type; + // The numerical type that this HexFloat represents. + typedef void underlying_type; + // The type needed to construct the underlying type. + typedef void native_type; + // The number of bits that are actually relevant in the uint_type. + // This allows us to deal with, for example, 24-bit values in a 32-bit + // integer. + static const uint32_t num_used_bits = 0; + // Number of bits that represent the exponent. + static const uint32_t num_exponent_bits = 0; + // Number of bits that represent the fractional part. + static const uint32_t num_fraction_bits = 0; + // The bias of the exponent. (How much we need to subtract from the stored + // value to get the correct value.) + static const uint32_t exponent_bias = 0; +}; + +// Traits for IEEE float. +// 1 sign bit, 8 exponent bits, 23 fractional bits. +template <> +struct HexFloatTraits> { + typedef uint32_t uint_type; + typedef int32_t int_type; + typedef FloatProxy underlying_type; + typedef float native_type; + static const uint_type num_used_bits = 32; + static const uint_type num_exponent_bits = 8; + static const uint_type num_fraction_bits = 23; + static const uint_type exponent_bias = 127; +}; + +// Traits for IEEE double. +// 1 sign bit, 11 exponent bits, 52 fractional bits. +template <> +struct HexFloatTraits> { + typedef uint64_t uint_type; + typedef int64_t int_type; + typedef FloatProxy underlying_type; + typedef double native_type; + static const uint_type num_used_bits = 64; + static const uint_type num_exponent_bits = 11; + static const uint_type num_fraction_bits = 52; + static const uint_type exponent_bias = 1023; +}; + +// Traits for IEEE half. +// 1 sign bit, 5 exponent bits, 10 fractional bits. +template <> +struct HexFloatTraits> { + typedef uint16_t uint_type; + typedef int16_t int_type; + typedef uint16_t underlying_type; + typedef uint16_t native_type; + static const uint_type num_used_bits = 16; + static const uint_type num_exponent_bits = 5; + static const uint_type num_fraction_bits = 10; + static const uint_type exponent_bias = 15; +}; + +enum round_direction { + kRoundToZero, + kRoundToNearestEven, + kRoundToPositiveInfinity, + kRoundToNegativeInfinity +}; + +// Template class that houses a floating pointer number. +// It exposes a number of constants based on the provided traits to +// assist in interpreting the bits of the value. +template > +class HexFloat { + public: + typedef typename Traits::uint_type uint_type; + typedef typename Traits::int_type int_type; + typedef typename Traits::underlying_type underlying_type; + typedef typename Traits::native_type native_type; + + explicit HexFloat(T f) : value_(f) {} + + T value() const { return value_; } + void set_value(T f) { value_ = f; } + + // These are all written like this because it is convenient to have + // compile-time constants for all of these values. + + // Pass-through values to save typing. + static const uint32_t num_used_bits = Traits::num_used_bits; + static const uint32_t exponent_bias = Traits::exponent_bias; + static const uint32_t num_exponent_bits = Traits::num_exponent_bits; + static const uint32_t num_fraction_bits = Traits::num_fraction_bits; + + // Number of bits to shift left to set the highest relevant bit. + static const uint32_t top_bit_left_shift = num_used_bits - 1; + // How many nibbles (hex characters) the fractional part takes up. + static const uint32_t fraction_nibbles = (num_fraction_bits + 3) / 4; + // If the fractional part does not fit evenly into a hex character (4-bits) + // then we have to left-shift to get rid of leading 0s. This is the amount + // we have to shift (might be 0). + static const uint32_t num_overflow_bits = + fraction_nibbles * 4 - num_fraction_bits; + + // The representation of the fraction, not the actual bits. This + // includes the leading bit that is usually implicit. + static const uint_type fraction_represent_mask = + spvutils::SetBits::get; + + // The topmost bit in the nibble-aligned fraction. + static const uint_type fraction_top_bit = + uint_type(1) << (num_fraction_bits + num_overflow_bits - 1); + + // The least significant bit in the exponent, which is also the bit + // immediately to the left of the significand. + static const uint_type first_exponent_bit = uint_type(1) + << (num_fraction_bits); + + // The mask for the encoded fraction. It does not include the + // implicit bit. + static const uint_type fraction_encode_mask = + spvutils::SetBits::get; + + // The bit that is used as a sign. + static const uint_type sign_mask = uint_type(1) << top_bit_left_shift; + + // The bits that represent the exponent. + static const uint_type exponent_mask = + spvutils::SetBits::get; + + // How far left the exponent is shifted. + static const uint32_t exponent_left_shift = num_fraction_bits; + + // How far from the right edge the fraction is shifted. + static const uint32_t fraction_right_shift = + static_cast(sizeof(uint_type) * 8) - num_fraction_bits; + + // The maximum representable unbiased exponent. + static const int_type max_exponent = + (exponent_mask >> num_fraction_bits) - exponent_bias; + // The minimum representable exponent for normalized numbers. + static const int_type min_exponent = -static_cast(exponent_bias); + + // Returns the bits associated with the value. + uint_type getBits() const { return spvutils::BitwiseCast(value_); } + + // Returns the bits associated with the value, without the leading sign bit. + uint_type getUnsignedBits() const { + return static_cast(spvutils::BitwiseCast(value_) & + ~sign_mask); + } + + // Returns the bits associated with the exponent, shifted to start at the + // lsb of the type. + const uint_type getExponentBits() const { + return static_cast((getBits() & exponent_mask) >> + num_fraction_bits); + } + + // Returns the exponent in unbiased form. This is the exponent in the + // human-friendly form. + const int_type getUnbiasedExponent() const { + return static_cast(getExponentBits() - exponent_bias); + } + + // Returns just the significand bits from the value. + const uint_type getSignificandBits() const { + return getBits() & fraction_encode_mask; + } + + // If the number was normalized, returns the unbiased exponent. + // If the number was denormal, normalize the exponent first. + const int_type getUnbiasedNormalizedExponent() const { + if ((getBits() & ~sign_mask) == 0) { // special case if everything is 0 + return 0; + } + int_type exp = getUnbiasedExponent(); + if (exp == min_exponent) { // We are in denorm land. + uint_type significand_bits = getSignificandBits(); + while ((significand_bits & (first_exponent_bit >> 1)) == 0) { + significand_bits = static_cast(significand_bits << 1); + exp = static_cast(exp - 1); + } + significand_bits &= fraction_encode_mask; + } + return exp; + } + + // Returns the signficand after it has been normalized. + const uint_type getNormalizedSignificand() const { + int_type unbiased_exponent = getUnbiasedNormalizedExponent(); + uint_type significand = getSignificandBits(); + for (int_type i = unbiased_exponent; i <= min_exponent; ++i) { + significand = static_cast(significand << 1); + } + significand &= fraction_encode_mask; + return significand; + } + + // Returns true if this number represents a negative value. + bool isNegative() const { return (getBits() & sign_mask) != 0; } + + // Sets this HexFloat from the individual components. + // Note this assumes EVERY significand is normalized, and has an implicit + // leading one. This means that the only way that this method will set 0, + // is if you set a number so denormalized that it underflows. + // Do not use this method with raw bits extracted from a subnormal number, + // since subnormals do not have an implicit leading 1 in the significand. + // The significand is also expected to be in the + // lowest-most num_fraction_bits of the uint_type. + // The exponent is expected to be unbiased, meaning an exponent of + // 0 actually means 0. + // If underflow_round_up is set, then on underflow, if a number is non-0 + // and would underflow, we round up to the smallest denorm. + void setFromSignUnbiasedExponentAndNormalizedSignificand( + bool negative, int_type exponent, uint_type significand, + bool round_denorm_up) { + bool significand_is_zero = significand == 0; + + if (exponent <= min_exponent) { + // If this was denormalized, then we have to shift the bit on, meaning + // the significand is not zero. + significand_is_zero = false; + significand |= first_exponent_bit; + significand = static_cast(significand >> 1); + } + + while (exponent < min_exponent) { + significand = static_cast(significand >> 1); + ++exponent; + } + + if (exponent == min_exponent) { + if (significand == 0 && !significand_is_zero && round_denorm_up) { + significand = static_cast(0x1); + } + } + + uint_type new_value = 0; + if (negative) { + new_value = static_cast(new_value | sign_mask); + } + exponent = static_cast(exponent + exponent_bias); + assert(exponent >= 0); + + // put it all together + exponent = static_cast((exponent << exponent_left_shift) & + exponent_mask); + significand = static_cast(significand & fraction_encode_mask); + new_value = static_cast(new_value | (exponent | significand)); + value_ = BitwiseCast(new_value); + } + + // Increments the significand of this number by the given amount. + // If this would spill the significand into the implicit bit, + // carry is set to true and the significand is shifted to fit into + // the correct location, otherwise carry is set to false. + // All significands and to_increment are assumed to be within the bounds + // for a valid significand. + static uint_type incrementSignificand(uint_type significand, + uint_type to_increment, bool* carry) { + significand = static_cast(significand + to_increment); + *carry = false; + if (significand & first_exponent_bit) { + *carry = true; + // The implicit 1-bit will have carried, so we should zero-out the + // top bit and shift back. + significand = static_cast(significand & ~first_exponent_bit); + significand = static_cast(significand >> 1); + } + return significand; + } + + // These exist because MSVC throws warnings on negative right-shifts + // even if they are not going to be executed. Eg: + // constant_number < 0? 0: constant_number + // These convert the negative left-shifts into right shifts. + + template + uint_type negatable_left_shift(int_type N, uint_type val) + { + if(N >= 0) + return val << N; + + return val >> -N; + } + + template + uint_type negatable_right_shift(int_type N, uint_type val) + { + if(N >= 0) + return val >> N; + + return val << -N; + } + + // Returns the significand, rounded to fit in a significand in + // other_T. This is shifted so that the most significant + // bit of the rounded number lines up with the most significant bit + // of the returned significand. + template + typename other_T::uint_type getRoundedNormalizedSignificand( + round_direction dir, bool* carry_bit) { + typedef typename other_T::uint_type other_uint_type; + static const int_type num_throwaway_bits = + static_cast(num_fraction_bits) - + static_cast(other_T::num_fraction_bits); + + static const uint_type last_significant_bit = + (num_throwaway_bits < 0) + ? 0 + : negatable_left_shift(num_throwaway_bits, 1u); + static const uint_type first_rounded_bit = + (num_throwaway_bits < 1) + ? 0 + : negatable_left_shift(num_throwaway_bits - 1, 1u); + + static const uint_type throwaway_mask_bits = + num_throwaway_bits > 0 ? num_throwaway_bits : 0; + static const uint_type throwaway_mask = + spvutils::SetBits::get; + + *carry_bit = false; + other_uint_type out_val = 0; + uint_type significand = getNormalizedSignificand(); + // If we are up-casting, then we just have to shift to the right location. + if (num_throwaway_bits <= 0) { + out_val = static_cast(significand); + uint_type shift_amount = static_cast(-num_throwaway_bits); + out_val = static_cast(out_val << shift_amount); + return out_val; + } + + // If every non-representable bit is 0, then we don't have any casting to + // do. + if ((significand & throwaway_mask) == 0) { + return static_cast( + negatable_right_shift(num_throwaway_bits, significand)); + } + + bool round_away_from_zero = false; + // We actually have to narrow the significand here, so we have to follow the + // rounding rules. + switch (dir) { + case kRoundToZero: + break; + case kRoundToPositiveInfinity: + round_away_from_zero = !isNegative(); + break; + case kRoundToNegativeInfinity: + round_away_from_zero = isNegative(); + break; + case kRoundToNearestEven: + // Have to round down, round bit is 0 + if ((first_rounded_bit & significand) == 0) { + break; + } + if (((significand & throwaway_mask) & ~first_rounded_bit) != 0) { + // If any subsequent bit of the rounded portion is non-0 then we round + // up. + round_away_from_zero = true; + break; + } + // We are exactly half-way between 2 numbers, pick even. + if ((significand & last_significant_bit) != 0) { + // 1 for our last bit, round up. + round_away_from_zero = true; + break; + } + break; + } + + if (round_away_from_zero) { + return static_cast( + negatable_right_shift(num_throwaway_bits, incrementSignificand( + significand, last_significant_bit, carry_bit))); + } else { + return static_cast( + negatable_right_shift(num_throwaway_bits, significand)); + } + } + + // Casts this value to another HexFloat. If the cast is widening, + // then round_dir is ignored. If the cast is narrowing, then + // the result is rounded in the direction specified. + // This number will retain Nan and Inf values. + // It will also saturate to Inf if the number overflows, and + // underflow to (0 or min depending on rounding) if the number underflows. + template + void castTo(other_T& other, round_direction round_dir) { + other = other_T(static_cast(0)); + bool negate = isNegative(); + if (getUnsignedBits() == 0) { + if (negate) { + other.set_value(-other.value()); + } + return; + } + uint_type significand = getSignificandBits(); + bool carried = false; + typename other_T::uint_type rounded_significand = + getRoundedNormalizedSignificand(round_dir, &carried); + + int_type exponent = getUnbiasedExponent(); + if (exponent == min_exponent) { + // If we are denormal, normalize the exponent, so that we can encode + // easily. + exponent = static_cast(exponent + 1); + for (uint_type check_bit = first_exponent_bit >> 1; check_bit != 0; + check_bit = static_cast(check_bit >> 1)) { + exponent = static_cast(exponent - 1); + if (check_bit & significand) break; + } + } + + bool is_nan = + (getBits() & exponent_mask) == exponent_mask && significand != 0; + bool is_inf = + !is_nan && + ((exponent + carried) > static_cast(other_T::exponent_bias) || + (significand == 0 && (getBits() & exponent_mask) == exponent_mask)); + + // If we are Nan or Inf we should pass that through. + if (is_inf) { + other.set_value(BitwiseCast( + static_cast( + (negate ? other_T::sign_mask : 0) | other_T::exponent_mask))); + return; + } + if (is_nan) { + typename other_T::uint_type shifted_significand; + shifted_significand = static_cast( + negatable_left_shift( + static_cast(other_T::num_fraction_bits) - + static_cast(num_fraction_bits), significand)); + + // We are some sort of Nan. We try to keep the bit-pattern of the Nan + // as close as possible. If we had to shift off bits so we are 0, then we + // just set the last bit. + other.set_value(BitwiseCast( + static_cast( + (negate ? other_T::sign_mask : 0) | other_T::exponent_mask | + (shifted_significand == 0 ? 0x1 : shifted_significand)))); + return; + } + + bool round_underflow_up = + isNegative() ? round_dir == kRoundToNegativeInfinity + : round_dir == kRoundToPositiveInfinity; + typedef typename other_T::int_type other_int_type; + // setFromSignUnbiasedExponentAndNormalizedSignificand will + // zero out any underflowing value (but retain the sign). + other.setFromSignUnbiasedExponentAndNormalizedSignificand( + negate, static_cast(exponent), rounded_significand, + round_underflow_up); + return; + } + + private: + T value_; + + static_assert(num_used_bits == + Traits::num_exponent_bits + Traits::num_fraction_bits + 1, + "The number of bits do not fit"); + static_assert(sizeof(T) == sizeof(uint_type), "The type sizes do not match"); +}; + +// Returns 4 bits represented by the hex character. +inline uint8_t get_nibble_from_character(int character) { + const char* dec = "0123456789"; + const char* lower = "abcdef"; + const char* upper = "ABCDEF"; + const char* p = nullptr; + if ((p = strchr(dec, character))) { + return static_cast(p - dec); + } else if ((p = strchr(lower, character))) { + return static_cast(p - lower + 0xa); + } else if ((p = strchr(upper, character))) { + return static_cast(p - upper + 0xa); + } + + assert(false && "This was called with a non-hex character"); + return 0; +} + +// Outputs the given HexFloat to the stream. +template +std::ostream& operator<<(std::ostream& os, const HexFloat& value) { + typedef HexFloat HF; + typedef typename HF::uint_type uint_type; + typedef typename HF::int_type int_type; + + static_assert(HF::num_used_bits != 0, + "num_used_bits must be non-zero for a valid float"); + static_assert(HF::num_exponent_bits != 0, + "num_exponent_bits must be non-zero for a valid float"); + static_assert(HF::num_fraction_bits != 0, + "num_fractin_bits must be non-zero for a valid float"); + + const uint_type bits = spvutils::BitwiseCast(value.value()); + const char* const sign = (bits & HF::sign_mask) ? "-" : ""; + const uint_type exponent = static_cast( + (bits & HF::exponent_mask) >> HF::num_fraction_bits); + + uint_type fraction = static_cast((bits & HF::fraction_encode_mask) + << HF::num_overflow_bits); + + const bool is_zero = exponent == 0 && fraction == 0; + const bool is_denorm = exponent == 0 && !is_zero; + + // exponent contains the biased exponent we have to convert it back into + // the normal range. + int_type int_exponent = static_cast(exponent - HF::exponent_bias); + // If the number is all zeros, then we actually have to NOT shift the + // exponent. + int_exponent = is_zero ? 0 : int_exponent; + + // If we are denorm, then start shifting, and decreasing the exponent until + // our leading bit is 1. + + if (is_denorm) { + while ((fraction & HF::fraction_top_bit) == 0) { + fraction = static_cast(fraction << 1); + int_exponent = static_cast(int_exponent - 1); + } + // Since this is denormalized, we have to consume the leading 1 since it + // will end up being implicit. + fraction = static_cast(fraction << 1); // eat the leading 1 + fraction &= HF::fraction_represent_mask; + } + + uint_type fraction_nibbles = HF::fraction_nibbles; + // We do not have to display any trailing 0s, since this represents the + // fractional part. + while (fraction_nibbles > 0 && (fraction & 0xF) == 0) { + // Shift off any trailing values; + fraction = static_cast(fraction >> 4); + --fraction_nibbles; + } + + const auto saved_flags = os.flags(); + const auto saved_fill = os.fill(); + + os << sign << "0x" << (is_zero ? '0' : '1'); + if (fraction_nibbles) { + // Make sure to keep the leading 0s in place, since this is the fractional + // part. + os << "." << std::setw(static_cast(fraction_nibbles)) + << std::setfill('0') << std::hex << fraction; + } + os << "p" << std::dec << (int_exponent >= 0 ? "+" : "") << int_exponent; + + os.flags(saved_flags); + os.fill(saved_fill); + + return os; +} + +// Returns true if negate_value is true and the next character on the +// input stream is a plus or minus sign. In that case we also set the fail bit +// on the stream and set the value to the zero value for its type. +template +inline bool RejectParseDueToLeadingSign(std::istream& is, bool negate_value, + HexFloat& value) { + if (negate_value) { + auto next_char = is.peek(); + if (next_char == '-' || next_char == '+') { + // Fail the parse. Emulate standard behaviour by setting the value to + // the zero value, and set the fail bit on the stream. + value = HexFloat(typename HexFloat::uint_type(0)); + is.setstate(std::ios_base::failbit); + return true; + } + } + return false; +} + +// Parses a floating point number from the given stream and stores it into the +// value parameter. +// If negate_value is true then the number may not have a leading minus or +// plus, and if it successfully parses, then the number is negated before +// being stored into the value parameter. +// If the value cannot be correctly parsed or overflows the target floating +// point type, then set the fail bit on the stream. +// TODO(dneto): Promise C++11 standard behavior in how the value is set in +// the error case, but only after all target platforms implement it correctly. +// In particular, the Microsoft C++ runtime appears to be out of spec. +template +inline std::istream& ParseNormalFloat(std::istream& is, bool negate_value, + HexFloat& value) { + if (RejectParseDueToLeadingSign(is, negate_value, value)) { + return is; + } + T val; + is >> val; + if (negate_value) { + val = -val; + } + value.set_value(val); + // In the failure case, map -0.0 to 0.0. + if (is.fail() && value.getUnsignedBits() == 0u) { + value = HexFloat(typename HexFloat::uint_type(0)); + } + if (val.isInfinity()) { + // Fail the parse. Emulate standard behaviour by setting the value to + // the closest normal value, and set the fail bit on the stream. + value.set_value((value.isNegative() || negate_value) ? T::lowest() + : T::max()); + is.setstate(std::ios_base::failbit); + } + return is; +} + +// Specialization of ParseNormalFloat for FloatProxy values. +// This will parse the float as it were a 32-bit floating point number, +// and then round it down to fit into a Float16 value. +// The number is rounded towards zero. +// If negate_value is true then the number may not have a leading minus or +// plus, and if it successfully parses, then the number is negated before +// being stored into the value parameter. +// If the value cannot be correctly parsed or overflows the target floating +// point type, then set the fail bit on the stream. +// TODO(dneto): Promise C++11 standard behavior in how the value is set in +// the error case, but only after all target platforms implement it correctly. +// In particular, the Microsoft C++ runtime appears to be out of spec. +template <> +inline std::istream& +ParseNormalFloat, HexFloatTraits>>( + std::istream& is, bool negate_value, + HexFloat, HexFloatTraits>>& value) { + // First parse as a 32-bit float. + HexFloat> float_val(0.0f); + ParseNormalFloat(is, negate_value, float_val); + + // Then convert to 16-bit float, saturating at infinities, and + // rounding toward zero. + float_val.castTo(value, kRoundToZero); + + // Overflow on 16-bit behaves the same as for 32- and 64-bit: set the + // fail bit and set the lowest or highest value. + if (Float16::isInfinity(value.value().getAsFloat())) { + value.set_value(value.isNegative() ? Float16::lowest() : Float16::max()); + is.setstate(std::ios_base::failbit); + } + return is; +} + +// Reads a HexFloat from the given stream. +// If the float is not encoded as a hex-float then it will be parsed +// as a regular float. +// This may fail if your stream does not support at least one unget. +// Nan values can be encoded with "0x1.p+exponent_bias". +// This would normally overflow a float and round to +// infinity but this special pattern is the exact representation for a NaN, +// and therefore is actually encoded as the correct NaN. To encode inf, +// either 0x0p+exponent_bias can be specified or any exponent greater than +// exponent_bias. +// Examples using IEEE 32-bit float encoding. +// 0x1.0p+128 (+inf) +// -0x1.0p-128 (-inf) +// +// 0x1.1p+128 (+Nan) +// -0x1.1p+128 (-Nan) +// +// 0x1p+129 (+inf) +// -0x1p+129 (-inf) +template +std::istream& operator>>(std::istream& is, HexFloat& value) { + using HF = HexFloat; + using uint_type = typename HF::uint_type; + using int_type = typename HF::int_type; + + value.set_value(static_cast(0.f)); + + if (is.flags() & std::ios::skipws) { + // If the user wants to skip whitespace , then we should obey that. + while (std::isspace(is.peek())) { + is.get(); + } + } + + auto next_char = is.peek(); + bool negate_value = false; + + if (next_char != '-' && next_char != '0') { + return ParseNormalFloat(is, negate_value, value); + } + + if (next_char == '-') { + negate_value = true; + is.get(); + next_char = is.peek(); + } + + if (next_char == '0') { + is.get(); // We may have to unget this. + auto maybe_hex_start = is.peek(); + if (maybe_hex_start != 'x' && maybe_hex_start != 'X') { + is.unget(); + return ParseNormalFloat(is, negate_value, value); + } else { + is.get(); // Throw away the 'x'; + } + } else { + return ParseNormalFloat(is, negate_value, value); + } + + // This "looks" like a hex-float so treat it as one. + bool seen_p = false; + bool seen_dot = false; + uint_type fraction_index = 0; + + uint_type fraction = 0; + int_type exponent = HF::exponent_bias; + + // Strip off leading zeros so we don't have to special-case them later. + while ((next_char = is.peek()) == '0') { + is.get(); + } + + bool is_denorm = + true; // Assume denorm "representation" until we hear otherwise. + // NB: This does not mean the value is actually denorm, + // it just means that it was written 0. + bool bits_written = false; // Stays false until we write a bit. + while (!seen_p && !seen_dot) { + // Handle characters that are left of the fractional part. + if (next_char == '.') { + seen_dot = true; + } else if (next_char == 'p') { + seen_p = true; + } else if (::isxdigit(next_char)) { + // We know this is not denormalized since we have stripped all leading + // zeroes and we are not a ".". + is_denorm = false; + int number = get_nibble_from_character(next_char); + for (int i = 0; i < 4; ++i, number <<= 1) { + uint_type write_bit = (number & 0x8) ? 0x1 : 0x0; + if (bits_written) { + // If we are here the bits represented belong in the fractional + // part of the float, and we have to adjust the exponent accordingly. + fraction = static_cast( + fraction | + static_cast( + write_bit << (HF::top_bit_left_shift - fraction_index++))); + exponent = static_cast(exponent + 1); + } + bits_written |= write_bit != 0; + } + } else { + // We have not found our exponent yet, so we have to fail. + is.setstate(std::ios::failbit); + return is; + } + is.get(); + next_char = is.peek(); + } + bits_written = false; + while (seen_dot && !seen_p) { + // Handle only fractional parts now. + if (next_char == 'p') { + seen_p = true; + } else if (::isxdigit(next_char)) { + int number = get_nibble_from_character(next_char); + for (int i = 0; i < 4; ++i, number <<= 1) { + uint_type write_bit = (number & 0x8) ? 0x01 : 0x00; + bits_written |= write_bit != 0; + if (is_denorm && !bits_written) { + // Handle modifying the exponent here this way we can handle + // an arbitrary number of hex values without overflowing our + // integer. + exponent = static_cast(exponent - 1); + } else { + fraction = static_cast( + fraction | + static_cast( + write_bit << (HF::top_bit_left_shift - fraction_index++))); + } + } + } else { + // We still have not found our 'p' exponent yet, so this is not a valid + // hex-float. + is.setstate(std::ios::failbit); + return is; + } + is.get(); + next_char = is.peek(); + } + + bool seen_sign = false; + int8_t exponent_sign = 1; + int_type written_exponent = 0; + while (true) { + if ((next_char == '-' || next_char == '+')) { + if (seen_sign) { + is.setstate(std::ios::failbit); + return is; + } + seen_sign = true; + exponent_sign = (next_char == '-') ? -1 : 1; + } else if (::isdigit(next_char)) { + // Hex-floats express their exponent as decimal. + written_exponent = static_cast(written_exponent * 10); + written_exponent = + static_cast(written_exponent + (next_char - '0')); + } else { + break; + } + is.get(); + next_char = is.peek(); + } + + written_exponent = static_cast(written_exponent * exponent_sign); + exponent = static_cast(exponent + written_exponent); + + bool is_zero = is_denorm && (fraction == 0); + if (is_denorm && !is_zero) { + fraction = static_cast(fraction << 1); + exponent = static_cast(exponent - 1); + } else if (is_zero) { + exponent = 0; + } + + if (exponent <= 0 && !is_zero) { + fraction = static_cast(fraction >> 1); + fraction |= static_cast(1) << HF::top_bit_left_shift; + } + + fraction = (fraction >> HF::fraction_right_shift) & HF::fraction_encode_mask; + + const int_type max_exponent = + SetBits::get; + + // Handle actual denorm numbers + while (exponent < 0 && !is_zero) { + fraction = static_cast(fraction >> 1); + exponent = static_cast(exponent + 1); + + fraction &= HF::fraction_encode_mask; + if (fraction == 0) { + // We have underflowed our fraction. We should clamp to zero. + is_zero = true; + exponent = 0; + } + } + + // We have overflowed so we should be inf/-inf. + if (exponent > max_exponent) { + exponent = max_exponent; + fraction = 0; + } + + uint_type output_bits = static_cast( + static_cast(negate_value ? 1 : 0) << HF::top_bit_left_shift); + output_bits |= fraction; + + uint_type shifted_exponent = static_cast( + static_cast(exponent << HF::exponent_left_shift) & + HF::exponent_mask); + output_bits |= shifted_exponent; + + T output_float = spvutils::BitwiseCast(output_bits); + value.set_value(output_float); + + return is; +} + +// Writes a FloatProxy value to a stream. +// Zero and normal numbers are printed in the usual notation, but with +// enough digits to fully reproduce the value. Other values (subnormal, +// NaN, and infinity) are printed as a hex float. +template +std::ostream& operator<<(std::ostream& os, const FloatProxy& value) { + auto float_val = value.getAsFloat(); + switch (std::fpclassify(float_val)) { + case FP_ZERO: + case FP_NORMAL: { + auto saved_precision = os.precision(); + os.precision(std::numeric_limits::digits10); + os << float_val; + os.precision(saved_precision); + } break; + default: + os << HexFloat>(value); + break; + } + return os; +} + +template <> +inline std::ostream& operator<<(std::ostream& os, + const FloatProxy& value) { + os << HexFloat>(value); + return os; +} +} + +#endif // LIBSPIRV_UTIL_HEX_FLOAT_H_ diff --git a/android/x86/include/glslang/SPIRV/spirv.hpp b/android/x86/include/glslang/SPIRV/spirv.hpp new file mode 100644 index 00000000..dae36cf2 --- /dev/null +++ b/android/x86/include/glslang/SPIRV/spirv.hpp @@ -0,0 +1,2114 @@ +// Copyright (c) 2014-2020 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and/or associated documentation files (the "Materials"), +// to deal in the Materials without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Materials, and to permit persons to whom the +// Materials are furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +// IN THE MATERIALS. + +// This header is automatically generated by the same tool that creates +// the Binary Section of the SPIR-V specification. + +// Enumeration tokens for SPIR-V, in various styles: +// C, C++, C++11, JSON, Lua, Python, C#, D +// +// - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL +// - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL +// - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL +// - Lua will use tables, e.g.: spv.SourceLanguage.GLSL +// - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] +// - C# will use enum classes in the Specification class located in the "Spv" namespace, +// e.g.: Spv.Specification.SourceLanguage.GLSL +// - D will have tokens under the "spv" module, e.g: spv.SourceLanguage.GLSL +// +// Some tokens act like mask values, which can be OR'd together, +// while others are mutually exclusive. The mask-like ones have +// "Mask" in their name, and a parallel enum that has the shift +// amount (1 << x) for each corresponding enumerant. + +#ifndef spirv_HPP +#define spirv_HPP + +namespace spv { + +typedef unsigned int Id; + +#define SPV_VERSION 0x10500 +#define SPV_REVISION 3 + +static const unsigned int MagicNumber = 0x07230203; +static const unsigned int Version = 0x00010500; +static const unsigned int Revision = 3; +static const unsigned int OpCodeMask = 0xffff; +static const unsigned int WordCountShift = 16; + +enum SourceLanguage { + SourceLanguageUnknown = 0, + SourceLanguageESSL = 1, + SourceLanguageGLSL = 2, + SourceLanguageOpenCL_C = 3, + SourceLanguageOpenCL_CPP = 4, + SourceLanguageHLSL = 5, + SourceLanguageMax = 0x7fffffff, +}; + +enum ExecutionModel { + ExecutionModelVertex = 0, + ExecutionModelTessellationControl = 1, + ExecutionModelTessellationEvaluation = 2, + ExecutionModelGeometry = 3, + ExecutionModelFragment = 4, + ExecutionModelGLCompute = 5, + ExecutionModelKernel = 6, + ExecutionModelTaskNV = 5267, + ExecutionModelMeshNV = 5268, + ExecutionModelRayGenerationKHR = 5313, + ExecutionModelRayGenerationNV = 5313, + ExecutionModelIntersectionKHR = 5314, + ExecutionModelIntersectionNV = 5314, + ExecutionModelAnyHitKHR = 5315, + ExecutionModelAnyHitNV = 5315, + ExecutionModelClosestHitKHR = 5316, + ExecutionModelClosestHitNV = 5316, + ExecutionModelMissKHR = 5317, + ExecutionModelMissNV = 5317, + ExecutionModelCallableKHR = 5318, + ExecutionModelCallableNV = 5318, + ExecutionModelMax = 0x7fffffff, +}; + +enum AddressingModel { + AddressingModelLogical = 0, + AddressingModelPhysical32 = 1, + AddressingModelPhysical64 = 2, + AddressingModelPhysicalStorageBuffer64 = 5348, + AddressingModelPhysicalStorageBuffer64EXT = 5348, + AddressingModelMax = 0x7fffffff, +}; + +enum MemoryModel { + MemoryModelSimple = 0, + MemoryModelGLSL450 = 1, + MemoryModelOpenCL = 2, + MemoryModelVulkan = 3, + MemoryModelVulkanKHR = 3, + MemoryModelMax = 0x7fffffff, +}; + +enum ExecutionMode { + ExecutionModeInvocations = 0, + ExecutionModeSpacingEqual = 1, + ExecutionModeSpacingFractionalEven = 2, + ExecutionModeSpacingFractionalOdd = 3, + ExecutionModeVertexOrderCw = 4, + ExecutionModeVertexOrderCcw = 5, + ExecutionModePixelCenterInteger = 6, + ExecutionModeOriginUpperLeft = 7, + ExecutionModeOriginLowerLeft = 8, + ExecutionModeEarlyFragmentTests = 9, + ExecutionModePointMode = 10, + ExecutionModeXfb = 11, + ExecutionModeDepthReplacing = 12, + ExecutionModeDepthGreater = 14, + ExecutionModeDepthLess = 15, + ExecutionModeDepthUnchanged = 16, + ExecutionModeLocalSize = 17, + ExecutionModeLocalSizeHint = 18, + ExecutionModeInputPoints = 19, + ExecutionModeInputLines = 20, + ExecutionModeInputLinesAdjacency = 21, + ExecutionModeTriangles = 22, + ExecutionModeInputTrianglesAdjacency = 23, + ExecutionModeQuads = 24, + ExecutionModeIsolines = 25, + ExecutionModeOutputVertices = 26, + ExecutionModeOutputPoints = 27, + ExecutionModeOutputLineStrip = 28, + ExecutionModeOutputTriangleStrip = 29, + ExecutionModeVecTypeHint = 30, + ExecutionModeContractionOff = 31, + ExecutionModeInitializer = 33, + ExecutionModeFinalizer = 34, + ExecutionModeSubgroupSize = 35, + ExecutionModeSubgroupsPerWorkgroup = 36, + ExecutionModeSubgroupsPerWorkgroupId = 37, + ExecutionModeLocalSizeId = 38, + ExecutionModeLocalSizeHintId = 39, + ExecutionModePostDepthCoverage = 4446, + ExecutionModeDenormPreserve = 4459, + ExecutionModeDenormFlushToZero = 4460, + ExecutionModeSignedZeroInfNanPreserve = 4461, + ExecutionModeRoundingModeRTE = 4462, + ExecutionModeRoundingModeRTZ = 4463, + ExecutionModeStencilRefReplacingEXT = 5027, + ExecutionModeOutputLinesNV = 5269, + ExecutionModeOutputPrimitivesNV = 5270, + ExecutionModeDerivativeGroupQuadsNV = 5289, + ExecutionModeDerivativeGroupLinearNV = 5290, + ExecutionModeOutputTrianglesNV = 5298, + ExecutionModePixelInterlockOrderedEXT = 5366, + ExecutionModePixelInterlockUnorderedEXT = 5367, + ExecutionModeSampleInterlockOrderedEXT = 5368, + ExecutionModeSampleInterlockUnorderedEXT = 5369, + ExecutionModeShadingRateInterlockOrderedEXT = 5370, + ExecutionModeShadingRateInterlockUnorderedEXT = 5371, + ExecutionModeMax = 0x7fffffff, +}; + +enum StorageClass { + StorageClassUniformConstant = 0, + StorageClassInput = 1, + StorageClassUniform = 2, + StorageClassOutput = 3, + StorageClassWorkgroup = 4, + StorageClassCrossWorkgroup = 5, + StorageClassPrivate = 6, + StorageClassFunction = 7, + StorageClassGeneric = 8, + StorageClassPushConstant = 9, + StorageClassAtomicCounter = 10, + StorageClassImage = 11, + StorageClassStorageBuffer = 12, + StorageClassCallableDataKHR = 5328, + StorageClassCallableDataNV = 5328, + StorageClassIncomingCallableDataKHR = 5329, + StorageClassIncomingCallableDataNV = 5329, + StorageClassRayPayloadKHR = 5338, + StorageClassRayPayloadNV = 5338, + StorageClassHitAttributeKHR = 5339, + StorageClassHitAttributeNV = 5339, + StorageClassIncomingRayPayloadKHR = 5342, + StorageClassIncomingRayPayloadNV = 5342, + StorageClassShaderRecordBufferKHR = 5343, + StorageClassShaderRecordBufferNV = 5343, + StorageClassPhysicalStorageBuffer = 5349, + StorageClassPhysicalStorageBufferEXT = 5349, + StorageClassMax = 0x7fffffff, +}; + +enum Dim { + Dim1D = 0, + Dim2D = 1, + Dim3D = 2, + DimCube = 3, + DimRect = 4, + DimBuffer = 5, + DimSubpassData = 6, + DimMax = 0x7fffffff, +}; + +enum SamplerAddressingMode { + SamplerAddressingModeNone = 0, + SamplerAddressingModeClampToEdge = 1, + SamplerAddressingModeClamp = 2, + SamplerAddressingModeRepeat = 3, + SamplerAddressingModeRepeatMirrored = 4, + SamplerAddressingModeMax = 0x7fffffff, +}; + +enum SamplerFilterMode { + SamplerFilterModeNearest = 0, + SamplerFilterModeLinear = 1, + SamplerFilterModeMax = 0x7fffffff, +}; + +enum ImageFormat { + ImageFormatUnknown = 0, + ImageFormatRgba32f = 1, + ImageFormatRgba16f = 2, + ImageFormatR32f = 3, + ImageFormatRgba8 = 4, + ImageFormatRgba8Snorm = 5, + ImageFormatRg32f = 6, + ImageFormatRg16f = 7, + ImageFormatR11fG11fB10f = 8, + ImageFormatR16f = 9, + ImageFormatRgba16 = 10, + ImageFormatRgb10A2 = 11, + ImageFormatRg16 = 12, + ImageFormatRg8 = 13, + ImageFormatR16 = 14, + ImageFormatR8 = 15, + ImageFormatRgba16Snorm = 16, + ImageFormatRg16Snorm = 17, + ImageFormatRg8Snorm = 18, + ImageFormatR16Snorm = 19, + ImageFormatR8Snorm = 20, + ImageFormatRgba32i = 21, + ImageFormatRgba16i = 22, + ImageFormatRgba8i = 23, + ImageFormatR32i = 24, + ImageFormatRg32i = 25, + ImageFormatRg16i = 26, + ImageFormatRg8i = 27, + ImageFormatR16i = 28, + ImageFormatR8i = 29, + ImageFormatRgba32ui = 30, + ImageFormatRgba16ui = 31, + ImageFormatRgba8ui = 32, + ImageFormatR32ui = 33, + ImageFormatRgb10a2ui = 34, + ImageFormatRg32ui = 35, + ImageFormatRg16ui = 36, + ImageFormatRg8ui = 37, + ImageFormatR16ui = 38, + ImageFormatR8ui = 39, + ImageFormatMax = 0x7fffffff, +}; + +enum ImageChannelOrder { + ImageChannelOrderR = 0, + ImageChannelOrderA = 1, + ImageChannelOrderRG = 2, + ImageChannelOrderRA = 3, + ImageChannelOrderRGB = 4, + ImageChannelOrderRGBA = 5, + ImageChannelOrderBGRA = 6, + ImageChannelOrderARGB = 7, + ImageChannelOrderIntensity = 8, + ImageChannelOrderLuminance = 9, + ImageChannelOrderRx = 10, + ImageChannelOrderRGx = 11, + ImageChannelOrderRGBx = 12, + ImageChannelOrderDepth = 13, + ImageChannelOrderDepthStencil = 14, + ImageChannelOrdersRGB = 15, + ImageChannelOrdersRGBx = 16, + ImageChannelOrdersRGBA = 17, + ImageChannelOrdersBGRA = 18, + ImageChannelOrderABGR = 19, + ImageChannelOrderMax = 0x7fffffff, +}; + +enum ImageChannelDataType { + ImageChannelDataTypeSnormInt8 = 0, + ImageChannelDataTypeSnormInt16 = 1, + ImageChannelDataTypeUnormInt8 = 2, + ImageChannelDataTypeUnormInt16 = 3, + ImageChannelDataTypeUnormShort565 = 4, + ImageChannelDataTypeUnormShort555 = 5, + ImageChannelDataTypeUnormInt101010 = 6, + ImageChannelDataTypeSignedInt8 = 7, + ImageChannelDataTypeSignedInt16 = 8, + ImageChannelDataTypeSignedInt32 = 9, + ImageChannelDataTypeUnsignedInt8 = 10, + ImageChannelDataTypeUnsignedInt16 = 11, + ImageChannelDataTypeUnsignedInt32 = 12, + ImageChannelDataTypeHalfFloat = 13, + ImageChannelDataTypeFloat = 14, + ImageChannelDataTypeUnormInt24 = 15, + ImageChannelDataTypeUnormInt101010_2 = 16, + ImageChannelDataTypeMax = 0x7fffffff, +}; + +enum ImageOperandsShift { + ImageOperandsBiasShift = 0, + ImageOperandsLodShift = 1, + ImageOperandsGradShift = 2, + ImageOperandsConstOffsetShift = 3, + ImageOperandsOffsetShift = 4, + ImageOperandsConstOffsetsShift = 5, + ImageOperandsSampleShift = 6, + ImageOperandsMinLodShift = 7, + ImageOperandsMakeTexelAvailableShift = 8, + ImageOperandsMakeTexelAvailableKHRShift = 8, + ImageOperandsMakeTexelVisibleShift = 9, + ImageOperandsMakeTexelVisibleKHRShift = 9, + ImageOperandsNonPrivateTexelShift = 10, + ImageOperandsNonPrivateTexelKHRShift = 10, + ImageOperandsVolatileTexelShift = 11, + ImageOperandsVolatileTexelKHRShift = 11, + ImageOperandsSignExtendShift = 12, + ImageOperandsZeroExtendShift = 13, + ImageOperandsMax = 0x7fffffff, +}; + +enum ImageOperandsMask { + ImageOperandsMaskNone = 0, + ImageOperandsBiasMask = 0x00000001, + ImageOperandsLodMask = 0x00000002, + ImageOperandsGradMask = 0x00000004, + ImageOperandsConstOffsetMask = 0x00000008, + ImageOperandsOffsetMask = 0x00000010, + ImageOperandsConstOffsetsMask = 0x00000020, + ImageOperandsSampleMask = 0x00000040, + ImageOperandsMinLodMask = 0x00000080, + ImageOperandsMakeTexelAvailableMask = 0x00000100, + ImageOperandsMakeTexelAvailableKHRMask = 0x00000100, + ImageOperandsMakeTexelVisibleMask = 0x00000200, + ImageOperandsMakeTexelVisibleKHRMask = 0x00000200, + ImageOperandsNonPrivateTexelMask = 0x00000400, + ImageOperandsNonPrivateTexelKHRMask = 0x00000400, + ImageOperandsVolatileTexelMask = 0x00000800, + ImageOperandsVolatileTexelKHRMask = 0x00000800, + ImageOperandsSignExtendMask = 0x00001000, + ImageOperandsZeroExtendMask = 0x00002000, +}; + +enum FPFastMathModeShift { + FPFastMathModeNotNaNShift = 0, + FPFastMathModeNotInfShift = 1, + FPFastMathModeNSZShift = 2, + FPFastMathModeAllowRecipShift = 3, + FPFastMathModeFastShift = 4, + FPFastMathModeMax = 0x7fffffff, +}; + +enum FPFastMathModeMask { + FPFastMathModeMaskNone = 0, + FPFastMathModeNotNaNMask = 0x00000001, + FPFastMathModeNotInfMask = 0x00000002, + FPFastMathModeNSZMask = 0x00000004, + FPFastMathModeAllowRecipMask = 0x00000008, + FPFastMathModeFastMask = 0x00000010, +}; + +enum FPRoundingMode { + FPRoundingModeRTE = 0, + FPRoundingModeRTZ = 1, + FPRoundingModeRTP = 2, + FPRoundingModeRTN = 3, + FPRoundingModeMax = 0x7fffffff, +}; + +enum LinkageType { + LinkageTypeExport = 0, + LinkageTypeImport = 1, + LinkageTypeMax = 0x7fffffff, +}; + +enum AccessQualifier { + AccessQualifierReadOnly = 0, + AccessQualifierWriteOnly = 1, + AccessQualifierReadWrite = 2, + AccessQualifierMax = 0x7fffffff, +}; + +enum FunctionParameterAttribute { + FunctionParameterAttributeZext = 0, + FunctionParameterAttributeSext = 1, + FunctionParameterAttributeByVal = 2, + FunctionParameterAttributeSret = 3, + FunctionParameterAttributeNoAlias = 4, + FunctionParameterAttributeNoCapture = 5, + FunctionParameterAttributeNoWrite = 6, + FunctionParameterAttributeNoReadWrite = 7, + FunctionParameterAttributeMax = 0x7fffffff, +}; + +enum Decoration { + DecorationRelaxedPrecision = 0, + DecorationSpecId = 1, + DecorationBlock = 2, + DecorationBufferBlock = 3, + DecorationRowMajor = 4, + DecorationColMajor = 5, + DecorationArrayStride = 6, + DecorationMatrixStride = 7, + DecorationGLSLShared = 8, + DecorationGLSLPacked = 9, + DecorationCPacked = 10, + DecorationBuiltIn = 11, + DecorationNoPerspective = 13, + DecorationFlat = 14, + DecorationPatch = 15, + DecorationCentroid = 16, + DecorationSample = 17, + DecorationInvariant = 18, + DecorationRestrict = 19, + DecorationAliased = 20, + DecorationVolatile = 21, + DecorationConstant = 22, + DecorationCoherent = 23, + DecorationNonWritable = 24, + DecorationNonReadable = 25, + DecorationUniform = 26, + DecorationUniformId = 27, + DecorationSaturatedConversion = 28, + DecorationStream = 29, + DecorationLocation = 30, + DecorationComponent = 31, + DecorationIndex = 32, + DecorationBinding = 33, + DecorationDescriptorSet = 34, + DecorationOffset = 35, + DecorationXfbBuffer = 36, + DecorationXfbStride = 37, + DecorationFuncParamAttr = 38, + DecorationFPRoundingMode = 39, + DecorationFPFastMathMode = 40, + DecorationLinkageAttributes = 41, + DecorationNoContraction = 42, + DecorationInputAttachmentIndex = 43, + DecorationAlignment = 44, + DecorationMaxByteOffset = 45, + DecorationAlignmentId = 46, + DecorationMaxByteOffsetId = 47, + DecorationNoSignedWrap = 4469, + DecorationNoUnsignedWrap = 4470, + DecorationExplicitInterpAMD = 4999, + DecorationOverrideCoverageNV = 5248, + DecorationPassthroughNV = 5250, + DecorationViewportRelativeNV = 5252, + DecorationSecondaryViewportRelativeNV = 5256, + DecorationPerPrimitiveNV = 5271, + DecorationPerViewNV = 5272, + DecorationPerTaskNV = 5273, + DecorationPerVertexNV = 5285, + DecorationNonUniform = 5300, + DecorationNonUniformEXT = 5300, + DecorationRestrictPointer = 5355, + DecorationRestrictPointerEXT = 5355, + DecorationAliasedPointer = 5356, + DecorationAliasedPointerEXT = 5356, + DecorationCounterBuffer = 5634, + DecorationHlslCounterBufferGOOGLE = 5634, + DecorationHlslSemanticGOOGLE = 5635, + DecorationUserSemantic = 5635, + DecorationUserTypeGOOGLE = 5636, + DecorationMax = 0x7fffffff, +}; + +enum BuiltIn { + BuiltInPosition = 0, + BuiltInPointSize = 1, + BuiltInClipDistance = 3, + BuiltInCullDistance = 4, + BuiltInVertexId = 5, + BuiltInInstanceId = 6, + BuiltInPrimitiveId = 7, + BuiltInInvocationId = 8, + BuiltInLayer = 9, + BuiltInViewportIndex = 10, + BuiltInTessLevelOuter = 11, + BuiltInTessLevelInner = 12, + BuiltInTessCoord = 13, + BuiltInPatchVertices = 14, + BuiltInFragCoord = 15, + BuiltInPointCoord = 16, + BuiltInFrontFacing = 17, + BuiltInSampleId = 18, + BuiltInSamplePosition = 19, + BuiltInSampleMask = 20, + BuiltInFragDepth = 22, + BuiltInHelperInvocation = 23, + BuiltInNumWorkgroups = 24, + BuiltInWorkgroupSize = 25, + BuiltInWorkgroupId = 26, + BuiltInLocalInvocationId = 27, + BuiltInGlobalInvocationId = 28, + BuiltInLocalInvocationIndex = 29, + BuiltInWorkDim = 30, + BuiltInGlobalSize = 31, + BuiltInEnqueuedWorkgroupSize = 32, + BuiltInGlobalOffset = 33, + BuiltInGlobalLinearId = 34, + BuiltInSubgroupSize = 36, + BuiltInSubgroupMaxSize = 37, + BuiltInNumSubgroups = 38, + BuiltInNumEnqueuedSubgroups = 39, + BuiltInSubgroupId = 40, + BuiltInSubgroupLocalInvocationId = 41, + BuiltInVertexIndex = 42, + BuiltInInstanceIndex = 43, + BuiltInSubgroupEqMask = 4416, + BuiltInSubgroupEqMaskKHR = 4416, + BuiltInSubgroupGeMask = 4417, + BuiltInSubgroupGeMaskKHR = 4417, + BuiltInSubgroupGtMask = 4418, + BuiltInSubgroupGtMaskKHR = 4418, + BuiltInSubgroupLeMask = 4419, + BuiltInSubgroupLeMaskKHR = 4419, + BuiltInSubgroupLtMask = 4420, + BuiltInSubgroupLtMaskKHR = 4420, + BuiltInBaseVertex = 4424, + BuiltInBaseInstance = 4425, + BuiltInDrawIndex = 4426, + BuiltInDeviceIndex = 4438, + BuiltInViewIndex = 4440, + BuiltInBaryCoordNoPerspAMD = 4992, + BuiltInBaryCoordNoPerspCentroidAMD = 4993, + BuiltInBaryCoordNoPerspSampleAMD = 4994, + BuiltInBaryCoordSmoothAMD = 4995, + BuiltInBaryCoordSmoothCentroidAMD = 4996, + BuiltInBaryCoordSmoothSampleAMD = 4997, + BuiltInBaryCoordPullModelAMD = 4998, + BuiltInFragStencilRefEXT = 5014, + BuiltInViewportMaskNV = 5253, + BuiltInSecondaryPositionNV = 5257, + BuiltInSecondaryViewportMaskNV = 5258, + BuiltInPositionPerViewNV = 5261, + BuiltInViewportMaskPerViewNV = 5262, + BuiltInFullyCoveredEXT = 5264, + BuiltInTaskCountNV = 5274, + BuiltInPrimitiveCountNV = 5275, + BuiltInPrimitiveIndicesNV = 5276, + BuiltInClipDistancePerViewNV = 5277, + BuiltInCullDistancePerViewNV = 5278, + BuiltInLayerPerViewNV = 5279, + BuiltInMeshViewCountNV = 5280, + BuiltInMeshViewIndicesNV = 5281, + BuiltInBaryCoordNV = 5286, + BuiltInBaryCoordNoPerspNV = 5287, + BuiltInFragSizeEXT = 5292, + BuiltInFragmentSizeNV = 5292, + BuiltInFragInvocationCountEXT = 5293, + BuiltInInvocationsPerPixelNV = 5293, + BuiltInLaunchIdKHR = 5319, + BuiltInLaunchIdNV = 5319, + BuiltInLaunchSizeKHR = 5320, + BuiltInLaunchSizeNV = 5320, + BuiltInWorldRayOriginKHR = 5321, + BuiltInWorldRayOriginNV = 5321, + BuiltInWorldRayDirectionKHR = 5322, + BuiltInWorldRayDirectionNV = 5322, + BuiltInObjectRayOriginKHR = 5323, + BuiltInObjectRayOriginNV = 5323, + BuiltInObjectRayDirectionKHR = 5324, + BuiltInObjectRayDirectionNV = 5324, + BuiltInRayTminKHR = 5325, + BuiltInRayTminNV = 5325, + BuiltInRayTmaxKHR = 5326, + BuiltInRayTmaxNV = 5326, + BuiltInInstanceCustomIndexKHR = 5327, + BuiltInInstanceCustomIndexNV = 5327, + BuiltInObjectToWorldKHR = 5330, + BuiltInObjectToWorldNV = 5330, + BuiltInWorldToObjectKHR = 5331, + BuiltInWorldToObjectNV = 5331, + BuiltInHitTKHR = 5332, + BuiltInHitTNV = 5332, + BuiltInHitKindKHR = 5333, + BuiltInHitKindNV = 5333, + BuiltInIncomingRayFlagsKHR = 5351, + BuiltInIncomingRayFlagsNV = 5351, + BuiltInRayGeometryIndexKHR = 5352, + BuiltInWarpsPerSMNV = 5374, + BuiltInSMCountNV = 5375, + BuiltInWarpIDNV = 5376, + BuiltInSMIDNV = 5377, + BuiltInMax = 0x7fffffff, +}; + +enum SelectionControlShift { + SelectionControlFlattenShift = 0, + SelectionControlDontFlattenShift = 1, + SelectionControlMax = 0x7fffffff, +}; + +enum SelectionControlMask { + SelectionControlMaskNone = 0, + SelectionControlFlattenMask = 0x00000001, + SelectionControlDontFlattenMask = 0x00000002, +}; + +enum LoopControlShift { + LoopControlUnrollShift = 0, + LoopControlDontUnrollShift = 1, + LoopControlDependencyInfiniteShift = 2, + LoopControlDependencyLengthShift = 3, + LoopControlMinIterationsShift = 4, + LoopControlMaxIterationsShift = 5, + LoopControlIterationMultipleShift = 6, + LoopControlPeelCountShift = 7, + LoopControlPartialCountShift = 8, + LoopControlMax = 0x7fffffff, +}; + +enum LoopControlMask { + LoopControlMaskNone = 0, + LoopControlUnrollMask = 0x00000001, + LoopControlDontUnrollMask = 0x00000002, + LoopControlDependencyInfiniteMask = 0x00000004, + LoopControlDependencyLengthMask = 0x00000008, + LoopControlMinIterationsMask = 0x00000010, + LoopControlMaxIterationsMask = 0x00000020, + LoopControlIterationMultipleMask = 0x00000040, + LoopControlPeelCountMask = 0x00000080, + LoopControlPartialCountMask = 0x00000100, +}; + +enum FunctionControlShift { + FunctionControlInlineShift = 0, + FunctionControlDontInlineShift = 1, + FunctionControlPureShift = 2, + FunctionControlConstShift = 3, + FunctionControlMax = 0x7fffffff, +}; + +enum FunctionControlMask { + FunctionControlMaskNone = 0, + FunctionControlInlineMask = 0x00000001, + FunctionControlDontInlineMask = 0x00000002, + FunctionControlPureMask = 0x00000004, + FunctionControlConstMask = 0x00000008, +}; + +enum MemorySemanticsShift { + MemorySemanticsAcquireShift = 1, + MemorySemanticsReleaseShift = 2, + MemorySemanticsAcquireReleaseShift = 3, + MemorySemanticsSequentiallyConsistentShift = 4, + MemorySemanticsUniformMemoryShift = 6, + MemorySemanticsSubgroupMemoryShift = 7, + MemorySemanticsWorkgroupMemoryShift = 8, + MemorySemanticsCrossWorkgroupMemoryShift = 9, + MemorySemanticsAtomicCounterMemoryShift = 10, + MemorySemanticsImageMemoryShift = 11, + MemorySemanticsOutputMemoryShift = 12, + MemorySemanticsOutputMemoryKHRShift = 12, + MemorySemanticsMakeAvailableShift = 13, + MemorySemanticsMakeAvailableKHRShift = 13, + MemorySemanticsMakeVisibleShift = 14, + MemorySemanticsMakeVisibleKHRShift = 14, + MemorySemanticsVolatileShift = 15, + MemorySemanticsMax = 0x7fffffff, +}; + +enum MemorySemanticsMask { + MemorySemanticsMaskNone = 0, + MemorySemanticsAcquireMask = 0x00000002, + MemorySemanticsReleaseMask = 0x00000004, + MemorySemanticsAcquireReleaseMask = 0x00000008, + MemorySemanticsSequentiallyConsistentMask = 0x00000010, + MemorySemanticsUniformMemoryMask = 0x00000040, + MemorySemanticsSubgroupMemoryMask = 0x00000080, + MemorySemanticsWorkgroupMemoryMask = 0x00000100, + MemorySemanticsCrossWorkgroupMemoryMask = 0x00000200, + MemorySemanticsAtomicCounterMemoryMask = 0x00000400, + MemorySemanticsImageMemoryMask = 0x00000800, + MemorySemanticsOutputMemoryMask = 0x00001000, + MemorySemanticsOutputMemoryKHRMask = 0x00001000, + MemorySemanticsMakeAvailableMask = 0x00002000, + MemorySemanticsMakeAvailableKHRMask = 0x00002000, + MemorySemanticsMakeVisibleMask = 0x00004000, + MemorySemanticsMakeVisibleKHRMask = 0x00004000, + MemorySemanticsVolatileMask = 0x00008000, +}; + +enum MemoryAccessShift { + MemoryAccessVolatileShift = 0, + MemoryAccessAlignedShift = 1, + MemoryAccessNontemporalShift = 2, + MemoryAccessMakePointerAvailableShift = 3, + MemoryAccessMakePointerAvailableKHRShift = 3, + MemoryAccessMakePointerVisibleShift = 4, + MemoryAccessMakePointerVisibleKHRShift = 4, + MemoryAccessNonPrivatePointerShift = 5, + MemoryAccessNonPrivatePointerKHRShift = 5, + MemoryAccessMax = 0x7fffffff, +}; + +enum MemoryAccessMask { + MemoryAccessMaskNone = 0, + MemoryAccessVolatileMask = 0x00000001, + MemoryAccessAlignedMask = 0x00000002, + MemoryAccessNontemporalMask = 0x00000004, + MemoryAccessMakePointerAvailableMask = 0x00000008, + MemoryAccessMakePointerAvailableKHRMask = 0x00000008, + MemoryAccessMakePointerVisibleMask = 0x00000010, + MemoryAccessMakePointerVisibleKHRMask = 0x00000010, + MemoryAccessNonPrivatePointerMask = 0x00000020, + MemoryAccessNonPrivatePointerKHRMask = 0x00000020, +}; + +enum Scope { + ScopeCrossDevice = 0, + ScopeDevice = 1, + ScopeWorkgroup = 2, + ScopeSubgroup = 3, + ScopeInvocation = 4, + ScopeQueueFamily = 5, + ScopeQueueFamilyKHR = 5, + ScopeShaderCallKHR = 6, + ScopeMax = 0x7fffffff, +}; + +enum GroupOperation { + GroupOperationReduce = 0, + GroupOperationInclusiveScan = 1, + GroupOperationExclusiveScan = 2, + GroupOperationClusteredReduce = 3, + GroupOperationPartitionedReduceNV = 6, + GroupOperationPartitionedInclusiveScanNV = 7, + GroupOperationPartitionedExclusiveScanNV = 8, + GroupOperationMax = 0x7fffffff, +}; + +enum KernelEnqueueFlags { + KernelEnqueueFlagsNoWait = 0, + KernelEnqueueFlagsWaitKernel = 1, + KernelEnqueueFlagsWaitWorkGroup = 2, + KernelEnqueueFlagsMax = 0x7fffffff, +}; + +enum KernelProfilingInfoShift { + KernelProfilingInfoCmdExecTimeShift = 0, + KernelProfilingInfoMax = 0x7fffffff, +}; + +enum KernelProfilingInfoMask { + KernelProfilingInfoMaskNone = 0, + KernelProfilingInfoCmdExecTimeMask = 0x00000001, +}; + +enum Capability { + CapabilityMatrix = 0, + CapabilityShader = 1, + CapabilityGeometry = 2, + CapabilityTessellation = 3, + CapabilityAddresses = 4, + CapabilityLinkage = 5, + CapabilityKernel = 6, + CapabilityVector16 = 7, + CapabilityFloat16Buffer = 8, + CapabilityFloat16 = 9, + CapabilityFloat64 = 10, + CapabilityInt64 = 11, + CapabilityInt64Atomics = 12, + CapabilityImageBasic = 13, + CapabilityImageReadWrite = 14, + CapabilityImageMipmap = 15, + CapabilityPipes = 17, + CapabilityGroups = 18, + CapabilityDeviceEnqueue = 19, + CapabilityLiteralSampler = 20, + CapabilityAtomicStorage = 21, + CapabilityInt16 = 22, + CapabilityTessellationPointSize = 23, + CapabilityGeometryPointSize = 24, + CapabilityImageGatherExtended = 25, + CapabilityStorageImageMultisample = 27, + CapabilityUniformBufferArrayDynamicIndexing = 28, + CapabilitySampledImageArrayDynamicIndexing = 29, + CapabilityStorageBufferArrayDynamicIndexing = 30, + CapabilityStorageImageArrayDynamicIndexing = 31, + CapabilityClipDistance = 32, + CapabilityCullDistance = 33, + CapabilityImageCubeArray = 34, + CapabilitySampleRateShading = 35, + CapabilityImageRect = 36, + CapabilitySampledRect = 37, + CapabilityGenericPointer = 38, + CapabilityInt8 = 39, + CapabilityInputAttachment = 40, + CapabilitySparseResidency = 41, + CapabilityMinLod = 42, + CapabilitySampled1D = 43, + CapabilityImage1D = 44, + CapabilitySampledCubeArray = 45, + CapabilitySampledBuffer = 46, + CapabilityImageBuffer = 47, + CapabilityImageMSArray = 48, + CapabilityStorageImageExtendedFormats = 49, + CapabilityImageQuery = 50, + CapabilityDerivativeControl = 51, + CapabilityInterpolationFunction = 52, + CapabilityTransformFeedback = 53, + CapabilityGeometryStreams = 54, + CapabilityStorageImageReadWithoutFormat = 55, + CapabilityStorageImageWriteWithoutFormat = 56, + CapabilityMultiViewport = 57, + CapabilitySubgroupDispatch = 58, + CapabilityNamedBarrier = 59, + CapabilityPipeStorage = 60, + CapabilityGroupNonUniform = 61, + CapabilityGroupNonUniformVote = 62, + CapabilityGroupNonUniformArithmetic = 63, + CapabilityGroupNonUniformBallot = 64, + CapabilityGroupNonUniformShuffle = 65, + CapabilityGroupNonUniformShuffleRelative = 66, + CapabilityGroupNonUniformClustered = 67, + CapabilityGroupNonUniformQuad = 68, + CapabilityShaderLayer = 69, + CapabilityShaderViewportIndex = 70, + CapabilitySubgroupBallotKHR = 4423, + CapabilityDrawParameters = 4427, + CapabilitySubgroupVoteKHR = 4431, + CapabilityStorageBuffer16BitAccess = 4433, + CapabilityStorageUniformBufferBlock16 = 4433, + CapabilityStorageUniform16 = 4434, + CapabilityUniformAndStorageBuffer16BitAccess = 4434, + CapabilityStoragePushConstant16 = 4435, + CapabilityStorageInputOutput16 = 4436, + CapabilityDeviceGroup = 4437, + CapabilityMultiView = 4439, + CapabilityVariablePointersStorageBuffer = 4441, + CapabilityVariablePointers = 4442, + CapabilityAtomicStorageOps = 4445, + CapabilitySampleMaskPostDepthCoverage = 4447, + CapabilityStorageBuffer8BitAccess = 4448, + CapabilityUniformAndStorageBuffer8BitAccess = 4449, + CapabilityStoragePushConstant8 = 4450, + CapabilityDenormPreserve = 4464, + CapabilityDenormFlushToZero = 4465, + CapabilitySignedZeroInfNanPreserve = 4466, + CapabilityRoundingModeRTE = 4467, + CapabilityRoundingModeRTZ = 4468, + CapabilityRayQueryProvisionalKHR = 4471, + CapabilityRayTraversalPrimitiveCullingProvisionalKHR = 4478, + CapabilityFloat16ImageAMD = 5008, + CapabilityImageGatherBiasLodAMD = 5009, + CapabilityFragmentMaskAMD = 5010, + CapabilityStencilExportEXT = 5013, + CapabilityImageReadWriteLodAMD = 5015, + CapabilityShaderClockKHR = 5055, + CapabilitySampleMaskOverrideCoverageNV = 5249, + CapabilityGeometryShaderPassthroughNV = 5251, + CapabilityShaderViewportIndexLayerEXT = 5254, + CapabilityShaderViewportIndexLayerNV = 5254, + CapabilityShaderViewportMaskNV = 5255, + CapabilityShaderStereoViewNV = 5259, + CapabilityPerViewAttributesNV = 5260, + CapabilityFragmentFullyCoveredEXT = 5265, + CapabilityMeshShadingNV = 5266, + CapabilityImageFootprintNV = 5282, + CapabilityFragmentBarycentricNV = 5284, + CapabilityComputeDerivativeGroupQuadsNV = 5288, + CapabilityFragmentDensityEXT = 5291, + CapabilityShadingRateNV = 5291, + CapabilityGroupNonUniformPartitionedNV = 5297, + CapabilityShaderNonUniform = 5301, + CapabilityShaderNonUniformEXT = 5301, + CapabilityRuntimeDescriptorArray = 5302, + CapabilityRuntimeDescriptorArrayEXT = 5302, + CapabilityInputAttachmentArrayDynamicIndexing = 5303, + CapabilityInputAttachmentArrayDynamicIndexingEXT = 5303, + CapabilityUniformTexelBufferArrayDynamicIndexing = 5304, + CapabilityUniformTexelBufferArrayDynamicIndexingEXT = 5304, + CapabilityStorageTexelBufferArrayDynamicIndexing = 5305, + CapabilityStorageTexelBufferArrayDynamicIndexingEXT = 5305, + CapabilityUniformBufferArrayNonUniformIndexing = 5306, + CapabilityUniformBufferArrayNonUniformIndexingEXT = 5306, + CapabilitySampledImageArrayNonUniformIndexing = 5307, + CapabilitySampledImageArrayNonUniformIndexingEXT = 5307, + CapabilityStorageBufferArrayNonUniformIndexing = 5308, + CapabilityStorageBufferArrayNonUniformIndexingEXT = 5308, + CapabilityStorageImageArrayNonUniformIndexing = 5309, + CapabilityStorageImageArrayNonUniformIndexingEXT = 5309, + CapabilityInputAttachmentArrayNonUniformIndexing = 5310, + CapabilityInputAttachmentArrayNonUniformIndexingEXT = 5310, + CapabilityUniformTexelBufferArrayNonUniformIndexing = 5311, + CapabilityUniformTexelBufferArrayNonUniformIndexingEXT = 5311, + CapabilityStorageTexelBufferArrayNonUniformIndexing = 5312, + CapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312, + CapabilityRayTracingNV = 5340, + CapabilityVulkanMemoryModel = 5345, + CapabilityVulkanMemoryModelKHR = 5345, + CapabilityVulkanMemoryModelDeviceScope = 5346, + CapabilityVulkanMemoryModelDeviceScopeKHR = 5346, + CapabilityPhysicalStorageBufferAddresses = 5347, + CapabilityPhysicalStorageBufferAddressesEXT = 5347, + CapabilityComputeDerivativeGroupLinearNV = 5350, + CapabilityRayTracingProvisionalKHR = 5353, + CapabilityCooperativeMatrixNV = 5357, + CapabilityFragmentShaderSampleInterlockEXT = 5363, + CapabilityFragmentShaderShadingRateInterlockEXT = 5372, + CapabilityShaderSMBuiltinsNV = 5373, + CapabilityFragmentShaderPixelInterlockEXT = 5378, + CapabilityDemoteToHelperInvocationEXT = 5379, + CapabilitySubgroupShuffleINTEL = 5568, + CapabilitySubgroupBufferBlockIOINTEL = 5569, + CapabilitySubgroupImageBlockIOINTEL = 5570, + CapabilitySubgroupImageMediaBlockIOINTEL = 5579, + CapabilityIntegerFunctions2INTEL = 5584, + CapabilitySubgroupAvcMotionEstimationINTEL = 5696, + CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697, + CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698, + CapabilityMax = 0x7fffffff, +}; + +enum RayFlagsShift { + RayFlagsOpaqueKHRShift = 0, + RayFlagsNoOpaqueKHRShift = 1, + RayFlagsTerminateOnFirstHitKHRShift = 2, + RayFlagsSkipClosestHitShaderKHRShift = 3, + RayFlagsCullBackFacingTrianglesKHRShift = 4, + RayFlagsCullFrontFacingTrianglesKHRShift = 5, + RayFlagsCullOpaqueKHRShift = 6, + RayFlagsCullNoOpaqueKHRShift = 7, + RayFlagsSkipTrianglesKHRShift = 8, + RayFlagsSkipAABBsKHRShift = 9, + RayFlagsMax = 0x7fffffff, +}; + +enum RayFlagsMask { + RayFlagsMaskNone = 0, + RayFlagsOpaqueKHRMask = 0x00000001, + RayFlagsNoOpaqueKHRMask = 0x00000002, + RayFlagsTerminateOnFirstHitKHRMask = 0x00000004, + RayFlagsSkipClosestHitShaderKHRMask = 0x00000008, + RayFlagsCullBackFacingTrianglesKHRMask = 0x00000010, + RayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020, + RayFlagsCullOpaqueKHRMask = 0x00000040, + RayFlagsCullNoOpaqueKHRMask = 0x00000080, + RayFlagsSkipTrianglesKHRMask = 0x00000100, + RayFlagsSkipAABBsKHRMask = 0x00000200, +}; + +enum RayQueryIntersection { + RayQueryIntersectionRayQueryCandidateIntersectionKHR = 0, + RayQueryIntersectionRayQueryCommittedIntersectionKHR = 1, + RayQueryIntersectionMax = 0x7fffffff, +}; + +enum RayQueryCommittedIntersectionType { + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR = 0, + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR = 1, + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR = 2, + RayQueryCommittedIntersectionTypeMax = 0x7fffffff, +}; + +enum RayQueryCandidateIntersectionType { + RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR = 0, + RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR = 1, + RayQueryCandidateIntersectionTypeMax = 0x7fffffff, +}; + +enum Op { + OpNop = 0, + OpUndef = 1, + OpSourceContinued = 2, + OpSource = 3, + OpSourceExtension = 4, + OpName = 5, + OpMemberName = 6, + OpString = 7, + OpLine = 8, + OpExtension = 10, + OpExtInstImport = 11, + OpExtInst = 12, + OpMemoryModel = 14, + OpEntryPoint = 15, + OpExecutionMode = 16, + OpCapability = 17, + OpTypeVoid = 19, + OpTypeBool = 20, + OpTypeInt = 21, + OpTypeFloat = 22, + OpTypeVector = 23, + OpTypeMatrix = 24, + OpTypeImage = 25, + OpTypeSampler = 26, + OpTypeSampledImage = 27, + OpTypeArray = 28, + OpTypeRuntimeArray = 29, + OpTypeStruct = 30, + OpTypeOpaque = 31, + OpTypePointer = 32, + OpTypeFunction = 33, + OpTypeEvent = 34, + OpTypeDeviceEvent = 35, + OpTypeReserveId = 36, + OpTypeQueue = 37, + OpTypePipe = 38, + OpTypeForwardPointer = 39, + OpConstantTrue = 41, + OpConstantFalse = 42, + OpConstant = 43, + OpConstantComposite = 44, + OpConstantSampler = 45, + OpConstantNull = 46, + OpSpecConstantTrue = 48, + OpSpecConstantFalse = 49, + OpSpecConstant = 50, + OpSpecConstantComposite = 51, + OpSpecConstantOp = 52, + OpFunction = 54, + OpFunctionParameter = 55, + OpFunctionEnd = 56, + OpFunctionCall = 57, + OpVariable = 59, + OpImageTexelPointer = 60, + OpLoad = 61, + OpStore = 62, + OpCopyMemory = 63, + OpCopyMemorySized = 64, + OpAccessChain = 65, + OpInBoundsAccessChain = 66, + OpPtrAccessChain = 67, + OpArrayLength = 68, + OpGenericPtrMemSemantics = 69, + OpInBoundsPtrAccessChain = 70, + OpDecorate = 71, + OpMemberDecorate = 72, + OpDecorationGroup = 73, + OpGroupDecorate = 74, + OpGroupMemberDecorate = 75, + OpVectorExtractDynamic = 77, + OpVectorInsertDynamic = 78, + OpVectorShuffle = 79, + OpCompositeConstruct = 80, + OpCompositeExtract = 81, + OpCompositeInsert = 82, + OpCopyObject = 83, + OpTranspose = 84, + OpSampledImage = 86, + OpImageSampleImplicitLod = 87, + OpImageSampleExplicitLod = 88, + OpImageSampleDrefImplicitLod = 89, + OpImageSampleDrefExplicitLod = 90, + OpImageSampleProjImplicitLod = 91, + OpImageSampleProjExplicitLod = 92, + OpImageSampleProjDrefImplicitLod = 93, + OpImageSampleProjDrefExplicitLod = 94, + OpImageFetch = 95, + OpImageGather = 96, + OpImageDrefGather = 97, + OpImageRead = 98, + OpImageWrite = 99, + OpImage = 100, + OpImageQueryFormat = 101, + OpImageQueryOrder = 102, + OpImageQuerySizeLod = 103, + OpImageQuerySize = 104, + OpImageQueryLod = 105, + OpImageQueryLevels = 106, + OpImageQuerySamples = 107, + OpConvertFToU = 109, + OpConvertFToS = 110, + OpConvertSToF = 111, + OpConvertUToF = 112, + OpUConvert = 113, + OpSConvert = 114, + OpFConvert = 115, + OpQuantizeToF16 = 116, + OpConvertPtrToU = 117, + OpSatConvertSToU = 118, + OpSatConvertUToS = 119, + OpConvertUToPtr = 120, + OpPtrCastToGeneric = 121, + OpGenericCastToPtr = 122, + OpGenericCastToPtrExplicit = 123, + OpBitcast = 124, + OpSNegate = 126, + OpFNegate = 127, + OpIAdd = 128, + OpFAdd = 129, + OpISub = 130, + OpFSub = 131, + OpIMul = 132, + OpFMul = 133, + OpUDiv = 134, + OpSDiv = 135, + OpFDiv = 136, + OpUMod = 137, + OpSRem = 138, + OpSMod = 139, + OpFRem = 140, + OpFMod = 141, + OpVectorTimesScalar = 142, + OpMatrixTimesScalar = 143, + OpVectorTimesMatrix = 144, + OpMatrixTimesVector = 145, + OpMatrixTimesMatrix = 146, + OpOuterProduct = 147, + OpDot = 148, + OpIAddCarry = 149, + OpISubBorrow = 150, + OpUMulExtended = 151, + OpSMulExtended = 152, + OpAny = 154, + OpAll = 155, + OpIsNan = 156, + OpIsInf = 157, + OpIsFinite = 158, + OpIsNormal = 159, + OpSignBitSet = 160, + OpLessOrGreater = 161, + OpOrdered = 162, + OpUnordered = 163, + OpLogicalEqual = 164, + OpLogicalNotEqual = 165, + OpLogicalOr = 166, + OpLogicalAnd = 167, + OpLogicalNot = 168, + OpSelect = 169, + OpIEqual = 170, + OpINotEqual = 171, + OpUGreaterThan = 172, + OpSGreaterThan = 173, + OpUGreaterThanEqual = 174, + OpSGreaterThanEqual = 175, + OpULessThan = 176, + OpSLessThan = 177, + OpULessThanEqual = 178, + OpSLessThanEqual = 179, + OpFOrdEqual = 180, + OpFUnordEqual = 181, + OpFOrdNotEqual = 182, + OpFUnordNotEqual = 183, + OpFOrdLessThan = 184, + OpFUnordLessThan = 185, + OpFOrdGreaterThan = 186, + OpFUnordGreaterThan = 187, + OpFOrdLessThanEqual = 188, + OpFUnordLessThanEqual = 189, + OpFOrdGreaterThanEqual = 190, + OpFUnordGreaterThanEqual = 191, + OpShiftRightLogical = 194, + OpShiftRightArithmetic = 195, + OpShiftLeftLogical = 196, + OpBitwiseOr = 197, + OpBitwiseXor = 198, + OpBitwiseAnd = 199, + OpNot = 200, + OpBitFieldInsert = 201, + OpBitFieldSExtract = 202, + OpBitFieldUExtract = 203, + OpBitReverse = 204, + OpBitCount = 205, + OpDPdx = 207, + OpDPdy = 208, + OpFwidth = 209, + OpDPdxFine = 210, + OpDPdyFine = 211, + OpFwidthFine = 212, + OpDPdxCoarse = 213, + OpDPdyCoarse = 214, + OpFwidthCoarse = 215, + OpEmitVertex = 218, + OpEndPrimitive = 219, + OpEmitStreamVertex = 220, + OpEndStreamPrimitive = 221, + OpControlBarrier = 224, + OpMemoryBarrier = 225, + OpAtomicLoad = 227, + OpAtomicStore = 228, + OpAtomicExchange = 229, + OpAtomicCompareExchange = 230, + OpAtomicCompareExchangeWeak = 231, + OpAtomicIIncrement = 232, + OpAtomicIDecrement = 233, + OpAtomicIAdd = 234, + OpAtomicISub = 235, + OpAtomicSMin = 236, + OpAtomicUMin = 237, + OpAtomicSMax = 238, + OpAtomicUMax = 239, + OpAtomicAnd = 240, + OpAtomicOr = 241, + OpAtomicXor = 242, + OpPhi = 245, + OpLoopMerge = 246, + OpSelectionMerge = 247, + OpLabel = 248, + OpBranch = 249, + OpBranchConditional = 250, + OpSwitch = 251, + OpKill = 252, + OpReturn = 253, + OpReturnValue = 254, + OpUnreachable = 255, + OpLifetimeStart = 256, + OpLifetimeStop = 257, + OpGroupAsyncCopy = 259, + OpGroupWaitEvents = 260, + OpGroupAll = 261, + OpGroupAny = 262, + OpGroupBroadcast = 263, + OpGroupIAdd = 264, + OpGroupFAdd = 265, + OpGroupFMin = 266, + OpGroupUMin = 267, + OpGroupSMin = 268, + OpGroupFMax = 269, + OpGroupUMax = 270, + OpGroupSMax = 271, + OpReadPipe = 274, + OpWritePipe = 275, + OpReservedReadPipe = 276, + OpReservedWritePipe = 277, + OpReserveReadPipePackets = 278, + OpReserveWritePipePackets = 279, + OpCommitReadPipe = 280, + OpCommitWritePipe = 281, + OpIsValidReserveId = 282, + OpGetNumPipePackets = 283, + OpGetMaxPipePackets = 284, + OpGroupReserveReadPipePackets = 285, + OpGroupReserveWritePipePackets = 286, + OpGroupCommitReadPipe = 287, + OpGroupCommitWritePipe = 288, + OpEnqueueMarker = 291, + OpEnqueueKernel = 292, + OpGetKernelNDrangeSubGroupCount = 293, + OpGetKernelNDrangeMaxSubGroupSize = 294, + OpGetKernelWorkGroupSize = 295, + OpGetKernelPreferredWorkGroupSizeMultiple = 296, + OpRetainEvent = 297, + OpReleaseEvent = 298, + OpCreateUserEvent = 299, + OpIsValidEvent = 300, + OpSetUserEventStatus = 301, + OpCaptureEventProfilingInfo = 302, + OpGetDefaultQueue = 303, + OpBuildNDRange = 304, + OpImageSparseSampleImplicitLod = 305, + OpImageSparseSampleExplicitLod = 306, + OpImageSparseSampleDrefImplicitLod = 307, + OpImageSparseSampleDrefExplicitLod = 308, + OpImageSparseSampleProjImplicitLod = 309, + OpImageSparseSampleProjExplicitLod = 310, + OpImageSparseSampleProjDrefImplicitLod = 311, + OpImageSparseSampleProjDrefExplicitLod = 312, + OpImageSparseFetch = 313, + OpImageSparseGather = 314, + OpImageSparseDrefGather = 315, + OpImageSparseTexelsResident = 316, + OpNoLine = 317, + OpAtomicFlagTestAndSet = 318, + OpAtomicFlagClear = 319, + OpImageSparseRead = 320, + OpSizeOf = 321, + OpTypePipeStorage = 322, + OpConstantPipeStorage = 323, + OpCreatePipeFromPipeStorage = 324, + OpGetKernelLocalSizeForSubgroupCount = 325, + OpGetKernelMaxNumSubgroups = 326, + OpTypeNamedBarrier = 327, + OpNamedBarrierInitialize = 328, + OpMemoryNamedBarrier = 329, + OpModuleProcessed = 330, + OpExecutionModeId = 331, + OpDecorateId = 332, + OpGroupNonUniformElect = 333, + OpGroupNonUniformAll = 334, + OpGroupNonUniformAny = 335, + OpGroupNonUniformAllEqual = 336, + OpGroupNonUniformBroadcast = 337, + OpGroupNonUniformBroadcastFirst = 338, + OpGroupNonUniformBallot = 339, + OpGroupNonUniformInverseBallot = 340, + OpGroupNonUniformBallotBitExtract = 341, + OpGroupNonUniformBallotBitCount = 342, + OpGroupNonUniformBallotFindLSB = 343, + OpGroupNonUniformBallotFindMSB = 344, + OpGroupNonUniformShuffle = 345, + OpGroupNonUniformShuffleXor = 346, + OpGroupNonUniformShuffleUp = 347, + OpGroupNonUniformShuffleDown = 348, + OpGroupNonUniformIAdd = 349, + OpGroupNonUniformFAdd = 350, + OpGroupNonUniformIMul = 351, + OpGroupNonUniformFMul = 352, + OpGroupNonUniformSMin = 353, + OpGroupNonUniformUMin = 354, + OpGroupNonUniformFMin = 355, + OpGroupNonUniformSMax = 356, + OpGroupNonUniformUMax = 357, + OpGroupNonUniformFMax = 358, + OpGroupNonUniformBitwiseAnd = 359, + OpGroupNonUniformBitwiseOr = 360, + OpGroupNonUniformBitwiseXor = 361, + OpGroupNonUniformLogicalAnd = 362, + OpGroupNonUniformLogicalOr = 363, + OpGroupNonUniformLogicalXor = 364, + OpGroupNonUniformQuadBroadcast = 365, + OpGroupNonUniformQuadSwap = 366, + OpCopyLogical = 400, + OpPtrEqual = 401, + OpPtrNotEqual = 402, + OpPtrDiff = 403, + OpSubgroupBallotKHR = 4421, + OpSubgroupFirstInvocationKHR = 4422, + OpSubgroupAllKHR = 4428, + OpSubgroupAnyKHR = 4429, + OpSubgroupAllEqualKHR = 4430, + OpSubgroupReadInvocationKHR = 4432, + OpTypeRayQueryProvisionalKHR = 4472, + OpRayQueryInitializeKHR = 4473, + OpRayQueryTerminateKHR = 4474, + OpRayQueryGenerateIntersectionKHR = 4475, + OpRayQueryConfirmIntersectionKHR = 4476, + OpRayQueryProceedKHR = 4477, + OpRayQueryGetIntersectionTypeKHR = 4479, + OpGroupIAddNonUniformAMD = 5000, + OpGroupFAddNonUniformAMD = 5001, + OpGroupFMinNonUniformAMD = 5002, + OpGroupUMinNonUniformAMD = 5003, + OpGroupSMinNonUniformAMD = 5004, + OpGroupFMaxNonUniformAMD = 5005, + OpGroupUMaxNonUniformAMD = 5006, + OpGroupSMaxNonUniformAMD = 5007, + OpFragmentMaskFetchAMD = 5011, + OpFragmentFetchAMD = 5012, + OpReadClockKHR = 5056, + OpImageSampleFootprintNV = 5283, + OpGroupNonUniformPartitionNV = 5296, + OpWritePackedPrimitiveIndices4x8NV = 5299, + OpReportIntersectionKHR = 5334, + OpReportIntersectionNV = 5334, + OpIgnoreIntersectionKHR = 5335, + OpIgnoreIntersectionNV = 5335, + OpTerminateRayKHR = 5336, + OpTerminateRayNV = 5336, + OpTraceNV = 5337, + OpTraceRayKHR = 5337, + OpTypeAccelerationStructureKHR = 5341, + OpTypeAccelerationStructureNV = 5341, + OpExecuteCallableKHR = 5344, + OpExecuteCallableNV = 5344, + OpTypeCooperativeMatrixNV = 5358, + OpCooperativeMatrixLoadNV = 5359, + OpCooperativeMatrixStoreNV = 5360, + OpCooperativeMatrixMulAddNV = 5361, + OpCooperativeMatrixLengthNV = 5362, + OpBeginInvocationInterlockEXT = 5364, + OpEndInvocationInterlockEXT = 5365, + OpDemoteToHelperInvocationEXT = 5380, + OpIsHelperInvocationEXT = 5381, + OpSubgroupShuffleINTEL = 5571, + OpSubgroupShuffleDownINTEL = 5572, + OpSubgroupShuffleUpINTEL = 5573, + OpSubgroupShuffleXorINTEL = 5574, + OpSubgroupBlockReadINTEL = 5575, + OpSubgroupBlockWriteINTEL = 5576, + OpSubgroupImageBlockReadINTEL = 5577, + OpSubgroupImageBlockWriteINTEL = 5578, + OpSubgroupImageMediaBlockReadINTEL = 5580, + OpSubgroupImageMediaBlockWriteINTEL = 5581, + OpUCountLeadingZerosINTEL = 5585, + OpUCountTrailingZerosINTEL = 5586, + OpAbsISubINTEL = 5587, + OpAbsUSubINTEL = 5588, + OpIAddSatINTEL = 5589, + OpUAddSatINTEL = 5590, + OpIAverageINTEL = 5591, + OpUAverageINTEL = 5592, + OpIAverageRoundedINTEL = 5593, + OpUAverageRoundedINTEL = 5594, + OpISubSatINTEL = 5595, + OpUSubSatINTEL = 5596, + OpIMul32x16INTEL = 5597, + OpUMul32x16INTEL = 5598, + OpDecorateString = 5632, + OpDecorateStringGOOGLE = 5632, + OpMemberDecorateString = 5633, + OpMemberDecorateStringGOOGLE = 5633, + OpVmeImageINTEL = 5699, + OpTypeVmeImageINTEL = 5700, + OpTypeAvcImePayloadINTEL = 5701, + OpTypeAvcRefPayloadINTEL = 5702, + OpTypeAvcSicPayloadINTEL = 5703, + OpTypeAvcMcePayloadINTEL = 5704, + OpTypeAvcMceResultINTEL = 5705, + OpTypeAvcImeResultINTEL = 5706, + OpTypeAvcImeResultSingleReferenceStreamoutINTEL = 5707, + OpTypeAvcImeResultDualReferenceStreamoutINTEL = 5708, + OpTypeAvcImeSingleReferenceStreaminINTEL = 5709, + OpTypeAvcImeDualReferenceStreaminINTEL = 5710, + OpTypeAvcRefResultINTEL = 5711, + OpTypeAvcSicResultINTEL = 5712, + OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL = 5713, + OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL = 5714, + OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL = 5715, + OpSubgroupAvcMceSetInterShapePenaltyINTEL = 5716, + OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL = 5717, + OpSubgroupAvcMceSetInterDirectionPenaltyINTEL = 5718, + OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL = 5719, + OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL = 5720, + OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL = 5721, + OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL = 5722, + OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL = 5723, + OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL = 5724, + OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL = 5725, + OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL = 5726, + OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL = 5727, + OpSubgroupAvcMceSetAcOnlyHaarINTEL = 5728, + OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL = 5729, + OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL = 5730, + OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL = 5731, + OpSubgroupAvcMceConvertToImePayloadINTEL = 5732, + OpSubgroupAvcMceConvertToImeResultINTEL = 5733, + OpSubgroupAvcMceConvertToRefPayloadINTEL = 5734, + OpSubgroupAvcMceConvertToRefResultINTEL = 5735, + OpSubgroupAvcMceConvertToSicPayloadINTEL = 5736, + OpSubgroupAvcMceConvertToSicResultINTEL = 5737, + OpSubgroupAvcMceGetMotionVectorsINTEL = 5738, + OpSubgroupAvcMceGetInterDistortionsINTEL = 5739, + OpSubgroupAvcMceGetBestInterDistortionsINTEL = 5740, + OpSubgroupAvcMceGetInterMajorShapeINTEL = 5741, + OpSubgroupAvcMceGetInterMinorShapeINTEL = 5742, + OpSubgroupAvcMceGetInterDirectionsINTEL = 5743, + OpSubgroupAvcMceGetInterMotionVectorCountINTEL = 5744, + OpSubgroupAvcMceGetInterReferenceIdsINTEL = 5745, + OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL = 5746, + OpSubgroupAvcImeInitializeINTEL = 5747, + OpSubgroupAvcImeSetSingleReferenceINTEL = 5748, + OpSubgroupAvcImeSetDualReferenceINTEL = 5749, + OpSubgroupAvcImeRefWindowSizeINTEL = 5750, + OpSubgroupAvcImeAdjustRefOffsetINTEL = 5751, + OpSubgroupAvcImeConvertToMcePayloadINTEL = 5752, + OpSubgroupAvcImeSetMaxMotionVectorCountINTEL = 5753, + OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL = 5754, + OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL = 5755, + OpSubgroupAvcImeSetWeightedSadINTEL = 5756, + OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL = 5757, + OpSubgroupAvcImeEvaluateWithDualReferenceINTEL = 5758, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL = 5759, + OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL = 5760, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL = 5761, + OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL = 5762, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL = 5763, + OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL = 5764, + OpSubgroupAvcImeConvertToMceResultINTEL = 5765, + OpSubgroupAvcImeGetSingleReferenceStreaminINTEL = 5766, + OpSubgroupAvcImeGetDualReferenceStreaminINTEL = 5767, + OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL = 5768, + OpSubgroupAvcImeStripDualReferenceStreamoutINTEL = 5769, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL = 5770, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL = 5771, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL = 5772, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL = 5773, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL = 5774, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL = 5775, + OpSubgroupAvcImeGetBorderReachedINTEL = 5776, + OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL = 5777, + OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL = 5778, + OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL = 5779, + OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL = 5780, + OpSubgroupAvcFmeInitializeINTEL = 5781, + OpSubgroupAvcBmeInitializeINTEL = 5782, + OpSubgroupAvcRefConvertToMcePayloadINTEL = 5783, + OpSubgroupAvcRefSetBidirectionalMixDisableINTEL = 5784, + OpSubgroupAvcRefSetBilinearFilterEnableINTEL = 5785, + OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL = 5786, + OpSubgroupAvcRefEvaluateWithDualReferenceINTEL = 5787, + OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL = 5788, + OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL = 5789, + OpSubgroupAvcRefConvertToMceResultINTEL = 5790, + OpSubgroupAvcSicInitializeINTEL = 5791, + OpSubgroupAvcSicConfigureSkcINTEL = 5792, + OpSubgroupAvcSicConfigureIpeLumaINTEL = 5793, + OpSubgroupAvcSicConfigureIpeLumaChromaINTEL = 5794, + OpSubgroupAvcSicGetMotionVectorMaskINTEL = 5795, + OpSubgroupAvcSicConvertToMcePayloadINTEL = 5796, + OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL = 5797, + OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL = 5798, + OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL = 5799, + OpSubgroupAvcSicSetBilinearFilterEnableINTEL = 5800, + OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL = 5801, + OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL = 5802, + OpSubgroupAvcSicEvaluateIpeINTEL = 5803, + OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL = 5804, + OpSubgroupAvcSicEvaluateWithDualReferenceINTEL = 5805, + OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL = 5806, + OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL = 5807, + OpSubgroupAvcSicConvertToMceResultINTEL = 5808, + OpSubgroupAvcSicGetIpeLumaShapeINTEL = 5809, + OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL = 5810, + OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL = 5811, + OpSubgroupAvcSicGetPackedIpeLumaModesINTEL = 5812, + OpSubgroupAvcSicGetIpeChromaModeINTEL = 5813, + OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, + OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, + OpSubgroupAvcSicGetInterRawSadsINTEL = 5816, + OpRayQueryGetRayTMinKHR = 6016, + OpRayQueryGetRayFlagsKHR = 6017, + OpRayQueryGetIntersectionTKHR = 6018, + OpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019, + OpRayQueryGetIntersectionInstanceIdKHR = 6020, + OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021, + OpRayQueryGetIntersectionGeometryIndexKHR = 6022, + OpRayQueryGetIntersectionPrimitiveIndexKHR = 6023, + OpRayQueryGetIntersectionBarycentricsKHR = 6024, + OpRayQueryGetIntersectionFrontFaceKHR = 6025, + OpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026, + OpRayQueryGetIntersectionObjectRayDirectionKHR = 6027, + OpRayQueryGetIntersectionObjectRayOriginKHR = 6028, + OpRayQueryGetWorldRayDirectionKHR = 6029, + OpRayQueryGetWorldRayOriginKHR = 6030, + OpRayQueryGetIntersectionObjectToWorldKHR = 6031, + OpRayQueryGetIntersectionWorldToObjectKHR = 6032, + OpMax = 0x7fffffff, +}; + +#ifdef SPV_ENABLE_UTILITY_CODE +inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) { + *hasResult = *hasResultType = false; + switch (opcode) { + default: /* unknown opcode */ break; + case OpNop: *hasResult = false; *hasResultType = false; break; + case OpUndef: *hasResult = true; *hasResultType = true; break; + case OpSourceContinued: *hasResult = false; *hasResultType = false; break; + case OpSource: *hasResult = false; *hasResultType = false; break; + case OpSourceExtension: *hasResult = false; *hasResultType = false; break; + case OpName: *hasResult = false; *hasResultType = false; break; + case OpMemberName: *hasResult = false; *hasResultType = false; break; + case OpString: *hasResult = true; *hasResultType = false; break; + case OpLine: *hasResult = false; *hasResultType = false; break; + case OpExtension: *hasResult = false; *hasResultType = false; break; + case OpExtInstImport: *hasResult = true; *hasResultType = false; break; + case OpExtInst: *hasResult = true; *hasResultType = true; break; + case OpMemoryModel: *hasResult = false; *hasResultType = false; break; + case OpEntryPoint: *hasResult = false; *hasResultType = false; break; + case OpExecutionMode: *hasResult = false; *hasResultType = false; break; + case OpCapability: *hasResult = false; *hasResultType = false; break; + case OpTypeVoid: *hasResult = true; *hasResultType = false; break; + case OpTypeBool: *hasResult = true; *hasResultType = false; break; + case OpTypeInt: *hasResult = true; *hasResultType = false; break; + case OpTypeFloat: *hasResult = true; *hasResultType = false; break; + case OpTypeVector: *hasResult = true; *hasResultType = false; break; + case OpTypeMatrix: *hasResult = true; *hasResultType = false; break; + case OpTypeImage: *hasResult = true; *hasResultType = false; break; + case OpTypeSampler: *hasResult = true; *hasResultType = false; break; + case OpTypeSampledImage: *hasResult = true; *hasResultType = false; break; + case OpTypeArray: *hasResult = true; *hasResultType = false; break; + case OpTypeRuntimeArray: *hasResult = true; *hasResultType = false; break; + case OpTypeStruct: *hasResult = true; *hasResultType = false; break; + case OpTypeOpaque: *hasResult = true; *hasResultType = false; break; + case OpTypePointer: *hasResult = true; *hasResultType = false; break; + case OpTypeFunction: *hasResult = true; *hasResultType = false; break; + case OpTypeEvent: *hasResult = true; *hasResultType = false; break; + case OpTypeDeviceEvent: *hasResult = true; *hasResultType = false; break; + case OpTypeReserveId: *hasResult = true; *hasResultType = false; break; + case OpTypeQueue: *hasResult = true; *hasResultType = false; break; + case OpTypePipe: *hasResult = true; *hasResultType = false; break; + case OpTypeForwardPointer: *hasResult = false; *hasResultType = false; break; + case OpConstantTrue: *hasResult = true; *hasResultType = true; break; + case OpConstantFalse: *hasResult = true; *hasResultType = true; break; + case OpConstant: *hasResult = true; *hasResultType = true; break; + case OpConstantComposite: *hasResult = true; *hasResultType = true; break; + case OpConstantSampler: *hasResult = true; *hasResultType = true; break; + case OpConstantNull: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantTrue: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantFalse: *hasResult = true; *hasResultType = true; break; + case OpSpecConstant: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantComposite: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantOp: *hasResult = true; *hasResultType = true; break; + case OpFunction: *hasResult = true; *hasResultType = true; break; + case OpFunctionParameter: *hasResult = true; *hasResultType = true; break; + case OpFunctionEnd: *hasResult = false; *hasResultType = false; break; + case OpFunctionCall: *hasResult = true; *hasResultType = true; break; + case OpVariable: *hasResult = true; *hasResultType = true; break; + case OpImageTexelPointer: *hasResult = true; *hasResultType = true; break; + case OpLoad: *hasResult = true; *hasResultType = true; break; + case OpStore: *hasResult = false; *hasResultType = false; break; + case OpCopyMemory: *hasResult = false; *hasResultType = false; break; + case OpCopyMemorySized: *hasResult = false; *hasResultType = false; break; + case OpAccessChain: *hasResult = true; *hasResultType = true; break; + case OpInBoundsAccessChain: *hasResult = true; *hasResultType = true; break; + case OpPtrAccessChain: *hasResult = true; *hasResultType = true; break; + case OpArrayLength: *hasResult = true; *hasResultType = true; break; + case OpGenericPtrMemSemantics: *hasResult = true; *hasResultType = true; break; + case OpInBoundsPtrAccessChain: *hasResult = true; *hasResultType = true; break; + case OpDecorate: *hasResult = false; *hasResultType = false; break; + case OpMemberDecorate: *hasResult = false; *hasResultType = false; break; + case OpDecorationGroup: *hasResult = true; *hasResultType = false; break; + case OpGroupDecorate: *hasResult = false; *hasResultType = false; break; + case OpGroupMemberDecorate: *hasResult = false; *hasResultType = false; break; + case OpVectorExtractDynamic: *hasResult = true; *hasResultType = true; break; + case OpVectorInsertDynamic: *hasResult = true; *hasResultType = true; break; + case OpVectorShuffle: *hasResult = true; *hasResultType = true; break; + case OpCompositeConstruct: *hasResult = true; *hasResultType = true; break; + case OpCompositeExtract: *hasResult = true; *hasResultType = true; break; + case OpCompositeInsert: *hasResult = true; *hasResultType = true; break; + case OpCopyObject: *hasResult = true; *hasResultType = true; break; + case OpTranspose: *hasResult = true; *hasResultType = true; break; + case OpSampledImage: *hasResult = true; *hasResultType = true; break; + case OpImageSampleImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageFetch: *hasResult = true; *hasResultType = true; break; + case OpImageGather: *hasResult = true; *hasResultType = true; break; + case OpImageDrefGather: *hasResult = true; *hasResultType = true; break; + case OpImageRead: *hasResult = true; *hasResultType = true; break; + case OpImageWrite: *hasResult = false; *hasResultType = false; break; + case OpImage: *hasResult = true; *hasResultType = true; break; + case OpImageQueryFormat: *hasResult = true; *hasResultType = true; break; + case OpImageQueryOrder: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySizeLod: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySize: *hasResult = true; *hasResultType = true; break; + case OpImageQueryLod: *hasResult = true; *hasResultType = true; break; + case OpImageQueryLevels: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySamples: *hasResult = true; *hasResultType = true; break; + case OpConvertFToU: *hasResult = true; *hasResultType = true; break; + case OpConvertFToS: *hasResult = true; *hasResultType = true; break; + case OpConvertSToF: *hasResult = true; *hasResultType = true; break; + case OpConvertUToF: *hasResult = true; *hasResultType = true; break; + case OpUConvert: *hasResult = true; *hasResultType = true; break; + case OpSConvert: *hasResult = true; *hasResultType = true; break; + case OpFConvert: *hasResult = true; *hasResultType = true; break; + case OpQuantizeToF16: *hasResult = true; *hasResultType = true; break; + case OpConvertPtrToU: *hasResult = true; *hasResultType = true; break; + case OpSatConvertSToU: *hasResult = true; *hasResultType = true; break; + case OpSatConvertUToS: *hasResult = true; *hasResultType = true; break; + case OpConvertUToPtr: *hasResult = true; *hasResultType = true; break; + case OpPtrCastToGeneric: *hasResult = true; *hasResultType = true; break; + case OpGenericCastToPtr: *hasResult = true; *hasResultType = true; break; + case OpGenericCastToPtrExplicit: *hasResult = true; *hasResultType = true; break; + case OpBitcast: *hasResult = true; *hasResultType = true; break; + case OpSNegate: *hasResult = true; *hasResultType = true; break; + case OpFNegate: *hasResult = true; *hasResultType = true; break; + case OpIAdd: *hasResult = true; *hasResultType = true; break; + case OpFAdd: *hasResult = true; *hasResultType = true; break; + case OpISub: *hasResult = true; *hasResultType = true; break; + case OpFSub: *hasResult = true; *hasResultType = true; break; + case OpIMul: *hasResult = true; *hasResultType = true; break; + case OpFMul: *hasResult = true; *hasResultType = true; break; + case OpUDiv: *hasResult = true; *hasResultType = true; break; + case OpSDiv: *hasResult = true; *hasResultType = true; break; + case OpFDiv: *hasResult = true; *hasResultType = true; break; + case OpUMod: *hasResult = true; *hasResultType = true; break; + case OpSRem: *hasResult = true; *hasResultType = true; break; + case OpSMod: *hasResult = true; *hasResultType = true; break; + case OpFRem: *hasResult = true; *hasResultType = true; break; + case OpFMod: *hasResult = true; *hasResultType = true; break; + case OpVectorTimesScalar: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesScalar: *hasResult = true; *hasResultType = true; break; + case OpVectorTimesMatrix: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesVector: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesMatrix: *hasResult = true; *hasResultType = true; break; + case OpOuterProduct: *hasResult = true; *hasResultType = true; break; + case OpDot: *hasResult = true; *hasResultType = true; break; + case OpIAddCarry: *hasResult = true; *hasResultType = true; break; + case OpISubBorrow: *hasResult = true; *hasResultType = true; break; + case OpUMulExtended: *hasResult = true; *hasResultType = true; break; + case OpSMulExtended: *hasResult = true; *hasResultType = true; break; + case OpAny: *hasResult = true; *hasResultType = true; break; + case OpAll: *hasResult = true; *hasResultType = true; break; + case OpIsNan: *hasResult = true; *hasResultType = true; break; + case OpIsInf: *hasResult = true; *hasResultType = true; break; + case OpIsFinite: *hasResult = true; *hasResultType = true; break; + case OpIsNormal: *hasResult = true; *hasResultType = true; break; + case OpSignBitSet: *hasResult = true; *hasResultType = true; break; + case OpLessOrGreater: *hasResult = true; *hasResultType = true; break; + case OpOrdered: *hasResult = true; *hasResultType = true; break; + case OpUnordered: *hasResult = true; *hasResultType = true; break; + case OpLogicalEqual: *hasResult = true; *hasResultType = true; break; + case OpLogicalNotEqual: *hasResult = true; *hasResultType = true; break; + case OpLogicalOr: *hasResult = true; *hasResultType = true; break; + case OpLogicalAnd: *hasResult = true; *hasResultType = true; break; + case OpLogicalNot: *hasResult = true; *hasResultType = true; break; + case OpSelect: *hasResult = true; *hasResultType = true; break; + case OpIEqual: *hasResult = true; *hasResultType = true; break; + case OpINotEqual: *hasResult = true; *hasResultType = true; break; + case OpUGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpSGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpUGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpSGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpULessThan: *hasResult = true; *hasResultType = true; break; + case OpSLessThan: *hasResult = true; *hasResultType = true; break; + case OpULessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpSLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdNotEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordNotEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdLessThan: *hasResult = true; *hasResultType = true; break; + case OpFUnordLessThan: *hasResult = true; *hasResultType = true; break; + case OpFOrdGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpFUnordGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpFOrdLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpShiftRightLogical: *hasResult = true; *hasResultType = true; break; + case OpShiftRightArithmetic: *hasResult = true; *hasResultType = true; break; + case OpShiftLeftLogical: *hasResult = true; *hasResultType = true; break; + case OpBitwiseOr: *hasResult = true; *hasResultType = true; break; + case OpBitwiseXor: *hasResult = true; *hasResultType = true; break; + case OpBitwiseAnd: *hasResult = true; *hasResultType = true; break; + case OpNot: *hasResult = true; *hasResultType = true; break; + case OpBitFieldInsert: *hasResult = true; *hasResultType = true; break; + case OpBitFieldSExtract: *hasResult = true; *hasResultType = true; break; + case OpBitFieldUExtract: *hasResult = true; *hasResultType = true; break; + case OpBitReverse: *hasResult = true; *hasResultType = true; break; + case OpBitCount: *hasResult = true; *hasResultType = true; break; + case OpDPdx: *hasResult = true; *hasResultType = true; break; + case OpDPdy: *hasResult = true; *hasResultType = true; break; + case OpFwidth: *hasResult = true; *hasResultType = true; break; + case OpDPdxFine: *hasResult = true; *hasResultType = true; break; + case OpDPdyFine: *hasResult = true; *hasResultType = true; break; + case OpFwidthFine: *hasResult = true; *hasResultType = true; break; + case OpDPdxCoarse: *hasResult = true; *hasResultType = true; break; + case OpDPdyCoarse: *hasResult = true; *hasResultType = true; break; + case OpFwidthCoarse: *hasResult = true; *hasResultType = true; break; + case OpEmitVertex: *hasResult = false; *hasResultType = false; break; + case OpEndPrimitive: *hasResult = false; *hasResultType = false; break; + case OpEmitStreamVertex: *hasResult = false; *hasResultType = false; break; + case OpEndStreamPrimitive: *hasResult = false; *hasResultType = false; break; + case OpControlBarrier: *hasResult = false; *hasResultType = false; break; + case OpMemoryBarrier: *hasResult = false; *hasResultType = false; break; + case OpAtomicLoad: *hasResult = true; *hasResultType = true; break; + case OpAtomicStore: *hasResult = false; *hasResultType = false; break; + case OpAtomicExchange: *hasResult = true; *hasResultType = true; break; + case OpAtomicCompareExchange: *hasResult = true; *hasResultType = true; break; + case OpAtomicCompareExchangeWeak: *hasResult = true; *hasResultType = true; break; + case OpAtomicIIncrement: *hasResult = true; *hasResultType = true; break; + case OpAtomicIDecrement: *hasResult = true; *hasResultType = true; break; + case OpAtomicIAdd: *hasResult = true; *hasResultType = true; break; + case OpAtomicISub: *hasResult = true; *hasResultType = true; break; + case OpAtomicSMin: *hasResult = true; *hasResultType = true; break; + case OpAtomicUMin: *hasResult = true; *hasResultType = true; break; + case OpAtomicSMax: *hasResult = true; *hasResultType = true; break; + case OpAtomicUMax: *hasResult = true; *hasResultType = true; break; + case OpAtomicAnd: *hasResult = true; *hasResultType = true; break; + case OpAtomicOr: *hasResult = true; *hasResultType = true; break; + case OpAtomicXor: *hasResult = true; *hasResultType = true; break; + case OpPhi: *hasResult = true; *hasResultType = true; break; + case OpLoopMerge: *hasResult = false; *hasResultType = false; break; + case OpSelectionMerge: *hasResult = false; *hasResultType = false; break; + case OpLabel: *hasResult = true; *hasResultType = false; break; + case OpBranch: *hasResult = false; *hasResultType = false; break; + case OpBranchConditional: *hasResult = false; *hasResultType = false; break; + case OpSwitch: *hasResult = false; *hasResultType = false; break; + case OpKill: *hasResult = false; *hasResultType = false; break; + case OpReturn: *hasResult = false; *hasResultType = false; break; + case OpReturnValue: *hasResult = false; *hasResultType = false; break; + case OpUnreachable: *hasResult = false; *hasResultType = false; break; + case OpLifetimeStart: *hasResult = false; *hasResultType = false; break; + case OpLifetimeStop: *hasResult = false; *hasResultType = false; break; + case OpGroupAsyncCopy: *hasResult = true; *hasResultType = true; break; + case OpGroupWaitEvents: *hasResult = false; *hasResultType = false; break; + case OpGroupAll: *hasResult = true; *hasResultType = true; break; + case OpGroupAny: *hasResult = true; *hasResultType = true; break; + case OpGroupBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupIAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupFAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupFMin: *hasResult = true; *hasResultType = true; break; + case OpGroupUMin: *hasResult = true; *hasResultType = true; break; + case OpGroupSMin: *hasResult = true; *hasResultType = true; break; + case OpGroupFMax: *hasResult = true; *hasResultType = true; break; + case OpGroupUMax: *hasResult = true; *hasResultType = true; break; + case OpGroupSMax: *hasResult = true; *hasResultType = true; break; + case OpReadPipe: *hasResult = true; *hasResultType = true; break; + case OpWritePipe: *hasResult = true; *hasResultType = true; break; + case OpReservedReadPipe: *hasResult = true; *hasResultType = true; break; + case OpReservedWritePipe: *hasResult = true; *hasResultType = true; break; + case OpReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; + case OpReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; + case OpCommitReadPipe: *hasResult = false; *hasResultType = false; break; + case OpCommitWritePipe: *hasResult = false; *hasResultType = false; break; + case OpIsValidReserveId: *hasResult = true; *hasResultType = true; break; + case OpGetNumPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGetMaxPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupCommitReadPipe: *hasResult = false; *hasResultType = false; break; + case OpGroupCommitWritePipe: *hasResult = false; *hasResultType = false; break; + case OpEnqueueMarker: *hasResult = true; *hasResultType = true; break; + case OpEnqueueKernel: *hasResult = true; *hasResultType = true; break; + case OpGetKernelNDrangeSubGroupCount: *hasResult = true; *hasResultType = true; break; + case OpGetKernelNDrangeMaxSubGroupSize: *hasResult = true; *hasResultType = true; break; + case OpGetKernelWorkGroupSize: *hasResult = true; *hasResultType = true; break; + case OpGetKernelPreferredWorkGroupSizeMultiple: *hasResult = true; *hasResultType = true; break; + case OpRetainEvent: *hasResult = false; *hasResultType = false; break; + case OpReleaseEvent: *hasResult = false; *hasResultType = false; break; + case OpCreateUserEvent: *hasResult = true; *hasResultType = true; break; + case OpIsValidEvent: *hasResult = true; *hasResultType = true; break; + case OpSetUserEventStatus: *hasResult = false; *hasResultType = false; break; + case OpCaptureEventProfilingInfo: *hasResult = false; *hasResultType = false; break; + case OpGetDefaultQueue: *hasResult = true; *hasResultType = true; break; + case OpBuildNDRange: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseFetch: *hasResult = true; *hasResultType = true; break; + case OpImageSparseGather: *hasResult = true; *hasResultType = true; break; + case OpImageSparseDrefGather: *hasResult = true; *hasResultType = true; break; + case OpImageSparseTexelsResident: *hasResult = true; *hasResultType = true; break; + case OpNoLine: *hasResult = false; *hasResultType = false; break; + case OpAtomicFlagTestAndSet: *hasResult = true; *hasResultType = true; break; + case OpAtomicFlagClear: *hasResult = false; *hasResultType = false; break; + case OpImageSparseRead: *hasResult = true; *hasResultType = true; break; + case OpSizeOf: *hasResult = true; *hasResultType = true; break; + case OpTypePipeStorage: *hasResult = true; *hasResultType = false; break; + case OpConstantPipeStorage: *hasResult = true; *hasResultType = true; break; + case OpCreatePipeFromPipeStorage: *hasResult = true; *hasResultType = true; break; + case OpGetKernelLocalSizeForSubgroupCount: *hasResult = true; *hasResultType = true; break; + case OpGetKernelMaxNumSubgroups: *hasResult = true; *hasResultType = true; break; + case OpTypeNamedBarrier: *hasResult = true; *hasResultType = false; break; + case OpNamedBarrierInitialize: *hasResult = true; *hasResultType = true; break; + case OpMemoryNamedBarrier: *hasResult = false; *hasResultType = false; break; + case OpModuleProcessed: *hasResult = false; *hasResultType = false; break; + case OpExecutionModeId: *hasResult = false; *hasResultType = false; break; + case OpDecorateId: *hasResult = false; *hasResultType = false; break; + case OpGroupNonUniformElect: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAll: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAny: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAllEqual: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBroadcastFirst: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallot: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformInverseBallot: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotBitExtract: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotBitCount: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotFindLSB: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotFindMSB: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffle: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleUp: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleDown: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformIAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformIMul: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMul: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformSMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformUMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformSMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformUMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseAnd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseOr: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalAnd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalOr: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformQuadBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformQuadSwap: *hasResult = true; *hasResultType = true; break; + case OpCopyLogical: *hasResult = true; *hasResultType = true; break; + case OpPtrEqual: *hasResult = true; *hasResultType = true; break; + case OpPtrNotEqual: *hasResult = true; *hasResultType = true; break; + case OpPtrDiff: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break; + case OpTypeRayQueryProvisionalKHR: *hasResult = true; *hasResultType = false; break; + case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break; + case OpGroupIAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupUMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupSMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupUMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupSMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpFragmentMaskFetchAMD: *hasResult = true; *hasResultType = true; break; + case OpFragmentFetchAMD: *hasResult = true; *hasResultType = true; break; + case OpReadClockKHR: *hasResult = true; *hasResultType = true; break; + case OpImageSampleFootprintNV: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformPartitionNV: *hasResult = true; *hasResultType = true; break; + case OpWritePackedPrimitiveIndices4x8NV: *hasResult = false; *hasResultType = false; break; + case OpReportIntersectionNV: *hasResult = true; *hasResultType = true; break; + case OpIgnoreIntersectionNV: *hasResult = false; *hasResultType = false; break; + case OpTerminateRayNV: *hasResult = false; *hasResultType = false; break; + case OpTraceNV: *hasResult = false; *hasResultType = false; break; + case OpTypeAccelerationStructureNV: *hasResult = true; *hasResultType = false; break; + case OpExecuteCallableNV: *hasResult = false; *hasResultType = false; break; + case OpTypeCooperativeMatrixNV: *hasResult = true; *hasResultType = false; break; + case OpCooperativeMatrixLoadNV: *hasResult = true; *hasResultType = true; break; + case OpCooperativeMatrixStoreNV: *hasResult = false; *hasResultType = false; break; + case OpCooperativeMatrixMulAddNV: *hasResult = true; *hasResultType = true; break; + case OpCooperativeMatrixLengthNV: *hasResult = true; *hasResultType = true; break; + case OpBeginInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; + case OpEndInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; + case OpDemoteToHelperInvocationEXT: *hasResult = false; *hasResultType = false; break; + case OpIsHelperInvocationEXT: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleDownINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleUpINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleXorINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpSubgroupImageBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupImageBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpSubgroupImageMediaBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupImageMediaBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpUCountLeadingZerosINTEL: *hasResult = true; *hasResultType = true; break; + case OpUCountTrailingZerosINTEL: *hasResult = true; *hasResultType = true; break; + case OpAbsISubINTEL: *hasResult = true; *hasResultType = true; break; + case OpAbsUSubINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAddSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAddSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAverageINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAverageINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; + case OpISubSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break; + case OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break; + case OpDecorateString: *hasResult = false; *hasResultType = false; break; + case OpMemberDecorateString: *hasResult = false; *hasResultType = false; break; + case OpVmeImageINTEL: *hasResult = true; *hasResultType = true; break; + case OpTypeVmeImageINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImePayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcRefPayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcSicPayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcMcePayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcMceResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcRefResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcSicResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetAcOnlyHaarINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToImePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToImeResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToRefPayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToRefResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToSicPayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToSicResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetBestInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMajorShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMinorShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterDirectionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeRefWindowSizeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeAdjustRefOffsetINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetMaxMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetWeightedSadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeStripDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetBorderReachedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcFmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcBmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefSetBidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureSkcINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureIpeLumaINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureIpeLumaChromaINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetMotionVectorMaskINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateIpeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetIpeLumaShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedIpeLumaModesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetIpeChromaModeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetRayTMinKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetRayFlagsKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionTKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceCustomIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceIdKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionGeometryIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionPrimitiveIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionBarycentricsKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionFrontFaceKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetWorldRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetWorldRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break; + } +} +#endif /* SPV_ENABLE_UTILITY_CODE */ + +// Overload operator| for mask bit combining + +inline ImageOperandsMask operator|(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) | unsigned(b)); } +inline FPFastMathModeMask operator|(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) | unsigned(b)); } +inline SelectionControlMask operator|(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) | unsigned(b)); } +inline LoopControlMask operator|(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) | unsigned(b)); } +inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) | unsigned(b)); } +inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); } +inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); } +inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); } +inline RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); } + +} // end namespace spv + +#endif // #ifndef spirv_HPP + diff --git a/android/x86/include/glslang/SPIRV/spvIR.h b/android/x86/include/glslang/SPIRV/spvIR.h new file mode 100644 index 00000000..6523035e --- /dev/null +++ b/android/x86/include/glslang/SPIRV/spvIR.h @@ -0,0 +1,485 @@ +// +// Copyright (C) 2014 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// SPIRV-IR +// +// Simple in-memory representation (IR) of SPIRV. Just for holding +// Each function's CFG of blocks. Has this hierarchy: +// - Module, which is a list of +// - Function, which is a list of +// - Block, which is a list of +// - Instruction +// + +#pragma once +#ifndef spvIR_H +#define spvIR_H + +#include "spirv.hpp" + +#include +#include +#include +#include +#include +#include + +namespace spv { + +class Block; +class Function; +class Module; + +const Id NoResult = 0; +const Id NoType = 0; + +const Decoration NoPrecision = DecorationMax; + +#ifdef __GNUC__ +# define POTENTIALLY_UNUSED __attribute__((unused)) +#else +# define POTENTIALLY_UNUSED +#endif + +POTENTIALLY_UNUSED +const MemorySemanticsMask MemorySemanticsAllMemory = + (MemorySemanticsMask)(MemorySemanticsUniformMemoryMask | + MemorySemanticsWorkgroupMemoryMask | + MemorySemanticsAtomicCounterMemoryMask | + MemorySemanticsImageMemoryMask); + +struct IdImmediate { + bool isId; // true if word is an Id, false if word is an immediate + unsigned word; + IdImmediate(bool i, unsigned w) : isId(i), word(w) {} +}; + +// +// SPIR-V IR instruction. +// + +class Instruction { +public: + Instruction(Id resultId, Id typeId, Op opCode) : resultId(resultId), typeId(typeId), opCode(opCode), block(nullptr) { } + explicit Instruction(Op opCode) : resultId(NoResult), typeId(NoType), opCode(opCode), block(nullptr) { } + virtual ~Instruction() {} + void addIdOperand(Id id) { + operands.push_back(id); + idOperand.push_back(true); + } + void addImmediateOperand(unsigned int immediate) { + operands.push_back(immediate); + idOperand.push_back(false); + } + void setImmediateOperand(unsigned idx, unsigned int immediate) { + assert(!idOperand[idx]); + operands[idx] = immediate; + } + + void addStringOperand(const char* str) + { + unsigned int word; + char* wordString = (char*)&word; + char* wordPtr = wordString; + int charCount = 0; + char c; + do { + c = *(str++); + *(wordPtr++) = c; + ++charCount; + if (charCount == 4) { + addImmediateOperand(word); + wordPtr = wordString; + charCount = 0; + } + } while (c != 0); + + // deal with partial last word + if (charCount > 0) { + // pad with 0s + for (; charCount < 4; ++charCount) + *(wordPtr++) = 0; + addImmediateOperand(word); + } + } + bool isIdOperand(int op) const { return idOperand[op]; } + void setBlock(Block* b) { block = b; } + Block* getBlock() const { return block; } + Op getOpCode() const { return opCode; } + int getNumOperands() const + { + assert(operands.size() == idOperand.size()); + return (int)operands.size(); + } + Id getResultId() const { return resultId; } + Id getTypeId() const { return typeId; } + Id getIdOperand(int op) const { + assert(idOperand[op]); + return operands[op]; + } + unsigned int getImmediateOperand(int op) const { + assert(!idOperand[op]); + return operands[op]; + } + + // Write out the binary form. + void dump(std::vector& out) const + { + // Compute the wordCount + unsigned int wordCount = 1; + if (typeId) + ++wordCount; + if (resultId) + ++wordCount; + wordCount += (unsigned int)operands.size(); + + // Write out the beginning of the instruction + out.push_back(((wordCount) << WordCountShift) | opCode); + if (typeId) + out.push_back(typeId); + if (resultId) + out.push_back(resultId); + + // Write out the operands + for (int op = 0; op < (int)operands.size(); ++op) + out.push_back(operands[op]); + } + +protected: + Instruction(const Instruction&); + Id resultId; + Id typeId; + Op opCode; + std::vector operands; // operands, both and immediates (both are unsigned int) + std::vector idOperand; // true for operands that are , false for immediates + Block* block; +}; + +// +// SPIR-V IR block. +// + +class Block { +public: + Block(Id id, Function& parent); + virtual ~Block() + { + } + + Id getId() { return instructions.front()->getResultId(); } + + Function& getParent() const { return parent; } + void addInstruction(std::unique_ptr inst); + void addPredecessor(Block* pred) { predecessors.push_back(pred); pred->successors.push_back(this);} + void addLocalVariable(std::unique_ptr inst) { localVariables.push_back(std::move(inst)); } + const std::vector& getPredecessors() const { return predecessors; } + const std::vector& getSuccessors() const { return successors; } + const std::vector >& getInstructions() const { + return instructions; + } + const std::vector >& getLocalVariables() const { return localVariables; } + void setUnreachable() { unreachable = true; } + bool isUnreachable() const { return unreachable; } + // Returns the block's merge instruction, if one exists (otherwise null). + const Instruction* getMergeInstruction() const { + if (instructions.size() < 2) return nullptr; + const Instruction* nextToLast = (instructions.cend() - 2)->get(); + switch (nextToLast->getOpCode()) { + case OpSelectionMerge: + case OpLoopMerge: + return nextToLast; + default: + return nullptr; + } + return nullptr; + } + + // Change this block into a canonical dead merge block. Delete instructions + // as necessary. A canonical dead merge block has only an OpLabel and an + // OpUnreachable. + void rewriteAsCanonicalUnreachableMerge() { + assert(localVariables.empty()); + // Delete all instructions except for the label. + assert(instructions.size() > 0); + instructions.resize(1); + successors.clear(); + addInstruction(std::unique_ptr(new Instruction(OpUnreachable))); + } + // Change this block into a canonical dead continue target branching to the + // given header ID. Delete instructions as necessary. A canonical dead continue + // target has only an OpLabel and an unconditional branch back to the corresponding + // header. + void rewriteAsCanonicalUnreachableContinue(Block* header) { + assert(localVariables.empty()); + // Delete all instructions except for the label. + assert(instructions.size() > 0); + instructions.resize(1); + successors.clear(); + // Add OpBranch back to the header. + assert(header != nullptr); + Instruction* branch = new Instruction(OpBranch); + branch->addIdOperand(header->getId()); + addInstruction(std::unique_ptr(branch)); + successors.push_back(header); + } + + bool isTerminated() const + { + switch (instructions.back()->getOpCode()) { + case OpBranch: + case OpBranchConditional: + case OpSwitch: + case OpKill: + case OpReturn: + case OpReturnValue: + case OpUnreachable: + return true; + default: + return false; + } + } + + void dump(std::vector& out) const + { + instructions[0]->dump(out); + for (int i = 0; i < (int)localVariables.size(); ++i) + localVariables[i]->dump(out); + for (int i = 1; i < (int)instructions.size(); ++i) + instructions[i]->dump(out); + } + +protected: + Block(const Block&); + Block& operator=(Block&); + + // To enforce keeping parent and ownership in sync: + friend Function; + + std::vector > instructions; + std::vector predecessors, successors; + std::vector > localVariables; + Function& parent; + + // track whether this block is known to be uncreachable (not necessarily + // true for all unreachable blocks, but should be set at least + // for the extraneous ones introduced by the builder). + bool unreachable; +}; + +// The different reasons for reaching a block in the inReadableOrder traversal. +enum ReachReason { + // Reachable from the entry block via transfers of control, i.e. branches. + ReachViaControlFlow = 0, + // A continue target that is not reachable via control flow. + ReachDeadContinue, + // A merge block that is not reachable via control flow. + ReachDeadMerge +}; + +// Traverses the control-flow graph rooted at root in an order suited for +// readable code generation. Invokes callback at every node in the traversal +// order. The callback arguments are: +// - the block, +// - the reason we reached the block, +// - if the reason was that block is an unreachable continue or unreachable merge block +// then the last parameter is the corresponding header block. +void inReadableOrder(Block* root, std::function callback); + +// +// SPIR-V IR Function. +// + +class Function { +public: + Function(Id id, Id resultType, Id functionType, Id firstParam, Module& parent); + virtual ~Function() + { + for (int i = 0; i < (int)parameterInstructions.size(); ++i) + delete parameterInstructions[i]; + + for (int i = 0; i < (int)blocks.size(); ++i) + delete blocks[i]; + } + Id getId() const { return functionInstruction.getResultId(); } + Id getParamId(int p) const { return parameterInstructions[p]->getResultId(); } + Id getParamType(int p) const { return parameterInstructions[p]->getTypeId(); } + + void addBlock(Block* block) { blocks.push_back(block); } + void removeBlock(Block* block) + { + auto found = find(blocks.begin(), blocks.end(), block); + assert(found != blocks.end()); + blocks.erase(found); + delete block; + } + + Module& getParent() const { return parent; } + Block* getEntryBlock() const { return blocks.front(); } + Block* getLastBlock() const { return blocks.back(); } + const std::vector& getBlocks() const { return blocks; } + void addLocalVariable(std::unique_ptr inst); + Id getReturnType() const { return functionInstruction.getTypeId(); } + + void setImplicitThis() { implicitThis = true; } + bool hasImplicitThis() const { return implicitThis; } + + void dump(std::vector& out) const + { + // OpFunction + functionInstruction.dump(out); + + // OpFunctionParameter + for (int p = 0; p < (int)parameterInstructions.size(); ++p) + parameterInstructions[p]->dump(out); + + // Blocks + inReadableOrder(blocks[0], [&out](const Block* b, ReachReason, Block*) { b->dump(out); }); + Instruction end(0, 0, OpFunctionEnd); + end.dump(out); + } + +protected: + Function(const Function&); + Function& operator=(Function&); + + Module& parent; + Instruction functionInstruction; + std::vector parameterInstructions; + std::vector blocks; + bool implicitThis; // true if this is a member function expecting to be passed a 'this' as the first argument +}; + +// +// SPIR-V IR Module. +// + +class Module { +public: + Module() {} + virtual ~Module() + { + // TODO delete things + } + + void addFunction(Function *fun) { functions.push_back(fun); } + + void mapInstruction(Instruction *instruction) + { + spv::Id resultId = instruction->getResultId(); + // map the instruction's result id + if (resultId >= idToInstruction.size()) + idToInstruction.resize(resultId + 16); + idToInstruction[resultId] = instruction; + } + + Instruction* getInstruction(Id id) const { return idToInstruction[id]; } + const std::vector& getFunctions() const { return functions; } + spv::Id getTypeId(Id resultId) const { + return idToInstruction[resultId] == nullptr ? NoType : idToInstruction[resultId]->getTypeId(); + } + StorageClass getStorageClass(Id typeId) const + { + assert(idToInstruction[typeId]->getOpCode() == spv::OpTypePointer); + return (StorageClass)idToInstruction[typeId]->getImmediateOperand(0); + } + + void dump(std::vector& out) const + { + for (int f = 0; f < (int)functions.size(); ++f) + functions[f]->dump(out); + } + +protected: + Module(const Module&); + std::vector functions; + + // map from result id to instruction having that result id + std::vector idToInstruction; + + // map from a result id to its type id +}; + +// +// Implementation (it's here due to circular type definitions). +// + +// Add both +// - the OpFunction instruction +// - all the OpFunctionParameter instructions +__inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, Module& parent) + : parent(parent), functionInstruction(id, resultType, OpFunction), implicitThis(false) +{ + // OpFunction + functionInstruction.addImmediateOperand(FunctionControlMaskNone); + functionInstruction.addIdOperand(functionType); + parent.mapInstruction(&functionInstruction); + parent.addFunction(this); + + // OpFunctionParameter + Instruction* typeInst = parent.getInstruction(functionType); + int numParams = typeInst->getNumOperands() - 1; + for (int p = 0; p < numParams; ++p) { + Instruction* param = new Instruction(firstParamId + p, typeInst->getIdOperand(p + 1), OpFunctionParameter); + parent.mapInstruction(param); + parameterInstructions.push_back(param); + } +} + +__inline void Function::addLocalVariable(std::unique_ptr inst) +{ + Instruction* raw_instruction = inst.get(); + blocks[0]->addLocalVariable(std::move(inst)); + parent.mapInstruction(raw_instruction); +} + +__inline Block::Block(Id id, Function& parent) : parent(parent), unreachable(false) +{ + instructions.push_back(std::unique_ptr(new Instruction(id, NoType, OpLabel))); + instructions.back()->setBlock(this); + parent.getParent().mapInstruction(instructions.back().get()); +} + +__inline void Block::addInstruction(std::unique_ptr inst) +{ + Instruction* raw_instruction = inst.get(); + instructions.push_back(std::move(inst)); + raw_instruction->setBlock(this); + if (raw_instruction->getResultId()) + parent.getParent().mapInstruction(raw_instruction); +} + +} // end spv namespace + +#endif // spvIR_H diff --git a/mac/CMakeLists.txt b/mac/CMakeLists.txt index aa8329b8..f43e56e9 100644 --- a/mac/CMakeLists.txt +++ b/mac/CMakeLists.txt @@ -131,6 +131,38 @@ if(USE_TIFF) ) endif() +add_library(glslang STATIC IMPORTED GLOBAL) +set_target_properties(glslang PROPERTIES + IMPORTED_LOCATION ${CMAKE_CURRENT_LIST_DIR}/libs/glslang.lib +) +add_library(OGLCompiler STATIC IMPORTED GLOBAL) +set_target_properties(OGLCompiler PROPERTIES + IMPORTED_LOCATION ${CMAKE_CURRENT_LIST_DIR}/libs/OGLCompiler.lib +) +add_library(OSDependent STATIC IMPORTED GLOBAL) +set_target_properties(OSDependent PROPERTIES + IMPORTED_LOCATION ${CMAKE_CURRENT_LIST_DIR}/libs/OSDependent.lib +) +add_library(SPIRV STATIC IMPORTED GLOBAL) +set_target_properties(SPIRV PROPERTIES + IMPORTED_LOCATION ${CMAKE_CURRENT_LIST_DIR}/libs/SPIRV.lib +) +set(glslang_libs_name glslang OGLCompiler OSDependent SPIRV) + +add_library(spirv-cross-core STATIC IMPORTED GLOBAL) +set_target_properties(spirv-cross-core PROPERTIES + IMPORTED_LOCATION ${CMAKE_CURRENT_LIST_DIR}/libs/libspirv-cross-core.lib +) +add_library(spirv-cross-msl STATIC IMPORTED GLOBAL) +set_target_properties(spirv-cross-msl PROPERTIES + IMPORTED_LOCATION ${CMAKE_CURRENT_LIST_DIR}/libs/libspirv-cross-msl.lib +) +add_library(spirv-cross-glsl STATIC IMPORTED GLOBAL) +set_target_properties(spirv-cross-glsl PROPERTIES + IMPORTED_LOCATION ${CMAKE_CURRENT_LIST_DIR}/libs/libspirv-cross-glsl.lib +) +set(spirv-cross_libs_name spirv-cross-core spirv-cross-glsl spirv-cross-msl) + list(APPEND CC_EXTERNAL_LIBS freetype EGL @@ -143,6 +175,8 @@ list(APPEND CC_EXTERNAL_LIBS crypto ssl z + ${glslang_libs_name} + ${spirv-cross_libs_name} ) list(APPEND CC_EXTERNAL_INCLUDES diff --git a/mac/include/SPIRV/GLSL.ext.AMD.h b/mac/include/SPIRV/GLSL.ext.AMD.h new file mode 100644 index 00000000..009d2f1c --- /dev/null +++ b/mac/include/SPIRV/GLSL.ext.AMD.h @@ -0,0 +1,108 @@ +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextAMD_H +#define GLSLextAMD_H + +static const int GLSLextAMDVersion = 100; +static const int GLSLextAMDRevision = 7; + +// SPV_AMD_shader_ballot +static const char* const E_SPV_AMD_shader_ballot = "SPV_AMD_shader_ballot"; + +enum ShaderBallotAMD { + ShaderBallotBadAMD = 0, // Don't use + + SwizzleInvocationsAMD = 1, + SwizzleInvocationsMaskedAMD = 2, + WriteInvocationAMD = 3, + MbcntAMD = 4, + + ShaderBallotCountAMD +}; + +// SPV_AMD_shader_trinary_minmax +static const char* const E_SPV_AMD_shader_trinary_minmax = "SPV_AMD_shader_trinary_minmax"; + +enum ShaderTrinaryMinMaxAMD { + ShaderTrinaryMinMaxBadAMD = 0, // Don't use + + FMin3AMD = 1, + UMin3AMD = 2, + SMin3AMD = 3, + FMax3AMD = 4, + UMax3AMD = 5, + SMax3AMD = 6, + FMid3AMD = 7, + UMid3AMD = 8, + SMid3AMD = 9, + + ShaderTrinaryMinMaxCountAMD +}; + +// SPV_AMD_shader_explicit_vertex_parameter +static const char* const E_SPV_AMD_shader_explicit_vertex_parameter = "SPV_AMD_shader_explicit_vertex_parameter"; + +enum ShaderExplicitVertexParameterAMD { + ShaderExplicitVertexParameterBadAMD = 0, // Don't use + + InterpolateAtVertexAMD = 1, + + ShaderExplicitVertexParameterCountAMD +}; + +// SPV_AMD_gcn_shader +static const char* const E_SPV_AMD_gcn_shader = "SPV_AMD_gcn_shader"; + +enum GcnShaderAMD { + GcnShaderBadAMD = 0, // Don't use + + CubeFaceIndexAMD = 1, + CubeFaceCoordAMD = 2, + TimeAMD = 3, + + GcnShaderCountAMD +}; + +// SPV_AMD_gpu_shader_half_float +static const char* const E_SPV_AMD_gpu_shader_half_float = "SPV_AMD_gpu_shader_half_float"; + +// SPV_AMD_texture_gather_bias_lod +static const char* const E_SPV_AMD_texture_gather_bias_lod = "SPV_AMD_texture_gather_bias_lod"; + +// SPV_AMD_gpu_shader_int16 +static const char* const E_SPV_AMD_gpu_shader_int16 = "SPV_AMD_gpu_shader_int16"; + +// SPV_AMD_shader_image_load_store_lod +static const char* const E_SPV_AMD_shader_image_load_store_lod = "SPV_AMD_shader_image_load_store_lod"; + +// SPV_AMD_shader_fragment_mask +static const char* const E_SPV_AMD_shader_fragment_mask = "SPV_AMD_shader_fragment_mask"; + +// SPV_AMD_gpu_shader_half_float_fetch +static const char* const E_SPV_AMD_gpu_shader_half_float_fetch = "SPV_AMD_gpu_shader_half_float_fetch"; + +#endif // #ifndef GLSLextAMD_H diff --git a/mac/include/SPIRV/GLSL.ext.EXT.h b/mac/include/SPIRV/GLSL.ext.EXT.h new file mode 100644 index 00000000..40164b61 --- /dev/null +++ b/mac/include/SPIRV/GLSL.ext.EXT.h @@ -0,0 +1,39 @@ +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextEXT_H +#define GLSLextEXT_H + +static const int GLSLextEXTVersion = 100; +static const int GLSLextEXTRevision = 2; + +static const char* const E_SPV_EXT_shader_stencil_export = "SPV_EXT_shader_stencil_export"; +static const char* const E_SPV_EXT_shader_viewport_index_layer = "SPV_EXT_shader_viewport_index_layer"; +static const char* const E_SPV_EXT_fragment_fully_covered = "SPV_EXT_fragment_fully_covered"; +static const char* const E_SPV_EXT_fragment_invocation_density = "SPV_EXT_fragment_invocation_density"; +static const char* const E_SPV_EXT_demote_to_helper_invocation = "SPV_EXT_demote_to_helper_invocation"; + +#endif // #ifndef GLSLextEXT_H diff --git a/mac/include/SPIRV/GLSL.ext.KHR.h b/mac/include/SPIRV/GLSL.ext.KHR.h new file mode 100644 index 00000000..d783a8f2 --- /dev/null +++ b/mac/include/SPIRV/GLSL.ext.KHR.h @@ -0,0 +1,51 @@ +/* +** Copyright (c) 2014-2020 The Khronos Group Inc. +** Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextKHR_H +#define GLSLextKHR_H + +static const int GLSLextKHRVersion = 100; +static const int GLSLextKHRRevision = 2; + +static const char* const E_SPV_KHR_shader_ballot = "SPV_KHR_shader_ballot"; +static const char* const E_SPV_KHR_subgroup_vote = "SPV_KHR_subgroup_vote"; +static const char* const E_SPV_KHR_device_group = "SPV_KHR_device_group"; +static const char* const E_SPV_KHR_multiview = "SPV_KHR_multiview"; +static const char* const E_SPV_KHR_shader_draw_parameters = "SPV_KHR_shader_draw_parameters"; +static const char* const E_SPV_KHR_16bit_storage = "SPV_KHR_16bit_storage"; +static const char* const E_SPV_KHR_8bit_storage = "SPV_KHR_8bit_storage"; +static const char* const E_SPV_KHR_storage_buffer_storage_class = "SPV_KHR_storage_buffer_storage_class"; +static const char* const E_SPV_KHR_post_depth_coverage = "SPV_KHR_post_depth_coverage"; +static const char* const E_SPV_KHR_vulkan_memory_model = "SPV_KHR_vulkan_memory_model"; +static const char* const E_SPV_EXT_physical_storage_buffer = "SPV_EXT_physical_storage_buffer"; +static const char* const E_SPV_KHR_physical_storage_buffer = "SPV_KHR_physical_storage_buffer"; +static const char* const E_SPV_EXT_fragment_shader_interlock = "SPV_EXT_fragment_shader_interlock"; +static const char* const E_SPV_KHR_shader_clock = "SPV_KHR_shader_clock"; +static const char* const E_SPV_KHR_non_semantic_info = "SPV_KHR_non_semantic_info"; +static const char* const E_SPV_KHR_ray_tracing = "SPV_KHR_ray_tracing"; +static const char* const E_SPV_KHR_ray_query = "SPV_KHR_ray_query"; +#endif // #ifndef GLSLextKHR_H diff --git a/mac/include/SPIRV/GLSL.ext.NV.h b/mac/include/SPIRV/GLSL.ext.NV.h new file mode 100644 index 00000000..50146da1 --- /dev/null +++ b/mac/include/SPIRV/GLSL.ext.NV.h @@ -0,0 +1,81 @@ +/* +** Copyright (c) 2014-2017 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextNV_H +#define GLSLextNV_H + +enum BuiltIn; +enum Decoration; +enum Op; +enum Capability; + +static const int GLSLextNVVersion = 100; +static const int GLSLextNVRevision = 11; + +//SPV_NV_sample_mask_override_coverage +const char* const E_SPV_NV_sample_mask_override_coverage = "SPV_NV_sample_mask_override_coverage"; + +//SPV_NV_geometry_shader_passthrough +const char* const E_SPV_NV_geometry_shader_passthrough = "SPV_NV_geometry_shader_passthrough"; + +//SPV_NV_viewport_array2 +const char* const E_SPV_NV_viewport_array2 = "SPV_NV_viewport_array2"; +const char* const E_ARB_shader_viewport_layer_array = "SPV_ARB_shader_viewport_layer_array"; + +//SPV_NV_stereo_view_rendering +const char* const E_SPV_NV_stereo_view_rendering = "SPV_NV_stereo_view_rendering"; + +//SPV_NVX_multiview_per_view_attributes +const char* const E_SPV_NVX_multiview_per_view_attributes = "SPV_NVX_multiview_per_view_attributes"; + +//SPV_NV_shader_subgroup_partitioned +const char* const E_SPV_NV_shader_subgroup_partitioned = "SPV_NV_shader_subgroup_partitioned"; + +//SPV_NV_fragment_shader_barycentric +const char* const E_SPV_NV_fragment_shader_barycentric = "SPV_NV_fragment_shader_barycentric"; + +//SPV_NV_compute_shader_derivatives +const char* const E_SPV_NV_compute_shader_derivatives = "SPV_NV_compute_shader_derivatives"; + +//SPV_NV_shader_image_footprint +const char* const E_SPV_NV_shader_image_footprint = "SPV_NV_shader_image_footprint"; + +//SPV_NV_mesh_shader +const char* const E_SPV_NV_mesh_shader = "SPV_NV_mesh_shader"; + +//SPV_NV_raytracing +const char* const E_SPV_NV_ray_tracing = "SPV_NV_ray_tracing"; + +//SPV_NV_shading_rate +const char* const E_SPV_NV_shading_rate = "SPV_NV_shading_rate"; + +//SPV_NV_cooperative_matrix +const char* const E_SPV_NV_cooperative_matrix = "SPV_NV_cooperative_matrix"; + +//SPV_NV_shader_sm_builtins +const char* const E_SPV_NV_shader_sm_builtins = "SPV_NV_shader_sm_builtins"; + +#endif // #ifndef GLSLextNV_H diff --git a/mac/include/SPIRV/GLSL.std.450.h b/mac/include/SPIRV/GLSL.std.450.h new file mode 100644 index 00000000..df31092b --- /dev/null +++ b/mac/include/SPIRV/GLSL.std.450.h @@ -0,0 +1,131 @@ +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLstd450_H +#define GLSLstd450_H + +static const int GLSLstd450Version = 100; +static const int GLSLstd450Revision = 1; + +enum GLSLstd450 { + GLSLstd450Bad = 0, // Don't use + + GLSLstd450Round = 1, + GLSLstd450RoundEven = 2, + GLSLstd450Trunc = 3, + GLSLstd450FAbs = 4, + GLSLstd450SAbs = 5, + GLSLstd450FSign = 6, + GLSLstd450SSign = 7, + GLSLstd450Floor = 8, + GLSLstd450Ceil = 9, + GLSLstd450Fract = 10, + + GLSLstd450Radians = 11, + GLSLstd450Degrees = 12, + GLSLstd450Sin = 13, + GLSLstd450Cos = 14, + GLSLstd450Tan = 15, + GLSLstd450Asin = 16, + GLSLstd450Acos = 17, + GLSLstd450Atan = 18, + GLSLstd450Sinh = 19, + GLSLstd450Cosh = 20, + GLSLstd450Tanh = 21, + GLSLstd450Asinh = 22, + GLSLstd450Acosh = 23, + GLSLstd450Atanh = 24, + GLSLstd450Atan2 = 25, + + GLSLstd450Pow = 26, + GLSLstd450Exp = 27, + GLSLstd450Log = 28, + GLSLstd450Exp2 = 29, + GLSLstd450Log2 = 30, + GLSLstd450Sqrt = 31, + GLSLstd450InverseSqrt = 32, + + GLSLstd450Determinant = 33, + GLSLstd450MatrixInverse = 34, + + GLSLstd450Modf = 35, // second operand needs an OpVariable to write to + GLSLstd450ModfStruct = 36, // no OpVariable operand + GLSLstd450FMin = 37, + GLSLstd450UMin = 38, + GLSLstd450SMin = 39, + GLSLstd450FMax = 40, + GLSLstd450UMax = 41, + GLSLstd450SMax = 42, + GLSLstd450FClamp = 43, + GLSLstd450UClamp = 44, + GLSLstd450SClamp = 45, + GLSLstd450FMix = 46, + GLSLstd450IMix = 47, // Reserved + GLSLstd450Step = 48, + GLSLstd450SmoothStep = 49, + + GLSLstd450Fma = 50, + GLSLstd450Frexp = 51, // second operand needs an OpVariable to write to + GLSLstd450FrexpStruct = 52, // no OpVariable operand + GLSLstd450Ldexp = 53, + + GLSLstd450PackSnorm4x8 = 54, + GLSLstd450PackUnorm4x8 = 55, + GLSLstd450PackSnorm2x16 = 56, + GLSLstd450PackUnorm2x16 = 57, + GLSLstd450PackHalf2x16 = 58, + GLSLstd450PackDouble2x32 = 59, + GLSLstd450UnpackSnorm2x16 = 60, + GLSLstd450UnpackUnorm2x16 = 61, + GLSLstd450UnpackHalf2x16 = 62, + GLSLstd450UnpackSnorm4x8 = 63, + GLSLstd450UnpackUnorm4x8 = 64, + GLSLstd450UnpackDouble2x32 = 65, + + GLSLstd450Length = 66, + GLSLstd450Distance = 67, + GLSLstd450Cross = 68, + GLSLstd450Normalize = 69, + GLSLstd450FaceForward = 70, + GLSLstd450Reflect = 71, + GLSLstd450Refract = 72, + + GLSLstd450FindILsb = 73, + GLSLstd450FindSMsb = 74, + GLSLstd450FindUMsb = 75, + + GLSLstd450InterpolateAtCentroid = 76, + GLSLstd450InterpolateAtSample = 77, + GLSLstd450InterpolateAtOffset = 78, + + GLSLstd450NMin = 79, + GLSLstd450NMax = 80, + GLSLstd450NClamp = 81, + + GLSLstd450Count +}; + +#endif // #ifndef GLSLstd450_H diff --git a/mac/include/SPIRV/GlslangToSpv.h b/mac/include/SPIRV/GlslangToSpv.h new file mode 100644 index 00000000..3907be43 --- /dev/null +++ b/mac/include/SPIRV/GlslangToSpv.h @@ -0,0 +1,61 @@ +// +// Copyright (C) 2014 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#pragma once + +#if defined(_MSC_VER) && _MSC_VER >= 1900 + #pragma warning(disable : 4464) // relative include path contains '..' +#endif + +#include "SpvTools.h" +#include "glslang/Include/intermediate.h" + +#include +#include + +#include "Logger.h" + +namespace glslang { + +void GetSpirvVersion(std::string&); +int GetSpirvGeneratorVersion(); +void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, + SpvOptions* options = nullptr); +void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger* logger, SpvOptions* options = nullptr); +void OutputSpvBin(const std::vector& spirv, const char* baseName); +void OutputSpvHex(const std::vector& spirv, const char* baseName, const char* varName); + +} diff --git a/mac/include/SPIRV/Logger.h b/mac/include/SPIRV/Logger.h new file mode 100644 index 00000000..411367c0 --- /dev/null +++ b/mac/include/SPIRV/Logger.h @@ -0,0 +1,83 @@ +// +// Copyright (C) 2016 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef GLSLANG_SPIRV_LOGGER_H +#define GLSLANG_SPIRV_LOGGER_H + +#include +#include + +namespace spv { + +// A class for holding all SPIR-V build status messages, including +// missing/TBD functionalities, warnings, and errors. +class SpvBuildLogger { +public: + SpvBuildLogger() {} + +#ifdef GLSLANG_WEB + void tbdFunctionality(const std::string& f) { } + void missingFunctionality(const std::string& f) { } + void warning(const std::string& w) { } + void error(const std::string& e) { errors.push_back(e); } + std::string getAllMessages() { return ""; } +#else + + // Registers a TBD functionality. + void tbdFunctionality(const std::string& f); + // Registers a missing functionality. + void missingFunctionality(const std::string& f); + + // Logs a warning. + void warning(const std::string& w) { warnings.push_back(w); } + // Logs an error. + void error(const std::string& e) { errors.push_back(e); } + + // Returns all messages accumulated in the order of: + // TBD functionalities, missing functionalities, warnings, errors. + std::string getAllMessages() const; +#endif + +private: + SpvBuildLogger(const SpvBuildLogger&); + + std::vector tbdFeatures; + std::vector missingFeatures; + std::vector warnings; + std::vector errors; +}; + +} // end spv namespace + +#endif // GLSLANG_SPIRV_LOGGER_H diff --git a/mac/include/SPIRV/NonSemanticDebugPrintf.h b/mac/include/SPIRV/NonSemanticDebugPrintf.h new file mode 100644 index 00000000..83796d75 --- /dev/null +++ b/mac/include/SPIRV/NonSemanticDebugPrintf.h @@ -0,0 +1,50 @@ +// Copyright (c) 2020 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and/or associated documentation files (the +// "Materials"), to deal in the Materials without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Materials, and to +// permit persons to whom the Materials are furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS +// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS +// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT +// https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +// + +#ifndef SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ +#define SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + NonSemanticDebugPrintfRevision = 1, + NonSemanticDebugPrintfRevision_BitWidthPadding = 0x7fffffff +}; + +enum NonSemanticDebugPrintfInstructions { + NonSemanticDebugPrintfDebugPrintf = 1, + NonSemanticDebugPrintfInstructionsMax = 0x7fffffff +}; + + +#ifdef __cplusplus +} +#endif + +#endif // SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ diff --git a/mac/include/SPIRV/SPVRemapper.h b/mac/include/SPIRV/SPVRemapper.h new file mode 100644 index 00000000..d6b9c346 --- /dev/null +++ b/mac/include/SPIRV/SPVRemapper.h @@ -0,0 +1,304 @@ +// +// Copyright (C) 2015 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef SPIRVREMAPPER_H +#define SPIRVREMAPPER_H + +#include +#include +#include +#include + +namespace spv { + +// MSVC defines __cplusplus as an older value, even when it supports almost all of 11. +// We handle that here by making our own symbol. +#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1700) +# define use_cpp11 1 +#endif + +class spirvbin_base_t +{ +public: + enum Options { + NONE = 0, + STRIP = (1<<0), + MAP_TYPES = (1<<1), + MAP_NAMES = (1<<2), + MAP_FUNCS = (1<<3), + DCE_FUNCS = (1<<4), + DCE_VARS = (1<<5), + DCE_TYPES = (1<<6), + OPT_LOADSTORE = (1<<7), + OPT_FWD_LS = (1<<8), // EXPERIMENTAL: PRODUCES INVALID SCHEMA-0 SPIRV + MAP_ALL = (MAP_TYPES | MAP_NAMES | MAP_FUNCS), + DCE_ALL = (DCE_FUNCS | DCE_VARS | DCE_TYPES), + OPT_ALL = (OPT_LOADSTORE), + + ALL_BUT_STRIP = (MAP_ALL | DCE_ALL | OPT_ALL), + DO_EVERYTHING = (STRIP | ALL_BUT_STRIP) + }; +}; + +} // namespace SPV + +#if !defined (use_cpp11) +#include +#include + +namespace spv { +class spirvbin_t : public spirvbin_base_t +{ +public: + spirvbin_t(int /*verbose = 0*/) { } + + void remap(std::vector& /*spv*/, unsigned int /*opts = 0*/) + { + printf("Tool not compiled for C++11, which is required for SPIR-V remapping.\n"); + exit(5); + } +}; + +} // namespace SPV + +#else // defined (use_cpp11) + +#include +#include +#include +#include +#include +#include +#include + +#include "spirv.hpp" +#include "spvIR.h" + +namespace spv { + +// class to hold SPIR-V binary data for remapping, DCE, and debug stripping +class spirvbin_t : public spirvbin_base_t +{ +public: + spirvbin_t(int verbose = 0) : entryPoint(spv::NoResult), largestNewId(0), verbose(verbose), errorLatch(false) + { } + + virtual ~spirvbin_t() { } + + // remap on an existing binary in memory + void remap(std::vector& spv, std::uint32_t opts = DO_EVERYTHING); + + // Type for error/log handler functions + typedef std::function errorfn_t; + typedef std::function logfn_t; + + // Register error/log handling functions (can be lambda fn / functor / etc) + static void registerErrorHandler(errorfn_t handler) { errorHandler = handler; } + static void registerLogHandler(logfn_t handler) { logHandler = handler; } + +protected: + // This can be overridden to provide other message behavior if needed + virtual void msg(int minVerbosity, int indent, const std::string& txt) const; + +private: + // Local to global, or global to local ID map + typedef std::unordered_map idmap_t; + typedef std::unordered_set idset_t; + typedef std::unordered_map blockmap_t; + + void remap(std::uint32_t opts = DO_EVERYTHING); + + // Map of names to IDs + typedef std::unordered_map namemap_t; + + typedef std::uint32_t spirword_t; + + typedef std::pair range_t; + typedef std::function idfn_t; + typedef std::function instfn_t; + + // Special Values for ID map: + static const spv::Id unmapped; // unchanged from default value + static const spv::Id unused; // unused ID + static const int header_size; // SPIR header = 5 words + + class id_iterator_t; + + // For mapping type entries between different shaders + typedef std::vector typeentry_t; + typedef std::map globaltypes_t; + + // A set that preserves position order, and a reverse map + typedef std::set posmap_t; + typedef std::unordered_map posmap_rev_t; + + // Maps and ID to the size of its base type, if known. + typedef std::unordered_map typesize_map_t; + + // handle error + void error(const std::string& txt) const { errorLatch = true; errorHandler(txt); } + + bool isConstOp(spv::Op opCode) const; + bool isTypeOp(spv::Op opCode) const; + bool isStripOp(spv::Op opCode) const; + bool isFlowCtrl(spv::Op opCode) const; + range_t literalRange(spv::Op opCode) const; + range_t typeRange(spv::Op opCode) const; + range_t constRange(spv::Op opCode) const; + unsigned typeSizeInWords(spv::Id id) const; + unsigned idTypeSizeInWords(spv::Id id) const; + + spv::Id& asId(unsigned word) { return spv[word]; } + const spv::Id& asId(unsigned word) const { return spv[word]; } + spv::Op asOpCode(unsigned word) const { return opOpCode(spv[word]); } + std::uint32_t asOpCodeHash(unsigned word); + spv::Decoration asDecoration(unsigned word) const { return spv::Decoration(spv[word]); } + unsigned asWordCount(unsigned word) const { return opWordCount(spv[word]); } + spv::Id asTypeConstId(unsigned word) const { return asId(word + (isTypeOp(asOpCode(word)) ? 1 : 2)); } + unsigned idPos(spv::Id id) const; + + static unsigned opWordCount(spirword_t data) { return data >> spv::WordCountShift; } + static spv::Op opOpCode(spirword_t data) { return spv::Op(data & spv::OpCodeMask); } + + // Header access & set methods + spirword_t magic() const { return spv[0]; } // return magic number + spirword_t bound() const { return spv[3]; } // return Id bound from header + spirword_t bound(spirword_t b) { return spv[3] = b; } + spirword_t genmagic() const { return spv[2]; } // generator magic + spirword_t genmagic(spirword_t m) { return spv[2] = m; } + spirword_t schemaNum() const { return spv[4]; } // schema number from header + + // Mapping fns: get + spv::Id localId(spv::Id id) const { return idMapL[id]; } + + // Mapping fns: set + inline spv::Id localId(spv::Id id, spv::Id newId); + void countIds(spv::Id id); + + // Return next unused new local ID. + // NOTE: boost::dynamic_bitset would be more efficient due to find_next(), + // which std::vector doens't have. + inline spv::Id nextUnusedId(spv::Id id); + + void buildLocalMaps(); + std::string literalString(unsigned word) const; // Return literal as a std::string + int literalStringWords(const std::string& str) const { return (int(str.size())+4)/4; } + + bool isNewIdMapped(spv::Id newId) const { return isMapped(newId); } + bool isOldIdUnmapped(spv::Id oldId) const { return localId(oldId) == unmapped; } + bool isOldIdUnused(spv::Id oldId) const { return localId(oldId) == unused; } + bool isOldIdMapped(spv::Id oldId) const { return !isOldIdUnused(oldId) && !isOldIdUnmapped(oldId); } + bool isFunction(spv::Id oldId) const { return fnPos.find(oldId) != fnPos.end(); } + + // bool matchType(const globaltypes_t& globalTypes, spv::Id lt, spv::Id gt) const; + // spv::Id findType(const globaltypes_t& globalTypes, spv::Id lt) const; + std::uint32_t hashType(unsigned typeStart) const; + + spirvbin_t& process(instfn_t, idfn_t, unsigned begin = 0, unsigned end = 0); + int processInstruction(unsigned word, instfn_t, idfn_t); + + void validate() const; + void mapTypeConst(); + void mapFnBodies(); + void optLoadStore(); + void dceFuncs(); + void dceVars(); + void dceTypes(); + void mapNames(); + void foldIds(); // fold IDs to smallest space + void forwardLoadStores(); // load store forwarding (EXPERIMENTAL) + void offsetIds(); // create relative offset IDs + + void applyMap(); // remap per local name map + void mapRemainder(); // map any IDs we haven't touched yet + void stripDebug(); // strip all debug info + void stripDeadRefs(); // strips debug info for now-dead references after DCE + void strip(); // remove debug symbols + + std::vector spv; // SPIR words + + namemap_t nameMap; // ID names from OpName + + // Since we want to also do binary ops, we can't use std::vector. we could use + // boost::dynamic_bitset, but we're trying to avoid a boost dependency. + typedef std::uint64_t bits_t; + std::vector mapped; // which new IDs have been mapped + static const int mBits = sizeof(bits_t) * 4; + + bool isMapped(spv::Id id) const { return id < maxMappedId() && ((mapped[id/mBits] & (1LL<<(id%mBits))) != 0); } + void setMapped(spv::Id id) { resizeMapped(id); mapped[id/mBits] |= (1LL<<(id%mBits)); } + void resizeMapped(spv::Id id) { if (id >= maxMappedId()) mapped.resize(id/mBits+1, 0); } + size_t maxMappedId() const { return mapped.size() * mBits; } + + // Add a strip range for a given instruction starting at 'start' + // Note: avoiding brace initializers to please older versions os MSVC. + void stripInst(unsigned start) { stripRange.push_back(range_t(start, start + asWordCount(start))); } + + // Function start and end. use unordered_map because we'll have + // many fewer functions than IDs. + std::unordered_map fnPos; + + // Which functions are called, anywhere in the module, with a call count + std::unordered_map fnCalls; + + posmap_t typeConstPos; // word positions that define types & consts (ordered) + posmap_rev_t idPosR; // reverse map from IDs to positions + typesize_map_t idTypeSizeMap; // maps each ID to its type size, if known. + + std::vector idMapL; // ID {M}ap from {L}ocal to {G}lobal IDs + + spv::Id entryPoint; // module entry point + spv::Id largestNewId; // biggest new ID we have mapped anything to + + // Sections of the binary to strip, given as [begin,end) + std::vector stripRange; + + // processing options: + std::uint32_t options; + int verbose; // verbosity level + + // Error latch: this is set if the error handler is ever executed. It would be better to + // use a try/catch block and throw, but that's not desired for certain environments, so + // this is the alternative. + mutable bool errorLatch; + + static errorfn_t errorHandler; + static logfn_t logHandler; +}; + +} // namespace SPV + +#endif // defined (use_cpp11) +#endif // SPIRVREMAPPER_H diff --git a/mac/include/SPIRV/SpvBuilder.h b/mac/include/SPIRV/SpvBuilder.h new file mode 100644 index 00000000..71b90d60 --- /dev/null +++ b/mac/include/SPIRV/SpvBuilder.h @@ -0,0 +1,838 @@ +// +// Copyright (C) 2014-2015 LunarG, Inc. +// Copyright (C) 2015-2020 Google, Inc. +// Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// "Builder" is an interface to fully build SPIR-V IR. Allocate one of +// these to build (a thread safe) internal SPIR-V representation (IR), +// and then dump it as a binary stream according to the SPIR-V specification. +// +// A Builder has a 1:1 relationship with a SPIR-V module. +// + +#pragma once +#ifndef SpvBuilder_H +#define SpvBuilder_H + +#include "Logger.h" +#include "spirv.hpp" +#include "spvIR.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace spv { + +typedef enum { + Spv_1_0 = (1 << 16), + Spv_1_1 = (1 << 16) | (1 << 8), + Spv_1_2 = (1 << 16) | (2 << 8), + Spv_1_3 = (1 << 16) | (3 << 8), + Spv_1_4 = (1 << 16) | (4 << 8), + Spv_1_5 = (1 << 16) | (5 << 8), +} SpvVersion; + +class Builder { +public: + Builder(unsigned int spvVersion, unsigned int userNumber, SpvBuildLogger* logger); + virtual ~Builder(); + + static const int maxMatrixSize = 4; + + unsigned int getSpvVersion() const { return spvVersion; } + + void setSource(spv::SourceLanguage lang, int version) + { + source = lang; + sourceVersion = version; + } + spv::Id getStringId(const std::string& str) + { + auto sItr = stringIds.find(str); + if (sItr != stringIds.end()) + return sItr->second; + spv::Id strId = getUniqueId(); + Instruction* fileString = new Instruction(strId, NoType, OpString); + const char* file_c_str = str.c_str(); + fileString->addStringOperand(file_c_str); + strings.push_back(std::unique_ptr(fileString)); + module.mapInstruction(fileString); + stringIds[file_c_str] = strId; + return strId; + } + void setSourceFile(const std::string& file) + { + sourceFileStringId = getStringId(file); + } + void setSourceText(const std::string& text) { sourceText = text; } + void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); } + void addModuleProcessed(const std::string& p) { moduleProcesses.push_back(p.c_str()); } + void setEmitOpLines() { emitOpLines = true; } + void addExtension(const char* ext) { extensions.insert(ext); } + void removeExtension(const char* ext) + { + extensions.erase(ext); + } + void addIncorporatedExtension(const char* ext, SpvVersion incorporatedVersion) + { + if (getSpvVersion() < static_cast(incorporatedVersion)) + addExtension(ext); + } + void promoteIncorporatedExtension(const char* baseExt, const char* promoExt, SpvVersion incorporatedVersion) + { + removeExtension(baseExt); + addIncorporatedExtension(promoExt, incorporatedVersion); + } + void addInclude(const std::string& name, const std::string& text) + { + spv::Id incId = getStringId(name); + includeFiles[incId] = &text; + } + Id import(const char*); + void setMemoryModel(spv::AddressingModel addr, spv::MemoryModel mem) + { + addressModel = addr; + memoryModel = mem; + } + + void addCapability(spv::Capability cap) { capabilities.insert(cap); } + + // To get a new for anything needing a new one. + Id getUniqueId() { return ++uniqueId; } + + // To get a set of new s, e.g., for a set of function parameters + Id getUniqueIds(int numIds) + { + Id id = uniqueId + 1; + uniqueId += numIds; + return id; + } + + // Generate OpLine for non-filename-based #line directives (ie no filename + // seen yet): Log the current line, and if different than the last one, + // issue a new OpLine using the new line and current source file name. + void setLine(int line); + + // If filename null, generate OpLine for non-filename-based line directives, + // else do filename-based: Log the current line and file, and if different + // than the last one, issue a new OpLine using the new line and file + // name. + void setLine(int line, const char* filename); + // Low-level OpLine. See setLine() for a layered helper. + void addLine(Id fileName, int line, int column); + + // For creating new types (will return old type if the requested one was already made). + Id makeVoidType(); + Id makeBoolType(); + Id makePointer(StorageClass, Id pointee); + Id makeForwardPointer(StorageClass); + Id makePointerFromForwardPointer(StorageClass, Id forwardPointerType, Id pointee); + Id makeIntegerType(int width, bool hasSign); // generic + Id makeIntType(int width) { return makeIntegerType(width, true); } + Id makeUintType(int width) { return makeIntegerType(width, false); } + Id makeFloatType(int width); + Id makeStructType(const std::vector& members, const char*); + Id makeStructResultType(Id type0, Id type1); + Id makeVectorType(Id component, int size); + Id makeMatrixType(Id component, int cols, int rows); + Id makeArrayType(Id element, Id sizeId, int stride); // 0 stride means no stride decoration + Id makeRuntimeArray(Id element); + Id makeFunctionType(Id returnType, const std::vector& paramTypes); + Id makeImageType(Id sampledType, Dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format); + Id makeSamplerType(); + Id makeSampledImageType(Id imageType); + Id makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols); + + // accelerationStructureNV type + Id makeAccelerationStructureType(); + // rayQueryEXT type + Id makeRayQueryType(); + + // For querying about types. + Id getTypeId(Id resultId) const { return module.getTypeId(resultId); } + Id getDerefTypeId(Id resultId) const; + Op getOpCode(Id id) const { return module.getInstruction(id)->getOpCode(); } + Op getTypeClass(Id typeId) const { return getOpCode(typeId); } + Op getMostBasicTypeClass(Id typeId) const; + int getNumComponents(Id resultId) const { return getNumTypeComponents(getTypeId(resultId)); } + int getNumTypeConstituents(Id typeId) const; + int getNumTypeComponents(Id typeId) const { return getNumTypeConstituents(typeId); } + Id getScalarTypeId(Id typeId) const; + Id getContainedTypeId(Id typeId) const; + Id getContainedTypeId(Id typeId, int) const; + StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); } + ImageFormat getImageTypeFormat(Id typeId) const + { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); } + + bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); } + bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); } + bool isVector(Id resultId) const { return isVectorType(getTypeId(resultId)); } + bool isMatrix(Id resultId) const { return isMatrixType(getTypeId(resultId)); } + bool isCooperativeMatrix(Id resultId)const { return isCooperativeMatrixType(getTypeId(resultId)); } + bool isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); } + bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); } + + bool isBoolType(Id typeId) + { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); } + bool isIntType(Id typeId) const + { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; } + bool isUintType(Id typeId) const + { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; } + bool isFloatType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat; } + bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; } + bool isScalarType(Id typeId) const + { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt || + getTypeClass(typeId) == OpTypeBool; } + bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; } + bool isMatrixType(Id typeId) const { return getTypeClass(typeId) == OpTypeMatrix; } + bool isStructType(Id typeId) const { return getTypeClass(typeId) == OpTypeStruct; } + bool isArrayType(Id typeId) const { return getTypeClass(typeId) == OpTypeArray; } +#ifdef GLSLANG_WEB + bool isCooperativeMatrixType(Id typeId)const { return false; } +#else + bool isCooperativeMatrixType(Id typeId)const { return getTypeClass(typeId) == OpTypeCooperativeMatrixNV; } +#endif + bool isAggregateType(Id typeId) const + { return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); } + bool isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; } + bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; } + bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; } + bool containsType(Id typeId, Op typeOp, unsigned int width) const; + bool containsPhysicalStorageBufferOrArray(Id typeId) const; + + bool isConstantOpCode(Op opcode) const; + bool isSpecConstantOpCode(Op opcode) const; + bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); } + bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; } + bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); } + unsigned int getConstantScalar(Id resultId) const + { return module.getInstruction(resultId)->getImmediateOperand(0); } + StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); } + + int getScalarTypeWidth(Id typeId) const + { + Id scalarTypeId = getScalarTypeId(typeId); + assert(getTypeClass(scalarTypeId) == OpTypeInt || getTypeClass(scalarTypeId) == OpTypeFloat); + return module.getInstruction(scalarTypeId)->getImmediateOperand(0); + } + + int getTypeNumColumns(Id typeId) const + { + assert(isMatrixType(typeId)); + return getNumTypeConstituents(typeId); + } + int getNumColumns(Id resultId) const { return getTypeNumColumns(getTypeId(resultId)); } + int getTypeNumRows(Id typeId) const + { + assert(isMatrixType(typeId)); + return getNumTypeComponents(getContainedTypeId(typeId)); + } + int getNumRows(Id resultId) const { return getTypeNumRows(getTypeId(resultId)); } + + Dim getTypeDimensionality(Id typeId) const + { + assert(isImageType(typeId)); + return (Dim)module.getInstruction(typeId)->getImmediateOperand(1); + } + Id getImageType(Id resultId) const + { + Id typeId = getTypeId(resultId); + assert(isImageType(typeId) || isSampledImageType(typeId)); + return isSampledImageType(typeId) ? module.getInstruction(typeId)->getIdOperand(0) : typeId; + } + bool isArrayedImageType(Id typeId) const + { + assert(isImageType(typeId)); + return module.getInstruction(typeId)->getImmediateOperand(3) != 0; + } + + // For making new constants (will return old constant if the requested one was already made). + Id makeBoolConstant(bool b, bool specConstant = false); + Id makeInt8Constant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); } + Id makeUint8Constant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(8), u, specConstant); } + Id makeInt16Constant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(16), (unsigned)i, specConstant); } + Id makeUint16Constant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(16), u, specConstant); } + Id makeIntConstant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); } + Id makeUintConstant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(32), u, specConstant); } + Id makeInt64Constant(long long i, bool specConstant = false) + { return makeInt64Constant(makeIntType(64), (unsigned long long)i, specConstant); } + Id makeUint64Constant(unsigned long long u, bool specConstant = false) + { return makeInt64Constant(makeUintType(64), u, specConstant); } + Id makeFloatConstant(float f, bool specConstant = false); + Id makeDoubleConstant(double d, bool specConstant = false); + Id makeFloat16Constant(float f16, bool specConstant = false); + Id makeFpConstant(Id type, double d, bool specConstant = false); + + // Turn the array of constants into a proper spv constant of the requested type. + Id makeCompositeConstant(Id type, const std::vector& comps, bool specConst = false); + + // Methods for adding information outside the CFG. + Instruction* addEntryPoint(ExecutionModel, Function*, const char* name); + void addExecutionMode(Function*, ExecutionMode mode, int value1 = -1, int value2 = -1, int value3 = -1); + void addName(Id, const char* name); + void addMemberName(Id, int member, const char* name); + void addDecoration(Id, Decoration, int num = -1); + void addDecoration(Id, Decoration, const char*); + void addDecorationId(Id id, Decoration, Id idDecoration); + void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1); + void addMemberDecoration(Id, unsigned int member, Decoration, const char*); + + // At the end of what block do the next create*() instructions go? + void setBuildPoint(Block* bp) { buildPoint = bp; } + Block* getBuildPoint() const { return buildPoint; } + + // Make the entry-point function. The returned pointer is only valid + // for the lifetime of this builder. + Function* makeEntryPoint(const char*); + + // Make a shader-style function, and create its entry block if entry is non-zero. + // Return the function, pass back the entry. + // The returned pointer is only valid for the lifetime of this builder. + Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, + const std::vector& paramTypes, const std::vector>& precisions, Block **entry = 0); + + // Create a return. An 'implicit' return is one not appearing in the source + // code. In the case of an implicit return, no post-return block is inserted. + void makeReturn(bool implicit, Id retVal = 0); + + // Generate all the code needed to finish up a function. + void leaveFunction(); + + // Create a discard. + void makeDiscard(); + + // Create a global or function local or IO variable. + Id createVariable(StorageClass, Id type, const char* name = 0, Id initializer = NoResult); + + // Create an intermediate with an undefined value. + Id createUndefined(Id type); + + // Store into an Id and return the l-value + void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + + // Load from an Id and return it + Id createLoad(Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + + // Create an OpAccessChain instruction + Id createAccessChain(StorageClass, Id base, const std::vector& offsets); + + // Create an OpArrayLength instruction + Id createArrayLength(Id base, unsigned int member); + + // Create an OpCooperativeMatrixLengthNV instruction + Id createCooperativeMatrixLength(Id type); + + // Create an OpCompositeExtract instruction + Id createCompositeExtract(Id composite, Id typeId, unsigned index); + Id createCompositeExtract(Id composite, Id typeId, const std::vector& indexes); + Id createCompositeInsert(Id object, Id composite, Id typeId, unsigned index); + Id createCompositeInsert(Id object, Id composite, Id typeId, const std::vector& indexes); + + Id createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex); + Id createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex); + + void createNoResultOp(Op); + void createNoResultOp(Op, Id operand); + void createNoResultOp(Op, const std::vector& operands); + void createNoResultOp(Op, const std::vector& operands); + void createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask); + void createMemoryBarrier(unsigned executionScope, unsigned memorySemantics); + Id createUnaryOp(Op, Id typeId, Id operand); + Id createBinOp(Op, Id typeId, Id operand1, Id operand2); + Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3); + Id createOp(Op, Id typeId, const std::vector& operands); + Id createOp(Op, Id typeId, const std::vector& operands); + Id createFunctionCall(spv::Function*, const std::vector&); + Id createSpecConstantOp(Op, Id typeId, const std::vector& operands, const std::vector& literals); + + // Take an rvalue (source) and a set of channels to extract from it to + // make a new rvalue, which is returned. + Id createRvalueSwizzle(Decoration precision, Id typeId, Id source, const std::vector& channels); + + // Take a copy of an lvalue (target) and a source of components, and set the + // source components into the lvalue where the 'channels' say to put them. + // An updated version of the target is returned. + // (No true lvalue or stores are used.) + Id createLvalueSwizzle(Id typeId, Id target, Id source, const std::vector& channels); + + // If both the id and precision are valid, the id + // gets tagged with the requested precision. + // The passed in id is always the returned id, to simplify use patterns. + Id setPrecision(Id id, Decoration precision) + { + if (precision != NoPrecision && id != NoResult) + addDecoration(id, precision); + + return id; + } + + // Can smear a scalar to a vector for the following forms: + // - promoteScalar(scalar, vector) // smear scalar to width of vector + // - promoteScalar(vector, scalar) // smear scalar to width of vector + // - promoteScalar(pointer, scalar) // smear scalar to width of what pointer points to + // - promoteScalar(scalar, scalar) // do nothing + // Other forms are not allowed. + // + // Generally, the type of 'scalar' does not need to be the same type as the components in 'vector'. + // The type of the created vector is a vector of components of the same type as the scalar. + // + // Note: One of the arguments will change, with the result coming back that way rather than + // through the return value. + void promoteScalar(Decoration precision, Id& left, Id& right); + + // Make a value by smearing the scalar to fill the type. + // vectorType should be the correct type for making a vector of scalarVal. + // (No conversions are done.) + Id smearScalar(Decoration precision, Id scalarVal, Id vectorType); + + // Create a call to a built-in function. + Id createBuiltinCall(Id resultType, Id builtins, int entryPoint, const std::vector& args); + + // List of parameters used to create a texture operation + struct TextureParameters { + Id sampler; + Id coords; + Id bias; + Id lod; + Id Dref; + Id offset; + Id offsets; + Id gradX; + Id gradY; + Id sample; + Id component; + Id texelOut; + Id lodClamp; + Id granularity; + Id coarse; + bool nonprivate; + bool volatil; + }; + + // Select the correct texture operation based on all inputs, and emit the correct instruction + Id createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, + bool noImplicit, const TextureParameters&, ImageOperandsMask); + + // Emit the OpTextureQuery* instruction that was passed in. + // Figure out the right return value and type, and return it. + Id createTextureQueryCall(Op, const TextureParameters&, bool isUnsignedResult); + + Id createSamplePositionCall(Decoration precision, Id, Id); + + Id createBitFieldExtractCall(Decoration precision, Id, Id, Id, bool isSigned); + Id createBitFieldInsertCall(Decoration precision, Id, Id, Id, Id); + + // Reduction comparison for composites: For equal and not-equal resulting in a scalar. + Id createCompositeCompare(Decoration precision, Id, Id, bool /* true if for equal, false if for not-equal */); + + // OpCompositeConstruct + Id createCompositeConstruct(Id typeId, const std::vector& constituents); + + // vector or scalar constructor + Id createConstructor(Decoration precision, const std::vector& sources, Id resultTypeId); + + // matrix constructor + Id createMatrixConstructor(Decoration precision, const std::vector& sources, Id constructee); + + // Helper to use for building nested control flow with if-then-else. + class If { + public: + If(Id condition, unsigned int ctrl, Builder& builder); + ~If() {} + + void makeBeginElse(); + void makeEndIf(); + + private: + If(const If&); + If& operator=(If&); + + Builder& builder; + Id condition; + unsigned int control; + Function* function; + Block* headerBlock; + Block* thenBlock; + Block* elseBlock; + Block* mergeBlock; + }; + + // Make a switch statement. A switch has 'numSegments' of pieces of code, not containing + // any case/default labels, all separated by one or more case/default labels. Each possible + // case value v is a jump to the caseValues[v] segment. The defaultSegment is also in this + // number space. How to compute the value is given by 'condition', as in switch(condition). + // + // The SPIR-V Builder will maintain the stack of post-switch merge blocks for nested switches. + // + // Use a defaultSegment < 0 if there is no default segment (to branch to post switch). + // + // Returns the right set of basic blocks to start each code segment with, so that the caller's + // recursion stack can hold the memory for it. + // + void makeSwitch(Id condition, unsigned int control, int numSegments, const std::vector& caseValues, + const std::vector& valueToSegment, int defaultSegment, std::vector& segmentBB); + + // Add a branch to the innermost switch's merge block. + void addSwitchBreak(); + + // Move to the next code segment, passing in the return argument in makeSwitch() + void nextSwitchSegment(std::vector& segmentBB, int segment); + + // Finish off the innermost switch. + void endSwitch(std::vector& segmentBB); + + struct LoopBlocks { + LoopBlocks(Block& head, Block& body, Block& merge, Block& continue_target) : + head(head), body(body), merge(merge), continue_target(continue_target) { } + Block &head, &body, &merge, &continue_target; + private: + LoopBlocks(); + LoopBlocks& operator=(const LoopBlocks&) = delete; + }; + + // Start a new loop and prepare the builder to generate code for it. Until + // closeLoop() is called for this loop, createLoopContinue() and + // createLoopExit() will target its corresponding blocks. + LoopBlocks& makeNewLoop(); + + // Create a new block in the function containing the build point. Memory is + // owned by the function object. + Block& makeNewBlock(); + + // Add a branch to the continue_target of the current (innermost) loop. + void createLoopContinue(); + + // Add an exit (e.g. "break") from the innermost loop that we're currently + // in. + void createLoopExit(); + + // Close the innermost loop that you're in + void closeLoop(); + + // + // Access chain design for an R-Value vs. L-Value: + // + // There is a single access chain the builder is building at + // any particular time. Such a chain can be used to either to a load or + // a store, when desired. + // + // Expressions can be r-values, l-values, or both, or only r-values: + // a[b.c].d = .... // l-value + // ... = a[b.c].d; // r-value, that also looks like an l-value + // ++a[b.c].d; // r-value and l-value + // (x + y)[2]; // r-value only, can't possibly be l-value + // + // Computing an r-value means generating code. Hence, + // r-values should only be computed when they are needed, not speculatively. + // + // Computing an l-value means saving away information for later use in the compiler, + // no code is generated until the l-value is later dereferenced. It is okay + // to speculatively generate an l-value, just not okay to speculatively dereference it. + // + // The base of the access chain (the left-most variable or expression + // from which everything is based) can be set either as an l-value + // or as an r-value. Most efficient would be to set an l-value if one + // is available. If an expression was evaluated, the resulting r-value + // can be set as the chain base. + // + // The users of this single access chain can save and restore if they + // want to nest or manage multiple chains. + // + + struct AccessChain { + Id base; // for l-values, pointer to the base object, for r-values, the base object + std::vector indexChain; + Id instr; // cache the instruction that generates this access chain + std::vector swizzle; // each std::vector element selects the next GLSL component number + Id component; // a dynamic component index, can coexist with a swizzle, + // done after the swizzle, NoResult if not present + Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied; + // NoType unless a swizzle or component is present + bool isRValue; // true if 'base' is an r-value, otherwise, base is an l-value + unsigned int alignment; // bitwise OR of alignment values passed in. Accumulates worst alignment. + // Only tracks base and (optional) component selection alignment. + + // Accumulate whether anything in the chain of structures has coherent decorations. + struct CoherentFlags { + CoherentFlags() { clear(); } +#ifdef GLSLANG_WEB + void clear() { } + bool isVolatile() const { return false; } + CoherentFlags operator |=(const CoherentFlags &other) { return *this; } +#else + bool isVolatile() const { return volatil; } + bool anyCoherent() const { + return coherent || devicecoherent || queuefamilycoherent || workgroupcoherent || + subgroupcoherent || shadercallcoherent; + } + + unsigned coherent : 1; + unsigned devicecoherent : 1; + unsigned queuefamilycoherent : 1; + unsigned workgroupcoherent : 1; + unsigned subgroupcoherent : 1; + unsigned shadercallcoherent : 1; + unsigned nonprivate : 1; + unsigned volatil : 1; + unsigned isImage : 1; + + void clear() { + coherent = 0; + devicecoherent = 0; + queuefamilycoherent = 0; + workgroupcoherent = 0; + subgroupcoherent = 0; + shadercallcoherent = 0; + nonprivate = 0; + volatil = 0; + isImage = 0; + } + + CoherentFlags operator |=(const CoherentFlags &other) { + coherent |= other.coherent; + devicecoherent |= other.devicecoherent; + queuefamilycoherent |= other.queuefamilycoherent; + workgroupcoherent |= other.workgroupcoherent; + subgroupcoherent |= other.subgroupcoherent; + shadercallcoherent |= other.shadercallcoherent; + nonprivate |= other.nonprivate; + volatil |= other.volatil; + isImage |= other.isImage; + return *this; + } +#endif + }; + CoherentFlags coherentFlags; + }; + + // + // the SPIR-V builder maintains a single active chain that + // the following methods operate on + // + + // for external save and restore + AccessChain getAccessChain() { return accessChain; } + void setAccessChain(AccessChain newChain) { accessChain = newChain; } + + // clear accessChain + void clearAccessChain(); + + // set new base as an l-value base + void setAccessChainLValue(Id lValue) + { + assert(isPointer(lValue)); + accessChain.base = lValue; + } + + // set new base value as an r-value + void setAccessChainRValue(Id rValue) + { + accessChain.isRValue = true; + accessChain.base = rValue; + } + + // push offset onto the end of the chain + void accessChainPush(Id offset, AccessChain::CoherentFlags coherentFlags, unsigned int alignment) + { + accessChain.indexChain.push_back(offset); + accessChain.coherentFlags |= coherentFlags; + accessChain.alignment |= alignment; + } + + // push new swizzle onto the end of any existing swizzle, merging into a single swizzle + void accessChainPushSwizzle(std::vector& swizzle, Id preSwizzleBaseType, + AccessChain::CoherentFlags coherentFlags, unsigned int alignment); + + // push a dynamic component selection onto the access chain, only applicable with a + // non-trivial swizzle or no swizzle + void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, + unsigned int alignment) + { + if (accessChain.swizzle.size() != 1) { + accessChain.component = component; + if (accessChain.preSwizzleBaseType == NoType) + accessChain.preSwizzleBaseType = preSwizzleBaseType; + } + accessChain.coherentFlags |= coherentFlags; + accessChain.alignment |= alignment; + } + + // use accessChain and swizzle to store value + void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + + // use accessChain and swizzle to load an r-value + Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType, + spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, + unsigned int alignment = 0); + + // Return whether or not the access chain can be represented in SPIR-V + // as an l-value. + // E.g., a[3].yx cannot be, while a[3].y and a[3].y[x] can be. + bool isSpvLvalue() const { return accessChain.swizzle.size() <= 1; } + + // get the direct pointer for an l-value + Id accessChainGetLValue(); + + // Get the inferred SPIR-V type of the result of the current access chain, + // based on the type of the base and the chain of dereferences. + Id accessChainGetInferredType(); + + // Add capabilities, extensions, remove unneeded decorations, etc., + // based on the resulting SPIR-V. + void postProcess(); + + // Prune unreachable blocks in the CFG and remove unneeded decorations. + void postProcessCFG(); + +#ifndef GLSLANG_WEB + // Add capabilities, extensions based on instructions in the module. + void postProcessFeatures(); + // Hook to visit each instruction in a block in a function + void postProcess(Instruction&); + // Hook to visit each non-32-bit sized float/int operation in a block. + void postProcessType(const Instruction&, spv::Id typeId); +#endif + + void dump(std::vector&) const; + + void createBranch(Block* block); + void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock); + void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, + const std::vector& operands); + + // Sets to generate opcode for specialization constants. + void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; } + // Sets to generate opcode for non-specialization constants (normal mode). + void setToNormalCodeGenMode() { generatingOpCodeForSpecConst = false; } + // Check if the builder is generating code for spec constants. + bool isInSpecConstCodeGenMode() { return generatingOpCodeForSpecConst; } + + protected: + Id makeIntConstant(Id typeId, unsigned value, bool specConstant); + Id makeInt64Constant(Id typeId, unsigned long long value, bool specConstant); + Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value); + Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2); + Id findCompositeConstant(Op typeClass, Id typeId, const std::vector& comps); + Id findStructConstant(Id typeId, const std::vector& comps); + Id collapseAccessChain(); + void remapDynamicSwizzle(); + void transferAccessChainSwizzle(bool dynamic); + void simplifyAccessChainSwizzle(); + void createAndSetNoPredecessorBlock(const char*); + void createSelectionMerge(Block* mergeBlock, unsigned int control); + void dumpSourceInstructions(std::vector&) const; + void dumpSourceInstructions(const spv::Id fileId, const std::string& text, std::vector&) const; + void dumpInstructions(std::vector&, const std::vector >&) const; + void dumpModuleProcesses(std::vector&) const; + spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) + const; + + unsigned int spvVersion; // the version of SPIR-V to emit in the header + SourceLanguage source; + int sourceVersion; + spv::Id sourceFileStringId; + std::string sourceText; + int currentLine; + const char* currentFile; + bool emitOpLines; + std::set extensions; + std::vector sourceExtensions; + std::vector moduleProcesses; + AddressingModel addressModel; + MemoryModel memoryModel; + std::set capabilities; + int builderNumber; + Module module; + Block* buildPoint; + Id uniqueId; + Function* entryPointFunction; + bool generatingOpCodeForSpecConst; + AccessChain accessChain; + + // special blocks of instructions for output + std::vector > strings; + std::vector > imports; + std::vector > entryPoints; + std::vector > executionModes; + std::vector > names; + std::vector > decorations; + std::vector > constantsTypesGlobals; + std::vector > externals; + std::vector > functions; + + // not output, internally used for quick & dirty canonical (unique) creation + + // map type opcodes to constant inst. + std::unordered_map> groupedConstants; + // map struct-id to constant instructions + std::unordered_map> groupedStructConstants; + // map type opcodes to type instructions + std::unordered_map> groupedTypes; + + // stack of switches + std::stack switchMerges; + + // Our loop stack. + std::stack loops; + + // map from strings to their string ids + std::unordered_map stringIds; + + // map from include file name ids to their contents + std::map includeFiles; + + // The stream for outputting warnings and errors. + SpvBuildLogger* logger; +}; // end Builder class + +}; // end spv namespace + +#endif // SpvBuilder_H diff --git a/mac/include/SPIRV/SpvTools.h b/mac/include/SPIRV/SpvTools.h new file mode 100644 index 00000000..59c914da --- /dev/null +++ b/mac/include/SPIRV/SpvTools.h @@ -0,0 +1,82 @@ +// +// Copyright (C) 2014-2016 LunarG, Inc. +// Copyright (C) 2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Call into SPIRV-Tools to disassemble, validate, and optimize. +// + +#pragma once +#ifndef GLSLANG_SPV_TOOLS_H +#define GLSLANG_SPV_TOOLS_H + +#ifdef ENABLE_OPT +#include +#include +#endif + +#include "glslang/MachineIndependent/localintermediate.h" +#include "Logger.h" + +namespace glslang { + +struct SpvOptions { + SpvOptions() : generateDebugInfo(false), disableOptimizer(true), + optimizeSize(false), disassemble(false), validate(false) { } + bool generateDebugInfo; + bool disableOptimizer; + bool optimizeSize; + bool disassemble; + bool validate; +}; + +#ifdef ENABLE_OPT + +// Use the SPIRV-Tools disassembler to print SPIR-V. +void SpirvToolsDisassemble(std::ostream& out, const std::vector& spirv); + +// Apply the SPIRV-Tools validator to generated SPIR-V. +void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger*, bool prelegalization); + +// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of +// legalizing HLSL SPIR-V. +void SpirvToolsLegalize(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger*, const SpvOptions*); + +#endif + +} // end namespace glslang + +#endif // GLSLANG_SPV_TOOLS_H diff --git a/mac/include/SPIRV/bitutils.h b/mac/include/SPIRV/bitutils.h new file mode 100644 index 00000000..22e44cec --- /dev/null +++ b/mac/include/SPIRV/bitutils.h @@ -0,0 +1,81 @@ +// Copyright (c) 2015-2016 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef LIBSPIRV_UTIL_BITUTILS_H_ +#define LIBSPIRV_UTIL_BITUTILS_H_ + +#include +#include + +namespace spvutils { + +// Performs a bitwise copy of source to the destination type Dest. +template +Dest BitwiseCast(Src source) { + Dest dest; + static_assert(sizeof(source) == sizeof(dest), + "BitwiseCast: Source and destination must have the same size"); + std::memcpy(static_cast(&dest), &source, sizeof(dest)); + return dest; +} + +// SetBits returns an integer of type with bits set +// for position through , counting from the least +// significant bit. In particular when Num == 0, no positions are set to 1. +// A static assert will be triggered if First + Num > sizeof(T) * 8, that is, +// a bit that will not fit in the underlying type is set. +template +struct SetBits { + static_assert(First < sizeof(T) * 8, + "Tried to set a bit that is shifted too far."); + const static T get = (T(1) << First) | SetBits::get; +}; + +template +struct SetBits { + const static T get = T(0); +}; + +// This is all compile-time so we can put our tests right here. +static_assert(SetBits::get == uint32_t(0x00000000), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x00000001), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x80000000), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x00000006), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0xc0000000), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x7FFFFFFF), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0xFFFFFFFF), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0xFFFF0000), + "SetBits failed"); + +static_assert(SetBits::get == uint64_t(0x0000000000000001LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0x8000000000000000LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0xc000000000000000LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0x0000000080000000LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0x00000000FFFF0000LL), + "SetBits failed"); + +} // namespace spvutils + +#endif // LIBSPIRV_UTIL_BITUTILS_H_ diff --git a/mac/include/SPIRV/disassemble.h b/mac/include/SPIRV/disassemble.h new file mode 100644 index 00000000..b6a46357 --- /dev/null +++ b/mac/include/SPIRV/disassemble.h @@ -0,0 +1,53 @@ +// +// Copyright (C) 2014-2015 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Disassembler for SPIR-V. +// + +#pragma once +#ifndef disassembler_H +#define disassembler_H + +#include +#include + +namespace spv { + + // disassemble with glslang custom disassembler + void Disassemble(std::ostream& out, const std::vector&); + +} // end namespace spv + +#endif // disassembler_H diff --git a/mac/include/SPIRV/doc.h b/mac/include/SPIRV/doc.h new file mode 100644 index 00000000..293256a2 --- /dev/null +++ b/mac/include/SPIRV/doc.h @@ -0,0 +1,258 @@ +// +// Copyright (C) 2014-2015 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Parameterize the SPIR-V enumerants. +// + +#pragma once + +#include "spirv.hpp" + +#include + +namespace spv { + +// Fill in all the parameters +void Parameterize(); + +// Return the English names of all the enums. +const char* SourceString(int); +const char* AddressingString(int); +const char* MemoryString(int); +const char* ExecutionModelString(int); +const char* ExecutionModeString(int); +const char* StorageClassString(int); +const char* DecorationString(int); +const char* BuiltInString(int); +const char* DimensionString(int); +const char* SelectControlString(int); +const char* LoopControlString(int); +const char* FunctionControlString(int); +const char* SamplerAddressingModeString(int); +const char* SamplerFilterModeString(int); +const char* ImageFormatString(int); +const char* ImageChannelOrderString(int); +const char* ImageChannelTypeString(int); +const char* ImageChannelDataTypeString(int type); +const char* ImageOperandsString(int format); +const char* ImageOperands(int); +const char* FPFastMathString(int); +const char* FPRoundingModeString(int); +const char* LinkageTypeString(int); +const char* FuncParamAttrString(int); +const char* AccessQualifierString(int); +const char* MemorySemanticsString(int); +const char* MemoryAccessString(int); +const char* ExecutionScopeString(int); +const char* GroupOperationString(int); +const char* KernelEnqueueFlagsString(int); +const char* KernelProfilingInfoString(int); +const char* CapabilityString(int); +const char* OpcodeString(int); +const char* ScopeString(int mem); + +// For grouping opcodes into subsections +enum OpcodeClass { + OpClassMisc, + OpClassDebug, + OpClassAnnotate, + OpClassExtension, + OpClassMode, + OpClassType, + OpClassConstant, + OpClassMemory, + OpClassFunction, + OpClassImage, + OpClassConvert, + OpClassComposite, + OpClassArithmetic, + OpClassBit, + OpClassRelationalLogical, + OpClassDerivative, + OpClassFlowControl, + OpClassAtomic, + OpClassPrimitive, + OpClassBarrier, + OpClassGroup, + OpClassDeviceSideEnqueue, + OpClassPipe, + + OpClassCount, + OpClassMissing // all instructions start out as missing +}; + +// For parameterizing operands. +enum OperandClass { + OperandNone, + OperandId, + OperandVariableIds, + OperandOptionalLiteral, + OperandOptionalLiteralString, + OperandVariableLiterals, + OperandVariableIdLiteral, + OperandVariableLiteralId, + OperandLiteralNumber, + OperandLiteralString, + OperandSource, + OperandExecutionModel, + OperandAddressing, + OperandMemory, + OperandExecutionMode, + OperandStorage, + OperandDimensionality, + OperandSamplerAddressingMode, + OperandSamplerFilterMode, + OperandSamplerImageFormat, + OperandImageChannelOrder, + OperandImageChannelDataType, + OperandImageOperands, + OperandFPFastMath, + OperandFPRoundingMode, + OperandLinkageType, + OperandAccessQualifier, + OperandFuncParamAttr, + OperandDecoration, + OperandBuiltIn, + OperandSelect, + OperandLoop, + OperandFunction, + OperandMemorySemantics, + OperandMemoryAccess, + OperandScope, + OperandGroupOperation, + OperandKernelEnqueueFlags, + OperandKernelProfilingInfo, + OperandCapability, + + OperandOpcode, + + OperandCount +}; + +// Any specific enum can have a set of capabilities that allow it: +typedef std::vector EnumCaps; + +// Parameterize a set of operands with their OperandClass(es) and descriptions. +class OperandParameters { +public: + OperandParameters() { } + void push(OperandClass oc, const char* d, bool opt = false) + { + opClass.push_back(oc); + desc.push_back(d); + optional.push_back(opt); + } + void setOptional(); + OperandClass getClass(int op) const { return opClass[op]; } + const char* getDesc(int op) const { return desc[op]; } + bool isOptional(int op) const { return optional[op]; } + int getNum() const { return (int)opClass.size(); } + +protected: + std::vector opClass; + std::vector desc; + std::vector optional; +}; + +// Parameterize an enumerant +class EnumParameters { +public: + EnumParameters() : desc(0) { } + const char* desc; +}; + +// Parameterize a set of enumerants that form an enum +class EnumDefinition : public EnumParameters { +public: + EnumDefinition() : + ceiling(0), bitmask(false), getName(0), enumParams(0), operandParams(0) { } + void set(int ceil, const char* (*name)(int), EnumParameters* ep, bool mask = false) + { + ceiling = ceil; + getName = name; + bitmask = mask; + enumParams = ep; + } + void setOperands(OperandParameters* op) { operandParams = op; } + int ceiling; // ceiling of enumerants + bool bitmask; // true if these enumerants combine into a bitmask + const char* (*getName)(int); // a function that returns the name for each enumerant value (or shift) + EnumParameters* enumParams; // parameters for each individual enumerant + OperandParameters* operandParams; // sets of operands +}; + +// Parameterize an instruction's logical format, including its known set of operands, +// per OperandParameters above. +class InstructionParameters { +public: + InstructionParameters() : + opDesc("TBD"), + opClass(OpClassMissing), + typePresent(true), // most normal, only exceptions have to be spelled out + resultPresent(true) // most normal, only exceptions have to be spelled out + { } + + void setResultAndType(bool r, bool t) + { + resultPresent = r; + typePresent = t; + } + + bool hasResult() const { return resultPresent != 0; } + bool hasType() const { return typePresent != 0; } + + const char* opDesc; + OpcodeClass opClass; + OperandParameters operands; + +protected: + int typePresent : 1; + int resultPresent : 1; +}; + +// The set of objects that hold all the instruction/operand +// parameterization information. +extern InstructionParameters InstructionDesc[]; + +// These hold definitions of the enumerants used for operands +extern EnumDefinition OperandClassParams[]; + +const char* GetOperandDesc(OperandClass operand); +void PrintImmediateRow(int imm, const char* name, const EnumParameters* enumParams, bool caps, bool hex = false); +const char* AccessQualifierString(int attr); + +void PrintOperands(const OperandParameters& operands, int reservedOperands); + +} // end namespace spv diff --git a/mac/include/SPIRV/hex_float.h b/mac/include/SPIRV/hex_float.h new file mode 100644 index 00000000..8be8e9f7 --- /dev/null +++ b/mac/include/SPIRV/hex_float.h @@ -0,0 +1,1078 @@ +// Copyright (c) 2015-2016 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef LIBSPIRV_UTIL_HEX_FLOAT_H_ +#define LIBSPIRV_UTIL_HEX_FLOAT_H_ + +#include +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) && _MSC_VER < 1800 +namespace std { +bool isnan(double f) +{ + return ::_isnan(f) != 0; +} +bool isinf(double f) +{ + return ::_finite(f) == 0; +} +} +#endif + +#include "bitutils.h" + +namespace spvutils { + +class Float16 { + public: + Float16(uint16_t v) : val(v) {} + Float16() {} + static bool isNan(const Float16& val) { + return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) != 0); + } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(const Float16& val) { + return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) == 0); + } + Float16(const Float16& other) { val = other.val; } + uint16_t get_value() const { return val; } + + // Returns the maximum normal value. + static Float16 max() { return Float16(0x7bff); } + // Returns the lowest normal value. + static Float16 lowest() { return Float16(0xfbff); } + + private: + uint16_t val; +}; + +// To specialize this type, you must override uint_type to define +// an unsigned integer that can fit your floating point type. +// You must also add a isNan function that returns true if +// a value is Nan. +template +struct FloatProxyTraits { + typedef void uint_type; +}; + +template <> +struct FloatProxyTraits { + typedef uint32_t uint_type; + static bool isNan(float f) { return std::isnan(f); } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(float f) { return std::isinf(f); } + // Returns the maximum normal value. + static float max() { return std::numeric_limits::max(); } + // Returns the lowest normal value. + static float lowest() { return std::numeric_limits::lowest(); } +}; + +template <> +struct FloatProxyTraits { + typedef uint64_t uint_type; + static bool isNan(double f) { return std::isnan(f); } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(double f) { return std::isinf(f); } + // Returns the maximum normal value. + static double max() { return std::numeric_limits::max(); } + // Returns the lowest normal value. + static double lowest() { return std::numeric_limits::lowest(); } +}; + +template <> +struct FloatProxyTraits { + typedef uint16_t uint_type; + static bool isNan(Float16 f) { return Float16::isNan(f); } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(Float16 f) { return Float16::isInfinity(f); } + // Returns the maximum normal value. + static Float16 max() { return Float16::max(); } + // Returns the lowest normal value. + static Float16 lowest() { return Float16::lowest(); } +}; + +// Since copying a floating point number (especially if it is NaN) +// does not guarantee that bits are preserved, this class lets us +// store the type and use it as a float when necessary. +template +class FloatProxy { + public: + typedef typename FloatProxyTraits::uint_type uint_type; + + // Since this is to act similar to the normal floats, + // do not initialize the data by default. + FloatProxy() {} + + // Intentionally non-explicit. This is a proxy type so + // implicit conversions allow us to use it more transparently. + FloatProxy(T val) { data_ = BitwiseCast(val); } + + // Intentionally non-explicit. This is a proxy type so + // implicit conversions allow us to use it more transparently. + FloatProxy(uint_type val) { data_ = val; } + + // This is helpful to have and is guaranteed not to stomp bits. + FloatProxy operator-() const { + return static_cast(data_ ^ + (uint_type(0x1) << (sizeof(T) * 8 - 1))); + } + + // Returns the data as a floating point value. + T getAsFloat() const { return BitwiseCast(data_); } + + // Returns the raw data. + uint_type data() const { return data_; } + + // Returns true if the value represents any type of NaN. + bool isNan() { return FloatProxyTraits::isNan(getAsFloat()); } + // Returns true if the value represents any type of infinity. + bool isInfinity() { return FloatProxyTraits::isInfinity(getAsFloat()); } + + // Returns the maximum normal value. + static FloatProxy max() { + return FloatProxy(FloatProxyTraits::max()); + } + // Returns the lowest normal value. + static FloatProxy lowest() { + return FloatProxy(FloatProxyTraits::lowest()); + } + + private: + uint_type data_; +}; + +template +bool operator==(const FloatProxy& first, const FloatProxy& second) { + return first.data() == second.data(); +} + +// Reads a FloatProxy value as a normal float from a stream. +template +std::istream& operator>>(std::istream& is, FloatProxy& value) { + T float_val; + is >> float_val; + value = FloatProxy(float_val); + return is; +} + +// This is an example traits. It is not meant to be used in practice, but will +// be the default for any non-specialized type. +template +struct HexFloatTraits { + // Integer type that can store this hex-float. + typedef void uint_type; + // Signed integer type that can store this hex-float. + typedef void int_type; + // The numerical type that this HexFloat represents. + typedef void underlying_type; + // The type needed to construct the underlying type. + typedef void native_type; + // The number of bits that are actually relevant in the uint_type. + // This allows us to deal with, for example, 24-bit values in a 32-bit + // integer. + static const uint32_t num_used_bits = 0; + // Number of bits that represent the exponent. + static const uint32_t num_exponent_bits = 0; + // Number of bits that represent the fractional part. + static const uint32_t num_fraction_bits = 0; + // The bias of the exponent. (How much we need to subtract from the stored + // value to get the correct value.) + static const uint32_t exponent_bias = 0; +}; + +// Traits for IEEE float. +// 1 sign bit, 8 exponent bits, 23 fractional bits. +template <> +struct HexFloatTraits> { + typedef uint32_t uint_type; + typedef int32_t int_type; + typedef FloatProxy underlying_type; + typedef float native_type; + static const uint_type num_used_bits = 32; + static const uint_type num_exponent_bits = 8; + static const uint_type num_fraction_bits = 23; + static const uint_type exponent_bias = 127; +}; + +// Traits for IEEE double. +// 1 sign bit, 11 exponent bits, 52 fractional bits. +template <> +struct HexFloatTraits> { + typedef uint64_t uint_type; + typedef int64_t int_type; + typedef FloatProxy underlying_type; + typedef double native_type; + static const uint_type num_used_bits = 64; + static const uint_type num_exponent_bits = 11; + static const uint_type num_fraction_bits = 52; + static const uint_type exponent_bias = 1023; +}; + +// Traits for IEEE half. +// 1 sign bit, 5 exponent bits, 10 fractional bits. +template <> +struct HexFloatTraits> { + typedef uint16_t uint_type; + typedef int16_t int_type; + typedef uint16_t underlying_type; + typedef uint16_t native_type; + static const uint_type num_used_bits = 16; + static const uint_type num_exponent_bits = 5; + static const uint_type num_fraction_bits = 10; + static const uint_type exponent_bias = 15; +}; + +enum round_direction { + kRoundToZero, + kRoundToNearestEven, + kRoundToPositiveInfinity, + kRoundToNegativeInfinity +}; + +// Template class that houses a floating pointer number. +// It exposes a number of constants based on the provided traits to +// assist in interpreting the bits of the value. +template > +class HexFloat { + public: + typedef typename Traits::uint_type uint_type; + typedef typename Traits::int_type int_type; + typedef typename Traits::underlying_type underlying_type; + typedef typename Traits::native_type native_type; + + explicit HexFloat(T f) : value_(f) {} + + T value() const { return value_; } + void set_value(T f) { value_ = f; } + + // These are all written like this because it is convenient to have + // compile-time constants for all of these values. + + // Pass-through values to save typing. + static const uint32_t num_used_bits = Traits::num_used_bits; + static const uint32_t exponent_bias = Traits::exponent_bias; + static const uint32_t num_exponent_bits = Traits::num_exponent_bits; + static const uint32_t num_fraction_bits = Traits::num_fraction_bits; + + // Number of bits to shift left to set the highest relevant bit. + static const uint32_t top_bit_left_shift = num_used_bits - 1; + // How many nibbles (hex characters) the fractional part takes up. + static const uint32_t fraction_nibbles = (num_fraction_bits + 3) / 4; + // If the fractional part does not fit evenly into a hex character (4-bits) + // then we have to left-shift to get rid of leading 0s. This is the amount + // we have to shift (might be 0). + static const uint32_t num_overflow_bits = + fraction_nibbles * 4 - num_fraction_bits; + + // The representation of the fraction, not the actual bits. This + // includes the leading bit that is usually implicit. + static const uint_type fraction_represent_mask = + spvutils::SetBits::get; + + // The topmost bit in the nibble-aligned fraction. + static const uint_type fraction_top_bit = + uint_type(1) << (num_fraction_bits + num_overflow_bits - 1); + + // The least significant bit in the exponent, which is also the bit + // immediately to the left of the significand. + static const uint_type first_exponent_bit = uint_type(1) + << (num_fraction_bits); + + // The mask for the encoded fraction. It does not include the + // implicit bit. + static const uint_type fraction_encode_mask = + spvutils::SetBits::get; + + // The bit that is used as a sign. + static const uint_type sign_mask = uint_type(1) << top_bit_left_shift; + + // The bits that represent the exponent. + static const uint_type exponent_mask = + spvutils::SetBits::get; + + // How far left the exponent is shifted. + static const uint32_t exponent_left_shift = num_fraction_bits; + + // How far from the right edge the fraction is shifted. + static const uint32_t fraction_right_shift = + static_cast(sizeof(uint_type) * 8) - num_fraction_bits; + + // The maximum representable unbiased exponent. + static const int_type max_exponent = + (exponent_mask >> num_fraction_bits) - exponent_bias; + // The minimum representable exponent for normalized numbers. + static const int_type min_exponent = -static_cast(exponent_bias); + + // Returns the bits associated with the value. + uint_type getBits() const { return spvutils::BitwiseCast(value_); } + + // Returns the bits associated with the value, without the leading sign bit. + uint_type getUnsignedBits() const { + return static_cast(spvutils::BitwiseCast(value_) & + ~sign_mask); + } + + // Returns the bits associated with the exponent, shifted to start at the + // lsb of the type. + const uint_type getExponentBits() const { + return static_cast((getBits() & exponent_mask) >> + num_fraction_bits); + } + + // Returns the exponent in unbiased form. This is the exponent in the + // human-friendly form. + const int_type getUnbiasedExponent() const { + return static_cast(getExponentBits() - exponent_bias); + } + + // Returns just the significand bits from the value. + const uint_type getSignificandBits() const { + return getBits() & fraction_encode_mask; + } + + // If the number was normalized, returns the unbiased exponent. + // If the number was denormal, normalize the exponent first. + const int_type getUnbiasedNormalizedExponent() const { + if ((getBits() & ~sign_mask) == 0) { // special case if everything is 0 + return 0; + } + int_type exp = getUnbiasedExponent(); + if (exp == min_exponent) { // We are in denorm land. + uint_type significand_bits = getSignificandBits(); + while ((significand_bits & (first_exponent_bit >> 1)) == 0) { + significand_bits = static_cast(significand_bits << 1); + exp = static_cast(exp - 1); + } + significand_bits &= fraction_encode_mask; + } + return exp; + } + + // Returns the signficand after it has been normalized. + const uint_type getNormalizedSignificand() const { + int_type unbiased_exponent = getUnbiasedNormalizedExponent(); + uint_type significand = getSignificandBits(); + for (int_type i = unbiased_exponent; i <= min_exponent; ++i) { + significand = static_cast(significand << 1); + } + significand &= fraction_encode_mask; + return significand; + } + + // Returns true if this number represents a negative value. + bool isNegative() const { return (getBits() & sign_mask) != 0; } + + // Sets this HexFloat from the individual components. + // Note this assumes EVERY significand is normalized, and has an implicit + // leading one. This means that the only way that this method will set 0, + // is if you set a number so denormalized that it underflows. + // Do not use this method with raw bits extracted from a subnormal number, + // since subnormals do not have an implicit leading 1 in the significand. + // The significand is also expected to be in the + // lowest-most num_fraction_bits of the uint_type. + // The exponent is expected to be unbiased, meaning an exponent of + // 0 actually means 0. + // If underflow_round_up is set, then on underflow, if a number is non-0 + // and would underflow, we round up to the smallest denorm. + void setFromSignUnbiasedExponentAndNormalizedSignificand( + bool negative, int_type exponent, uint_type significand, + bool round_denorm_up) { + bool significand_is_zero = significand == 0; + + if (exponent <= min_exponent) { + // If this was denormalized, then we have to shift the bit on, meaning + // the significand is not zero. + significand_is_zero = false; + significand |= first_exponent_bit; + significand = static_cast(significand >> 1); + } + + while (exponent < min_exponent) { + significand = static_cast(significand >> 1); + ++exponent; + } + + if (exponent == min_exponent) { + if (significand == 0 && !significand_is_zero && round_denorm_up) { + significand = static_cast(0x1); + } + } + + uint_type new_value = 0; + if (negative) { + new_value = static_cast(new_value | sign_mask); + } + exponent = static_cast(exponent + exponent_bias); + assert(exponent >= 0); + + // put it all together + exponent = static_cast((exponent << exponent_left_shift) & + exponent_mask); + significand = static_cast(significand & fraction_encode_mask); + new_value = static_cast(new_value | (exponent | significand)); + value_ = BitwiseCast(new_value); + } + + // Increments the significand of this number by the given amount. + // If this would spill the significand into the implicit bit, + // carry is set to true and the significand is shifted to fit into + // the correct location, otherwise carry is set to false. + // All significands and to_increment are assumed to be within the bounds + // for a valid significand. + static uint_type incrementSignificand(uint_type significand, + uint_type to_increment, bool* carry) { + significand = static_cast(significand + to_increment); + *carry = false; + if (significand & first_exponent_bit) { + *carry = true; + // The implicit 1-bit will have carried, so we should zero-out the + // top bit and shift back. + significand = static_cast(significand & ~first_exponent_bit); + significand = static_cast(significand >> 1); + } + return significand; + } + + // These exist because MSVC throws warnings on negative right-shifts + // even if they are not going to be executed. Eg: + // constant_number < 0? 0: constant_number + // These convert the negative left-shifts into right shifts. + + template + uint_type negatable_left_shift(int_type N, uint_type val) + { + if(N >= 0) + return val << N; + + return val >> -N; + } + + template + uint_type negatable_right_shift(int_type N, uint_type val) + { + if(N >= 0) + return val >> N; + + return val << -N; + } + + // Returns the significand, rounded to fit in a significand in + // other_T. This is shifted so that the most significant + // bit of the rounded number lines up with the most significant bit + // of the returned significand. + template + typename other_T::uint_type getRoundedNormalizedSignificand( + round_direction dir, bool* carry_bit) { + typedef typename other_T::uint_type other_uint_type; + static const int_type num_throwaway_bits = + static_cast(num_fraction_bits) - + static_cast(other_T::num_fraction_bits); + + static const uint_type last_significant_bit = + (num_throwaway_bits < 0) + ? 0 + : negatable_left_shift(num_throwaway_bits, 1u); + static const uint_type first_rounded_bit = + (num_throwaway_bits < 1) + ? 0 + : negatable_left_shift(num_throwaway_bits - 1, 1u); + + static const uint_type throwaway_mask_bits = + num_throwaway_bits > 0 ? num_throwaway_bits : 0; + static const uint_type throwaway_mask = + spvutils::SetBits::get; + + *carry_bit = false; + other_uint_type out_val = 0; + uint_type significand = getNormalizedSignificand(); + // If we are up-casting, then we just have to shift to the right location. + if (num_throwaway_bits <= 0) { + out_val = static_cast(significand); + uint_type shift_amount = static_cast(-num_throwaway_bits); + out_val = static_cast(out_val << shift_amount); + return out_val; + } + + // If every non-representable bit is 0, then we don't have any casting to + // do. + if ((significand & throwaway_mask) == 0) { + return static_cast( + negatable_right_shift(num_throwaway_bits, significand)); + } + + bool round_away_from_zero = false; + // We actually have to narrow the significand here, so we have to follow the + // rounding rules. + switch (dir) { + case kRoundToZero: + break; + case kRoundToPositiveInfinity: + round_away_from_zero = !isNegative(); + break; + case kRoundToNegativeInfinity: + round_away_from_zero = isNegative(); + break; + case kRoundToNearestEven: + // Have to round down, round bit is 0 + if ((first_rounded_bit & significand) == 0) { + break; + } + if (((significand & throwaway_mask) & ~first_rounded_bit) != 0) { + // If any subsequent bit of the rounded portion is non-0 then we round + // up. + round_away_from_zero = true; + break; + } + // We are exactly half-way between 2 numbers, pick even. + if ((significand & last_significant_bit) != 0) { + // 1 for our last bit, round up. + round_away_from_zero = true; + break; + } + break; + } + + if (round_away_from_zero) { + return static_cast( + negatable_right_shift(num_throwaway_bits, incrementSignificand( + significand, last_significant_bit, carry_bit))); + } else { + return static_cast( + negatable_right_shift(num_throwaway_bits, significand)); + } + } + + // Casts this value to another HexFloat. If the cast is widening, + // then round_dir is ignored. If the cast is narrowing, then + // the result is rounded in the direction specified. + // This number will retain Nan and Inf values. + // It will also saturate to Inf if the number overflows, and + // underflow to (0 or min depending on rounding) if the number underflows. + template + void castTo(other_T& other, round_direction round_dir) { + other = other_T(static_cast(0)); + bool negate = isNegative(); + if (getUnsignedBits() == 0) { + if (negate) { + other.set_value(-other.value()); + } + return; + } + uint_type significand = getSignificandBits(); + bool carried = false; + typename other_T::uint_type rounded_significand = + getRoundedNormalizedSignificand(round_dir, &carried); + + int_type exponent = getUnbiasedExponent(); + if (exponent == min_exponent) { + // If we are denormal, normalize the exponent, so that we can encode + // easily. + exponent = static_cast(exponent + 1); + for (uint_type check_bit = first_exponent_bit >> 1; check_bit != 0; + check_bit = static_cast(check_bit >> 1)) { + exponent = static_cast(exponent - 1); + if (check_bit & significand) break; + } + } + + bool is_nan = + (getBits() & exponent_mask) == exponent_mask && significand != 0; + bool is_inf = + !is_nan && + ((exponent + carried) > static_cast(other_T::exponent_bias) || + (significand == 0 && (getBits() & exponent_mask) == exponent_mask)); + + // If we are Nan or Inf we should pass that through. + if (is_inf) { + other.set_value(BitwiseCast( + static_cast( + (negate ? other_T::sign_mask : 0) | other_T::exponent_mask))); + return; + } + if (is_nan) { + typename other_T::uint_type shifted_significand; + shifted_significand = static_cast( + negatable_left_shift( + static_cast(other_T::num_fraction_bits) - + static_cast(num_fraction_bits), significand)); + + // We are some sort of Nan. We try to keep the bit-pattern of the Nan + // as close as possible. If we had to shift off bits so we are 0, then we + // just set the last bit. + other.set_value(BitwiseCast( + static_cast( + (negate ? other_T::sign_mask : 0) | other_T::exponent_mask | + (shifted_significand == 0 ? 0x1 : shifted_significand)))); + return; + } + + bool round_underflow_up = + isNegative() ? round_dir == kRoundToNegativeInfinity + : round_dir == kRoundToPositiveInfinity; + typedef typename other_T::int_type other_int_type; + // setFromSignUnbiasedExponentAndNormalizedSignificand will + // zero out any underflowing value (but retain the sign). + other.setFromSignUnbiasedExponentAndNormalizedSignificand( + negate, static_cast(exponent), rounded_significand, + round_underflow_up); + return; + } + + private: + T value_; + + static_assert(num_used_bits == + Traits::num_exponent_bits + Traits::num_fraction_bits + 1, + "The number of bits do not fit"); + static_assert(sizeof(T) == sizeof(uint_type), "The type sizes do not match"); +}; + +// Returns 4 bits represented by the hex character. +inline uint8_t get_nibble_from_character(int character) { + const char* dec = "0123456789"; + const char* lower = "abcdef"; + const char* upper = "ABCDEF"; + const char* p = nullptr; + if ((p = strchr(dec, character))) { + return static_cast(p - dec); + } else if ((p = strchr(lower, character))) { + return static_cast(p - lower + 0xa); + } else if ((p = strchr(upper, character))) { + return static_cast(p - upper + 0xa); + } + + assert(false && "This was called with a non-hex character"); + return 0; +} + +// Outputs the given HexFloat to the stream. +template +std::ostream& operator<<(std::ostream& os, const HexFloat& value) { + typedef HexFloat HF; + typedef typename HF::uint_type uint_type; + typedef typename HF::int_type int_type; + + static_assert(HF::num_used_bits != 0, + "num_used_bits must be non-zero for a valid float"); + static_assert(HF::num_exponent_bits != 0, + "num_exponent_bits must be non-zero for a valid float"); + static_assert(HF::num_fraction_bits != 0, + "num_fractin_bits must be non-zero for a valid float"); + + const uint_type bits = spvutils::BitwiseCast(value.value()); + const char* const sign = (bits & HF::sign_mask) ? "-" : ""; + const uint_type exponent = static_cast( + (bits & HF::exponent_mask) >> HF::num_fraction_bits); + + uint_type fraction = static_cast((bits & HF::fraction_encode_mask) + << HF::num_overflow_bits); + + const bool is_zero = exponent == 0 && fraction == 0; + const bool is_denorm = exponent == 0 && !is_zero; + + // exponent contains the biased exponent we have to convert it back into + // the normal range. + int_type int_exponent = static_cast(exponent - HF::exponent_bias); + // If the number is all zeros, then we actually have to NOT shift the + // exponent. + int_exponent = is_zero ? 0 : int_exponent; + + // If we are denorm, then start shifting, and decreasing the exponent until + // our leading bit is 1. + + if (is_denorm) { + while ((fraction & HF::fraction_top_bit) == 0) { + fraction = static_cast(fraction << 1); + int_exponent = static_cast(int_exponent - 1); + } + // Since this is denormalized, we have to consume the leading 1 since it + // will end up being implicit. + fraction = static_cast(fraction << 1); // eat the leading 1 + fraction &= HF::fraction_represent_mask; + } + + uint_type fraction_nibbles = HF::fraction_nibbles; + // We do not have to display any trailing 0s, since this represents the + // fractional part. + while (fraction_nibbles > 0 && (fraction & 0xF) == 0) { + // Shift off any trailing values; + fraction = static_cast(fraction >> 4); + --fraction_nibbles; + } + + const auto saved_flags = os.flags(); + const auto saved_fill = os.fill(); + + os << sign << "0x" << (is_zero ? '0' : '1'); + if (fraction_nibbles) { + // Make sure to keep the leading 0s in place, since this is the fractional + // part. + os << "." << std::setw(static_cast(fraction_nibbles)) + << std::setfill('0') << std::hex << fraction; + } + os << "p" << std::dec << (int_exponent >= 0 ? "+" : "") << int_exponent; + + os.flags(saved_flags); + os.fill(saved_fill); + + return os; +} + +// Returns true if negate_value is true and the next character on the +// input stream is a plus or minus sign. In that case we also set the fail bit +// on the stream and set the value to the zero value for its type. +template +inline bool RejectParseDueToLeadingSign(std::istream& is, bool negate_value, + HexFloat& value) { + if (negate_value) { + auto next_char = is.peek(); + if (next_char == '-' || next_char == '+') { + // Fail the parse. Emulate standard behaviour by setting the value to + // the zero value, and set the fail bit on the stream. + value = HexFloat(typename HexFloat::uint_type(0)); + is.setstate(std::ios_base::failbit); + return true; + } + } + return false; +} + +// Parses a floating point number from the given stream and stores it into the +// value parameter. +// If negate_value is true then the number may not have a leading minus or +// plus, and if it successfully parses, then the number is negated before +// being stored into the value parameter. +// If the value cannot be correctly parsed or overflows the target floating +// point type, then set the fail bit on the stream. +// TODO(dneto): Promise C++11 standard behavior in how the value is set in +// the error case, but only after all target platforms implement it correctly. +// In particular, the Microsoft C++ runtime appears to be out of spec. +template +inline std::istream& ParseNormalFloat(std::istream& is, bool negate_value, + HexFloat& value) { + if (RejectParseDueToLeadingSign(is, negate_value, value)) { + return is; + } + T val; + is >> val; + if (negate_value) { + val = -val; + } + value.set_value(val); + // In the failure case, map -0.0 to 0.0. + if (is.fail() && value.getUnsignedBits() == 0u) { + value = HexFloat(typename HexFloat::uint_type(0)); + } + if (val.isInfinity()) { + // Fail the parse. Emulate standard behaviour by setting the value to + // the closest normal value, and set the fail bit on the stream. + value.set_value((value.isNegative() || negate_value) ? T::lowest() + : T::max()); + is.setstate(std::ios_base::failbit); + } + return is; +} + +// Specialization of ParseNormalFloat for FloatProxy values. +// This will parse the float as it were a 32-bit floating point number, +// and then round it down to fit into a Float16 value. +// The number is rounded towards zero. +// If negate_value is true then the number may not have a leading minus or +// plus, and if it successfully parses, then the number is negated before +// being stored into the value parameter. +// If the value cannot be correctly parsed or overflows the target floating +// point type, then set the fail bit on the stream. +// TODO(dneto): Promise C++11 standard behavior in how the value is set in +// the error case, but only after all target platforms implement it correctly. +// In particular, the Microsoft C++ runtime appears to be out of spec. +template <> +inline std::istream& +ParseNormalFloat, HexFloatTraits>>( + std::istream& is, bool negate_value, + HexFloat, HexFloatTraits>>& value) { + // First parse as a 32-bit float. + HexFloat> float_val(0.0f); + ParseNormalFloat(is, negate_value, float_val); + + // Then convert to 16-bit float, saturating at infinities, and + // rounding toward zero. + float_val.castTo(value, kRoundToZero); + + // Overflow on 16-bit behaves the same as for 32- and 64-bit: set the + // fail bit and set the lowest or highest value. + if (Float16::isInfinity(value.value().getAsFloat())) { + value.set_value(value.isNegative() ? Float16::lowest() : Float16::max()); + is.setstate(std::ios_base::failbit); + } + return is; +} + +// Reads a HexFloat from the given stream. +// If the float is not encoded as a hex-float then it will be parsed +// as a regular float. +// This may fail if your stream does not support at least one unget. +// Nan values can be encoded with "0x1.p+exponent_bias". +// This would normally overflow a float and round to +// infinity but this special pattern is the exact representation for a NaN, +// and therefore is actually encoded as the correct NaN. To encode inf, +// either 0x0p+exponent_bias can be specified or any exponent greater than +// exponent_bias. +// Examples using IEEE 32-bit float encoding. +// 0x1.0p+128 (+inf) +// -0x1.0p-128 (-inf) +// +// 0x1.1p+128 (+Nan) +// -0x1.1p+128 (-Nan) +// +// 0x1p+129 (+inf) +// -0x1p+129 (-inf) +template +std::istream& operator>>(std::istream& is, HexFloat& value) { + using HF = HexFloat; + using uint_type = typename HF::uint_type; + using int_type = typename HF::int_type; + + value.set_value(static_cast(0.f)); + + if (is.flags() & std::ios::skipws) { + // If the user wants to skip whitespace , then we should obey that. + while (std::isspace(is.peek())) { + is.get(); + } + } + + auto next_char = is.peek(); + bool negate_value = false; + + if (next_char != '-' && next_char != '0') { + return ParseNormalFloat(is, negate_value, value); + } + + if (next_char == '-') { + negate_value = true; + is.get(); + next_char = is.peek(); + } + + if (next_char == '0') { + is.get(); // We may have to unget this. + auto maybe_hex_start = is.peek(); + if (maybe_hex_start != 'x' && maybe_hex_start != 'X') { + is.unget(); + return ParseNormalFloat(is, negate_value, value); + } else { + is.get(); // Throw away the 'x'; + } + } else { + return ParseNormalFloat(is, negate_value, value); + } + + // This "looks" like a hex-float so treat it as one. + bool seen_p = false; + bool seen_dot = false; + uint_type fraction_index = 0; + + uint_type fraction = 0; + int_type exponent = HF::exponent_bias; + + // Strip off leading zeros so we don't have to special-case them later. + while ((next_char = is.peek()) == '0') { + is.get(); + } + + bool is_denorm = + true; // Assume denorm "representation" until we hear otherwise. + // NB: This does not mean the value is actually denorm, + // it just means that it was written 0. + bool bits_written = false; // Stays false until we write a bit. + while (!seen_p && !seen_dot) { + // Handle characters that are left of the fractional part. + if (next_char == '.') { + seen_dot = true; + } else if (next_char == 'p') { + seen_p = true; + } else if (::isxdigit(next_char)) { + // We know this is not denormalized since we have stripped all leading + // zeroes and we are not a ".". + is_denorm = false; + int number = get_nibble_from_character(next_char); + for (int i = 0; i < 4; ++i, number <<= 1) { + uint_type write_bit = (number & 0x8) ? 0x1 : 0x0; + if (bits_written) { + // If we are here the bits represented belong in the fractional + // part of the float, and we have to adjust the exponent accordingly. + fraction = static_cast( + fraction | + static_cast( + write_bit << (HF::top_bit_left_shift - fraction_index++))); + exponent = static_cast(exponent + 1); + } + bits_written |= write_bit != 0; + } + } else { + // We have not found our exponent yet, so we have to fail. + is.setstate(std::ios::failbit); + return is; + } + is.get(); + next_char = is.peek(); + } + bits_written = false; + while (seen_dot && !seen_p) { + // Handle only fractional parts now. + if (next_char == 'p') { + seen_p = true; + } else if (::isxdigit(next_char)) { + int number = get_nibble_from_character(next_char); + for (int i = 0; i < 4; ++i, number <<= 1) { + uint_type write_bit = (number & 0x8) ? 0x01 : 0x00; + bits_written |= write_bit != 0; + if (is_denorm && !bits_written) { + // Handle modifying the exponent here this way we can handle + // an arbitrary number of hex values without overflowing our + // integer. + exponent = static_cast(exponent - 1); + } else { + fraction = static_cast( + fraction | + static_cast( + write_bit << (HF::top_bit_left_shift - fraction_index++))); + } + } + } else { + // We still have not found our 'p' exponent yet, so this is not a valid + // hex-float. + is.setstate(std::ios::failbit); + return is; + } + is.get(); + next_char = is.peek(); + } + + bool seen_sign = false; + int8_t exponent_sign = 1; + int_type written_exponent = 0; + while (true) { + if ((next_char == '-' || next_char == '+')) { + if (seen_sign) { + is.setstate(std::ios::failbit); + return is; + } + seen_sign = true; + exponent_sign = (next_char == '-') ? -1 : 1; + } else if (::isdigit(next_char)) { + // Hex-floats express their exponent as decimal. + written_exponent = static_cast(written_exponent * 10); + written_exponent = + static_cast(written_exponent + (next_char - '0')); + } else { + break; + } + is.get(); + next_char = is.peek(); + } + + written_exponent = static_cast(written_exponent * exponent_sign); + exponent = static_cast(exponent + written_exponent); + + bool is_zero = is_denorm && (fraction == 0); + if (is_denorm && !is_zero) { + fraction = static_cast(fraction << 1); + exponent = static_cast(exponent - 1); + } else if (is_zero) { + exponent = 0; + } + + if (exponent <= 0 && !is_zero) { + fraction = static_cast(fraction >> 1); + fraction |= static_cast(1) << HF::top_bit_left_shift; + } + + fraction = (fraction >> HF::fraction_right_shift) & HF::fraction_encode_mask; + + const int_type max_exponent = + SetBits::get; + + // Handle actual denorm numbers + while (exponent < 0 && !is_zero) { + fraction = static_cast(fraction >> 1); + exponent = static_cast(exponent + 1); + + fraction &= HF::fraction_encode_mask; + if (fraction == 0) { + // We have underflowed our fraction. We should clamp to zero. + is_zero = true; + exponent = 0; + } + } + + // We have overflowed so we should be inf/-inf. + if (exponent > max_exponent) { + exponent = max_exponent; + fraction = 0; + } + + uint_type output_bits = static_cast( + static_cast(negate_value ? 1 : 0) << HF::top_bit_left_shift); + output_bits |= fraction; + + uint_type shifted_exponent = static_cast( + static_cast(exponent << HF::exponent_left_shift) & + HF::exponent_mask); + output_bits |= shifted_exponent; + + T output_float = spvutils::BitwiseCast(output_bits); + value.set_value(output_float); + + return is; +} + +// Writes a FloatProxy value to a stream. +// Zero and normal numbers are printed in the usual notation, but with +// enough digits to fully reproduce the value. Other values (subnormal, +// NaN, and infinity) are printed as a hex float. +template +std::ostream& operator<<(std::ostream& os, const FloatProxy& value) { + auto float_val = value.getAsFloat(); + switch (std::fpclassify(float_val)) { + case FP_ZERO: + case FP_NORMAL: { + auto saved_precision = os.precision(); + os.precision(std::numeric_limits::digits10); + os << float_val; + os.precision(saved_precision); + } break; + default: + os << HexFloat>(value); + break; + } + return os; +} + +template <> +inline std::ostream& operator<<(std::ostream& os, + const FloatProxy& value) { + os << HexFloat>(value); + return os; +} +} + +#endif // LIBSPIRV_UTIL_HEX_FLOAT_H_ diff --git a/mac/include/SPIRV/spirv.hpp b/mac/include/SPIRV/spirv.hpp new file mode 100644 index 00000000..dae36cf2 --- /dev/null +++ b/mac/include/SPIRV/spirv.hpp @@ -0,0 +1,2114 @@ +// Copyright (c) 2014-2020 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and/or associated documentation files (the "Materials"), +// to deal in the Materials without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Materials, and to permit persons to whom the +// Materials are furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +// IN THE MATERIALS. + +// This header is automatically generated by the same tool that creates +// the Binary Section of the SPIR-V specification. + +// Enumeration tokens for SPIR-V, in various styles: +// C, C++, C++11, JSON, Lua, Python, C#, D +// +// - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL +// - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL +// - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL +// - Lua will use tables, e.g.: spv.SourceLanguage.GLSL +// - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] +// - C# will use enum classes in the Specification class located in the "Spv" namespace, +// e.g.: Spv.Specification.SourceLanguage.GLSL +// - D will have tokens under the "spv" module, e.g: spv.SourceLanguage.GLSL +// +// Some tokens act like mask values, which can be OR'd together, +// while others are mutually exclusive. The mask-like ones have +// "Mask" in their name, and a parallel enum that has the shift +// amount (1 << x) for each corresponding enumerant. + +#ifndef spirv_HPP +#define spirv_HPP + +namespace spv { + +typedef unsigned int Id; + +#define SPV_VERSION 0x10500 +#define SPV_REVISION 3 + +static const unsigned int MagicNumber = 0x07230203; +static const unsigned int Version = 0x00010500; +static const unsigned int Revision = 3; +static const unsigned int OpCodeMask = 0xffff; +static const unsigned int WordCountShift = 16; + +enum SourceLanguage { + SourceLanguageUnknown = 0, + SourceLanguageESSL = 1, + SourceLanguageGLSL = 2, + SourceLanguageOpenCL_C = 3, + SourceLanguageOpenCL_CPP = 4, + SourceLanguageHLSL = 5, + SourceLanguageMax = 0x7fffffff, +}; + +enum ExecutionModel { + ExecutionModelVertex = 0, + ExecutionModelTessellationControl = 1, + ExecutionModelTessellationEvaluation = 2, + ExecutionModelGeometry = 3, + ExecutionModelFragment = 4, + ExecutionModelGLCompute = 5, + ExecutionModelKernel = 6, + ExecutionModelTaskNV = 5267, + ExecutionModelMeshNV = 5268, + ExecutionModelRayGenerationKHR = 5313, + ExecutionModelRayGenerationNV = 5313, + ExecutionModelIntersectionKHR = 5314, + ExecutionModelIntersectionNV = 5314, + ExecutionModelAnyHitKHR = 5315, + ExecutionModelAnyHitNV = 5315, + ExecutionModelClosestHitKHR = 5316, + ExecutionModelClosestHitNV = 5316, + ExecutionModelMissKHR = 5317, + ExecutionModelMissNV = 5317, + ExecutionModelCallableKHR = 5318, + ExecutionModelCallableNV = 5318, + ExecutionModelMax = 0x7fffffff, +}; + +enum AddressingModel { + AddressingModelLogical = 0, + AddressingModelPhysical32 = 1, + AddressingModelPhysical64 = 2, + AddressingModelPhysicalStorageBuffer64 = 5348, + AddressingModelPhysicalStorageBuffer64EXT = 5348, + AddressingModelMax = 0x7fffffff, +}; + +enum MemoryModel { + MemoryModelSimple = 0, + MemoryModelGLSL450 = 1, + MemoryModelOpenCL = 2, + MemoryModelVulkan = 3, + MemoryModelVulkanKHR = 3, + MemoryModelMax = 0x7fffffff, +}; + +enum ExecutionMode { + ExecutionModeInvocations = 0, + ExecutionModeSpacingEqual = 1, + ExecutionModeSpacingFractionalEven = 2, + ExecutionModeSpacingFractionalOdd = 3, + ExecutionModeVertexOrderCw = 4, + ExecutionModeVertexOrderCcw = 5, + ExecutionModePixelCenterInteger = 6, + ExecutionModeOriginUpperLeft = 7, + ExecutionModeOriginLowerLeft = 8, + ExecutionModeEarlyFragmentTests = 9, + ExecutionModePointMode = 10, + ExecutionModeXfb = 11, + ExecutionModeDepthReplacing = 12, + ExecutionModeDepthGreater = 14, + ExecutionModeDepthLess = 15, + ExecutionModeDepthUnchanged = 16, + ExecutionModeLocalSize = 17, + ExecutionModeLocalSizeHint = 18, + ExecutionModeInputPoints = 19, + ExecutionModeInputLines = 20, + ExecutionModeInputLinesAdjacency = 21, + ExecutionModeTriangles = 22, + ExecutionModeInputTrianglesAdjacency = 23, + ExecutionModeQuads = 24, + ExecutionModeIsolines = 25, + ExecutionModeOutputVertices = 26, + ExecutionModeOutputPoints = 27, + ExecutionModeOutputLineStrip = 28, + ExecutionModeOutputTriangleStrip = 29, + ExecutionModeVecTypeHint = 30, + ExecutionModeContractionOff = 31, + ExecutionModeInitializer = 33, + ExecutionModeFinalizer = 34, + ExecutionModeSubgroupSize = 35, + ExecutionModeSubgroupsPerWorkgroup = 36, + ExecutionModeSubgroupsPerWorkgroupId = 37, + ExecutionModeLocalSizeId = 38, + ExecutionModeLocalSizeHintId = 39, + ExecutionModePostDepthCoverage = 4446, + ExecutionModeDenormPreserve = 4459, + ExecutionModeDenormFlushToZero = 4460, + ExecutionModeSignedZeroInfNanPreserve = 4461, + ExecutionModeRoundingModeRTE = 4462, + ExecutionModeRoundingModeRTZ = 4463, + ExecutionModeStencilRefReplacingEXT = 5027, + ExecutionModeOutputLinesNV = 5269, + ExecutionModeOutputPrimitivesNV = 5270, + ExecutionModeDerivativeGroupQuadsNV = 5289, + ExecutionModeDerivativeGroupLinearNV = 5290, + ExecutionModeOutputTrianglesNV = 5298, + ExecutionModePixelInterlockOrderedEXT = 5366, + ExecutionModePixelInterlockUnorderedEXT = 5367, + ExecutionModeSampleInterlockOrderedEXT = 5368, + ExecutionModeSampleInterlockUnorderedEXT = 5369, + ExecutionModeShadingRateInterlockOrderedEXT = 5370, + ExecutionModeShadingRateInterlockUnorderedEXT = 5371, + ExecutionModeMax = 0x7fffffff, +}; + +enum StorageClass { + StorageClassUniformConstant = 0, + StorageClassInput = 1, + StorageClassUniform = 2, + StorageClassOutput = 3, + StorageClassWorkgroup = 4, + StorageClassCrossWorkgroup = 5, + StorageClassPrivate = 6, + StorageClassFunction = 7, + StorageClassGeneric = 8, + StorageClassPushConstant = 9, + StorageClassAtomicCounter = 10, + StorageClassImage = 11, + StorageClassStorageBuffer = 12, + StorageClassCallableDataKHR = 5328, + StorageClassCallableDataNV = 5328, + StorageClassIncomingCallableDataKHR = 5329, + StorageClassIncomingCallableDataNV = 5329, + StorageClassRayPayloadKHR = 5338, + StorageClassRayPayloadNV = 5338, + StorageClassHitAttributeKHR = 5339, + StorageClassHitAttributeNV = 5339, + StorageClassIncomingRayPayloadKHR = 5342, + StorageClassIncomingRayPayloadNV = 5342, + StorageClassShaderRecordBufferKHR = 5343, + StorageClassShaderRecordBufferNV = 5343, + StorageClassPhysicalStorageBuffer = 5349, + StorageClassPhysicalStorageBufferEXT = 5349, + StorageClassMax = 0x7fffffff, +}; + +enum Dim { + Dim1D = 0, + Dim2D = 1, + Dim3D = 2, + DimCube = 3, + DimRect = 4, + DimBuffer = 5, + DimSubpassData = 6, + DimMax = 0x7fffffff, +}; + +enum SamplerAddressingMode { + SamplerAddressingModeNone = 0, + SamplerAddressingModeClampToEdge = 1, + SamplerAddressingModeClamp = 2, + SamplerAddressingModeRepeat = 3, + SamplerAddressingModeRepeatMirrored = 4, + SamplerAddressingModeMax = 0x7fffffff, +}; + +enum SamplerFilterMode { + SamplerFilterModeNearest = 0, + SamplerFilterModeLinear = 1, + SamplerFilterModeMax = 0x7fffffff, +}; + +enum ImageFormat { + ImageFormatUnknown = 0, + ImageFormatRgba32f = 1, + ImageFormatRgba16f = 2, + ImageFormatR32f = 3, + ImageFormatRgba8 = 4, + ImageFormatRgba8Snorm = 5, + ImageFormatRg32f = 6, + ImageFormatRg16f = 7, + ImageFormatR11fG11fB10f = 8, + ImageFormatR16f = 9, + ImageFormatRgba16 = 10, + ImageFormatRgb10A2 = 11, + ImageFormatRg16 = 12, + ImageFormatRg8 = 13, + ImageFormatR16 = 14, + ImageFormatR8 = 15, + ImageFormatRgba16Snorm = 16, + ImageFormatRg16Snorm = 17, + ImageFormatRg8Snorm = 18, + ImageFormatR16Snorm = 19, + ImageFormatR8Snorm = 20, + ImageFormatRgba32i = 21, + ImageFormatRgba16i = 22, + ImageFormatRgba8i = 23, + ImageFormatR32i = 24, + ImageFormatRg32i = 25, + ImageFormatRg16i = 26, + ImageFormatRg8i = 27, + ImageFormatR16i = 28, + ImageFormatR8i = 29, + ImageFormatRgba32ui = 30, + ImageFormatRgba16ui = 31, + ImageFormatRgba8ui = 32, + ImageFormatR32ui = 33, + ImageFormatRgb10a2ui = 34, + ImageFormatRg32ui = 35, + ImageFormatRg16ui = 36, + ImageFormatRg8ui = 37, + ImageFormatR16ui = 38, + ImageFormatR8ui = 39, + ImageFormatMax = 0x7fffffff, +}; + +enum ImageChannelOrder { + ImageChannelOrderR = 0, + ImageChannelOrderA = 1, + ImageChannelOrderRG = 2, + ImageChannelOrderRA = 3, + ImageChannelOrderRGB = 4, + ImageChannelOrderRGBA = 5, + ImageChannelOrderBGRA = 6, + ImageChannelOrderARGB = 7, + ImageChannelOrderIntensity = 8, + ImageChannelOrderLuminance = 9, + ImageChannelOrderRx = 10, + ImageChannelOrderRGx = 11, + ImageChannelOrderRGBx = 12, + ImageChannelOrderDepth = 13, + ImageChannelOrderDepthStencil = 14, + ImageChannelOrdersRGB = 15, + ImageChannelOrdersRGBx = 16, + ImageChannelOrdersRGBA = 17, + ImageChannelOrdersBGRA = 18, + ImageChannelOrderABGR = 19, + ImageChannelOrderMax = 0x7fffffff, +}; + +enum ImageChannelDataType { + ImageChannelDataTypeSnormInt8 = 0, + ImageChannelDataTypeSnormInt16 = 1, + ImageChannelDataTypeUnormInt8 = 2, + ImageChannelDataTypeUnormInt16 = 3, + ImageChannelDataTypeUnormShort565 = 4, + ImageChannelDataTypeUnormShort555 = 5, + ImageChannelDataTypeUnormInt101010 = 6, + ImageChannelDataTypeSignedInt8 = 7, + ImageChannelDataTypeSignedInt16 = 8, + ImageChannelDataTypeSignedInt32 = 9, + ImageChannelDataTypeUnsignedInt8 = 10, + ImageChannelDataTypeUnsignedInt16 = 11, + ImageChannelDataTypeUnsignedInt32 = 12, + ImageChannelDataTypeHalfFloat = 13, + ImageChannelDataTypeFloat = 14, + ImageChannelDataTypeUnormInt24 = 15, + ImageChannelDataTypeUnormInt101010_2 = 16, + ImageChannelDataTypeMax = 0x7fffffff, +}; + +enum ImageOperandsShift { + ImageOperandsBiasShift = 0, + ImageOperandsLodShift = 1, + ImageOperandsGradShift = 2, + ImageOperandsConstOffsetShift = 3, + ImageOperandsOffsetShift = 4, + ImageOperandsConstOffsetsShift = 5, + ImageOperandsSampleShift = 6, + ImageOperandsMinLodShift = 7, + ImageOperandsMakeTexelAvailableShift = 8, + ImageOperandsMakeTexelAvailableKHRShift = 8, + ImageOperandsMakeTexelVisibleShift = 9, + ImageOperandsMakeTexelVisibleKHRShift = 9, + ImageOperandsNonPrivateTexelShift = 10, + ImageOperandsNonPrivateTexelKHRShift = 10, + ImageOperandsVolatileTexelShift = 11, + ImageOperandsVolatileTexelKHRShift = 11, + ImageOperandsSignExtendShift = 12, + ImageOperandsZeroExtendShift = 13, + ImageOperandsMax = 0x7fffffff, +}; + +enum ImageOperandsMask { + ImageOperandsMaskNone = 0, + ImageOperandsBiasMask = 0x00000001, + ImageOperandsLodMask = 0x00000002, + ImageOperandsGradMask = 0x00000004, + ImageOperandsConstOffsetMask = 0x00000008, + ImageOperandsOffsetMask = 0x00000010, + ImageOperandsConstOffsetsMask = 0x00000020, + ImageOperandsSampleMask = 0x00000040, + ImageOperandsMinLodMask = 0x00000080, + ImageOperandsMakeTexelAvailableMask = 0x00000100, + ImageOperandsMakeTexelAvailableKHRMask = 0x00000100, + ImageOperandsMakeTexelVisibleMask = 0x00000200, + ImageOperandsMakeTexelVisibleKHRMask = 0x00000200, + ImageOperandsNonPrivateTexelMask = 0x00000400, + ImageOperandsNonPrivateTexelKHRMask = 0x00000400, + ImageOperandsVolatileTexelMask = 0x00000800, + ImageOperandsVolatileTexelKHRMask = 0x00000800, + ImageOperandsSignExtendMask = 0x00001000, + ImageOperandsZeroExtendMask = 0x00002000, +}; + +enum FPFastMathModeShift { + FPFastMathModeNotNaNShift = 0, + FPFastMathModeNotInfShift = 1, + FPFastMathModeNSZShift = 2, + FPFastMathModeAllowRecipShift = 3, + FPFastMathModeFastShift = 4, + FPFastMathModeMax = 0x7fffffff, +}; + +enum FPFastMathModeMask { + FPFastMathModeMaskNone = 0, + FPFastMathModeNotNaNMask = 0x00000001, + FPFastMathModeNotInfMask = 0x00000002, + FPFastMathModeNSZMask = 0x00000004, + FPFastMathModeAllowRecipMask = 0x00000008, + FPFastMathModeFastMask = 0x00000010, +}; + +enum FPRoundingMode { + FPRoundingModeRTE = 0, + FPRoundingModeRTZ = 1, + FPRoundingModeRTP = 2, + FPRoundingModeRTN = 3, + FPRoundingModeMax = 0x7fffffff, +}; + +enum LinkageType { + LinkageTypeExport = 0, + LinkageTypeImport = 1, + LinkageTypeMax = 0x7fffffff, +}; + +enum AccessQualifier { + AccessQualifierReadOnly = 0, + AccessQualifierWriteOnly = 1, + AccessQualifierReadWrite = 2, + AccessQualifierMax = 0x7fffffff, +}; + +enum FunctionParameterAttribute { + FunctionParameterAttributeZext = 0, + FunctionParameterAttributeSext = 1, + FunctionParameterAttributeByVal = 2, + FunctionParameterAttributeSret = 3, + FunctionParameterAttributeNoAlias = 4, + FunctionParameterAttributeNoCapture = 5, + FunctionParameterAttributeNoWrite = 6, + FunctionParameterAttributeNoReadWrite = 7, + FunctionParameterAttributeMax = 0x7fffffff, +}; + +enum Decoration { + DecorationRelaxedPrecision = 0, + DecorationSpecId = 1, + DecorationBlock = 2, + DecorationBufferBlock = 3, + DecorationRowMajor = 4, + DecorationColMajor = 5, + DecorationArrayStride = 6, + DecorationMatrixStride = 7, + DecorationGLSLShared = 8, + DecorationGLSLPacked = 9, + DecorationCPacked = 10, + DecorationBuiltIn = 11, + DecorationNoPerspective = 13, + DecorationFlat = 14, + DecorationPatch = 15, + DecorationCentroid = 16, + DecorationSample = 17, + DecorationInvariant = 18, + DecorationRestrict = 19, + DecorationAliased = 20, + DecorationVolatile = 21, + DecorationConstant = 22, + DecorationCoherent = 23, + DecorationNonWritable = 24, + DecorationNonReadable = 25, + DecorationUniform = 26, + DecorationUniformId = 27, + DecorationSaturatedConversion = 28, + DecorationStream = 29, + DecorationLocation = 30, + DecorationComponent = 31, + DecorationIndex = 32, + DecorationBinding = 33, + DecorationDescriptorSet = 34, + DecorationOffset = 35, + DecorationXfbBuffer = 36, + DecorationXfbStride = 37, + DecorationFuncParamAttr = 38, + DecorationFPRoundingMode = 39, + DecorationFPFastMathMode = 40, + DecorationLinkageAttributes = 41, + DecorationNoContraction = 42, + DecorationInputAttachmentIndex = 43, + DecorationAlignment = 44, + DecorationMaxByteOffset = 45, + DecorationAlignmentId = 46, + DecorationMaxByteOffsetId = 47, + DecorationNoSignedWrap = 4469, + DecorationNoUnsignedWrap = 4470, + DecorationExplicitInterpAMD = 4999, + DecorationOverrideCoverageNV = 5248, + DecorationPassthroughNV = 5250, + DecorationViewportRelativeNV = 5252, + DecorationSecondaryViewportRelativeNV = 5256, + DecorationPerPrimitiveNV = 5271, + DecorationPerViewNV = 5272, + DecorationPerTaskNV = 5273, + DecorationPerVertexNV = 5285, + DecorationNonUniform = 5300, + DecorationNonUniformEXT = 5300, + DecorationRestrictPointer = 5355, + DecorationRestrictPointerEXT = 5355, + DecorationAliasedPointer = 5356, + DecorationAliasedPointerEXT = 5356, + DecorationCounterBuffer = 5634, + DecorationHlslCounterBufferGOOGLE = 5634, + DecorationHlslSemanticGOOGLE = 5635, + DecorationUserSemantic = 5635, + DecorationUserTypeGOOGLE = 5636, + DecorationMax = 0x7fffffff, +}; + +enum BuiltIn { + BuiltInPosition = 0, + BuiltInPointSize = 1, + BuiltInClipDistance = 3, + BuiltInCullDistance = 4, + BuiltInVertexId = 5, + BuiltInInstanceId = 6, + BuiltInPrimitiveId = 7, + BuiltInInvocationId = 8, + BuiltInLayer = 9, + BuiltInViewportIndex = 10, + BuiltInTessLevelOuter = 11, + BuiltInTessLevelInner = 12, + BuiltInTessCoord = 13, + BuiltInPatchVertices = 14, + BuiltInFragCoord = 15, + BuiltInPointCoord = 16, + BuiltInFrontFacing = 17, + BuiltInSampleId = 18, + BuiltInSamplePosition = 19, + BuiltInSampleMask = 20, + BuiltInFragDepth = 22, + BuiltInHelperInvocation = 23, + BuiltInNumWorkgroups = 24, + BuiltInWorkgroupSize = 25, + BuiltInWorkgroupId = 26, + BuiltInLocalInvocationId = 27, + BuiltInGlobalInvocationId = 28, + BuiltInLocalInvocationIndex = 29, + BuiltInWorkDim = 30, + BuiltInGlobalSize = 31, + BuiltInEnqueuedWorkgroupSize = 32, + BuiltInGlobalOffset = 33, + BuiltInGlobalLinearId = 34, + BuiltInSubgroupSize = 36, + BuiltInSubgroupMaxSize = 37, + BuiltInNumSubgroups = 38, + BuiltInNumEnqueuedSubgroups = 39, + BuiltInSubgroupId = 40, + BuiltInSubgroupLocalInvocationId = 41, + BuiltInVertexIndex = 42, + BuiltInInstanceIndex = 43, + BuiltInSubgroupEqMask = 4416, + BuiltInSubgroupEqMaskKHR = 4416, + BuiltInSubgroupGeMask = 4417, + BuiltInSubgroupGeMaskKHR = 4417, + BuiltInSubgroupGtMask = 4418, + BuiltInSubgroupGtMaskKHR = 4418, + BuiltInSubgroupLeMask = 4419, + BuiltInSubgroupLeMaskKHR = 4419, + BuiltInSubgroupLtMask = 4420, + BuiltInSubgroupLtMaskKHR = 4420, + BuiltInBaseVertex = 4424, + BuiltInBaseInstance = 4425, + BuiltInDrawIndex = 4426, + BuiltInDeviceIndex = 4438, + BuiltInViewIndex = 4440, + BuiltInBaryCoordNoPerspAMD = 4992, + BuiltInBaryCoordNoPerspCentroidAMD = 4993, + BuiltInBaryCoordNoPerspSampleAMD = 4994, + BuiltInBaryCoordSmoothAMD = 4995, + BuiltInBaryCoordSmoothCentroidAMD = 4996, + BuiltInBaryCoordSmoothSampleAMD = 4997, + BuiltInBaryCoordPullModelAMD = 4998, + BuiltInFragStencilRefEXT = 5014, + BuiltInViewportMaskNV = 5253, + BuiltInSecondaryPositionNV = 5257, + BuiltInSecondaryViewportMaskNV = 5258, + BuiltInPositionPerViewNV = 5261, + BuiltInViewportMaskPerViewNV = 5262, + BuiltInFullyCoveredEXT = 5264, + BuiltInTaskCountNV = 5274, + BuiltInPrimitiveCountNV = 5275, + BuiltInPrimitiveIndicesNV = 5276, + BuiltInClipDistancePerViewNV = 5277, + BuiltInCullDistancePerViewNV = 5278, + BuiltInLayerPerViewNV = 5279, + BuiltInMeshViewCountNV = 5280, + BuiltInMeshViewIndicesNV = 5281, + BuiltInBaryCoordNV = 5286, + BuiltInBaryCoordNoPerspNV = 5287, + BuiltInFragSizeEXT = 5292, + BuiltInFragmentSizeNV = 5292, + BuiltInFragInvocationCountEXT = 5293, + BuiltInInvocationsPerPixelNV = 5293, + BuiltInLaunchIdKHR = 5319, + BuiltInLaunchIdNV = 5319, + BuiltInLaunchSizeKHR = 5320, + BuiltInLaunchSizeNV = 5320, + BuiltInWorldRayOriginKHR = 5321, + BuiltInWorldRayOriginNV = 5321, + BuiltInWorldRayDirectionKHR = 5322, + BuiltInWorldRayDirectionNV = 5322, + BuiltInObjectRayOriginKHR = 5323, + BuiltInObjectRayOriginNV = 5323, + BuiltInObjectRayDirectionKHR = 5324, + BuiltInObjectRayDirectionNV = 5324, + BuiltInRayTminKHR = 5325, + BuiltInRayTminNV = 5325, + BuiltInRayTmaxKHR = 5326, + BuiltInRayTmaxNV = 5326, + BuiltInInstanceCustomIndexKHR = 5327, + BuiltInInstanceCustomIndexNV = 5327, + BuiltInObjectToWorldKHR = 5330, + BuiltInObjectToWorldNV = 5330, + BuiltInWorldToObjectKHR = 5331, + BuiltInWorldToObjectNV = 5331, + BuiltInHitTKHR = 5332, + BuiltInHitTNV = 5332, + BuiltInHitKindKHR = 5333, + BuiltInHitKindNV = 5333, + BuiltInIncomingRayFlagsKHR = 5351, + BuiltInIncomingRayFlagsNV = 5351, + BuiltInRayGeometryIndexKHR = 5352, + BuiltInWarpsPerSMNV = 5374, + BuiltInSMCountNV = 5375, + BuiltInWarpIDNV = 5376, + BuiltInSMIDNV = 5377, + BuiltInMax = 0x7fffffff, +}; + +enum SelectionControlShift { + SelectionControlFlattenShift = 0, + SelectionControlDontFlattenShift = 1, + SelectionControlMax = 0x7fffffff, +}; + +enum SelectionControlMask { + SelectionControlMaskNone = 0, + SelectionControlFlattenMask = 0x00000001, + SelectionControlDontFlattenMask = 0x00000002, +}; + +enum LoopControlShift { + LoopControlUnrollShift = 0, + LoopControlDontUnrollShift = 1, + LoopControlDependencyInfiniteShift = 2, + LoopControlDependencyLengthShift = 3, + LoopControlMinIterationsShift = 4, + LoopControlMaxIterationsShift = 5, + LoopControlIterationMultipleShift = 6, + LoopControlPeelCountShift = 7, + LoopControlPartialCountShift = 8, + LoopControlMax = 0x7fffffff, +}; + +enum LoopControlMask { + LoopControlMaskNone = 0, + LoopControlUnrollMask = 0x00000001, + LoopControlDontUnrollMask = 0x00000002, + LoopControlDependencyInfiniteMask = 0x00000004, + LoopControlDependencyLengthMask = 0x00000008, + LoopControlMinIterationsMask = 0x00000010, + LoopControlMaxIterationsMask = 0x00000020, + LoopControlIterationMultipleMask = 0x00000040, + LoopControlPeelCountMask = 0x00000080, + LoopControlPartialCountMask = 0x00000100, +}; + +enum FunctionControlShift { + FunctionControlInlineShift = 0, + FunctionControlDontInlineShift = 1, + FunctionControlPureShift = 2, + FunctionControlConstShift = 3, + FunctionControlMax = 0x7fffffff, +}; + +enum FunctionControlMask { + FunctionControlMaskNone = 0, + FunctionControlInlineMask = 0x00000001, + FunctionControlDontInlineMask = 0x00000002, + FunctionControlPureMask = 0x00000004, + FunctionControlConstMask = 0x00000008, +}; + +enum MemorySemanticsShift { + MemorySemanticsAcquireShift = 1, + MemorySemanticsReleaseShift = 2, + MemorySemanticsAcquireReleaseShift = 3, + MemorySemanticsSequentiallyConsistentShift = 4, + MemorySemanticsUniformMemoryShift = 6, + MemorySemanticsSubgroupMemoryShift = 7, + MemorySemanticsWorkgroupMemoryShift = 8, + MemorySemanticsCrossWorkgroupMemoryShift = 9, + MemorySemanticsAtomicCounterMemoryShift = 10, + MemorySemanticsImageMemoryShift = 11, + MemorySemanticsOutputMemoryShift = 12, + MemorySemanticsOutputMemoryKHRShift = 12, + MemorySemanticsMakeAvailableShift = 13, + MemorySemanticsMakeAvailableKHRShift = 13, + MemorySemanticsMakeVisibleShift = 14, + MemorySemanticsMakeVisibleKHRShift = 14, + MemorySemanticsVolatileShift = 15, + MemorySemanticsMax = 0x7fffffff, +}; + +enum MemorySemanticsMask { + MemorySemanticsMaskNone = 0, + MemorySemanticsAcquireMask = 0x00000002, + MemorySemanticsReleaseMask = 0x00000004, + MemorySemanticsAcquireReleaseMask = 0x00000008, + MemorySemanticsSequentiallyConsistentMask = 0x00000010, + MemorySemanticsUniformMemoryMask = 0x00000040, + MemorySemanticsSubgroupMemoryMask = 0x00000080, + MemorySemanticsWorkgroupMemoryMask = 0x00000100, + MemorySemanticsCrossWorkgroupMemoryMask = 0x00000200, + MemorySemanticsAtomicCounterMemoryMask = 0x00000400, + MemorySemanticsImageMemoryMask = 0x00000800, + MemorySemanticsOutputMemoryMask = 0x00001000, + MemorySemanticsOutputMemoryKHRMask = 0x00001000, + MemorySemanticsMakeAvailableMask = 0x00002000, + MemorySemanticsMakeAvailableKHRMask = 0x00002000, + MemorySemanticsMakeVisibleMask = 0x00004000, + MemorySemanticsMakeVisibleKHRMask = 0x00004000, + MemorySemanticsVolatileMask = 0x00008000, +}; + +enum MemoryAccessShift { + MemoryAccessVolatileShift = 0, + MemoryAccessAlignedShift = 1, + MemoryAccessNontemporalShift = 2, + MemoryAccessMakePointerAvailableShift = 3, + MemoryAccessMakePointerAvailableKHRShift = 3, + MemoryAccessMakePointerVisibleShift = 4, + MemoryAccessMakePointerVisibleKHRShift = 4, + MemoryAccessNonPrivatePointerShift = 5, + MemoryAccessNonPrivatePointerKHRShift = 5, + MemoryAccessMax = 0x7fffffff, +}; + +enum MemoryAccessMask { + MemoryAccessMaskNone = 0, + MemoryAccessVolatileMask = 0x00000001, + MemoryAccessAlignedMask = 0x00000002, + MemoryAccessNontemporalMask = 0x00000004, + MemoryAccessMakePointerAvailableMask = 0x00000008, + MemoryAccessMakePointerAvailableKHRMask = 0x00000008, + MemoryAccessMakePointerVisibleMask = 0x00000010, + MemoryAccessMakePointerVisibleKHRMask = 0x00000010, + MemoryAccessNonPrivatePointerMask = 0x00000020, + MemoryAccessNonPrivatePointerKHRMask = 0x00000020, +}; + +enum Scope { + ScopeCrossDevice = 0, + ScopeDevice = 1, + ScopeWorkgroup = 2, + ScopeSubgroup = 3, + ScopeInvocation = 4, + ScopeQueueFamily = 5, + ScopeQueueFamilyKHR = 5, + ScopeShaderCallKHR = 6, + ScopeMax = 0x7fffffff, +}; + +enum GroupOperation { + GroupOperationReduce = 0, + GroupOperationInclusiveScan = 1, + GroupOperationExclusiveScan = 2, + GroupOperationClusteredReduce = 3, + GroupOperationPartitionedReduceNV = 6, + GroupOperationPartitionedInclusiveScanNV = 7, + GroupOperationPartitionedExclusiveScanNV = 8, + GroupOperationMax = 0x7fffffff, +}; + +enum KernelEnqueueFlags { + KernelEnqueueFlagsNoWait = 0, + KernelEnqueueFlagsWaitKernel = 1, + KernelEnqueueFlagsWaitWorkGroup = 2, + KernelEnqueueFlagsMax = 0x7fffffff, +}; + +enum KernelProfilingInfoShift { + KernelProfilingInfoCmdExecTimeShift = 0, + KernelProfilingInfoMax = 0x7fffffff, +}; + +enum KernelProfilingInfoMask { + KernelProfilingInfoMaskNone = 0, + KernelProfilingInfoCmdExecTimeMask = 0x00000001, +}; + +enum Capability { + CapabilityMatrix = 0, + CapabilityShader = 1, + CapabilityGeometry = 2, + CapabilityTessellation = 3, + CapabilityAddresses = 4, + CapabilityLinkage = 5, + CapabilityKernel = 6, + CapabilityVector16 = 7, + CapabilityFloat16Buffer = 8, + CapabilityFloat16 = 9, + CapabilityFloat64 = 10, + CapabilityInt64 = 11, + CapabilityInt64Atomics = 12, + CapabilityImageBasic = 13, + CapabilityImageReadWrite = 14, + CapabilityImageMipmap = 15, + CapabilityPipes = 17, + CapabilityGroups = 18, + CapabilityDeviceEnqueue = 19, + CapabilityLiteralSampler = 20, + CapabilityAtomicStorage = 21, + CapabilityInt16 = 22, + CapabilityTessellationPointSize = 23, + CapabilityGeometryPointSize = 24, + CapabilityImageGatherExtended = 25, + CapabilityStorageImageMultisample = 27, + CapabilityUniformBufferArrayDynamicIndexing = 28, + CapabilitySampledImageArrayDynamicIndexing = 29, + CapabilityStorageBufferArrayDynamicIndexing = 30, + CapabilityStorageImageArrayDynamicIndexing = 31, + CapabilityClipDistance = 32, + CapabilityCullDistance = 33, + CapabilityImageCubeArray = 34, + CapabilitySampleRateShading = 35, + CapabilityImageRect = 36, + CapabilitySampledRect = 37, + CapabilityGenericPointer = 38, + CapabilityInt8 = 39, + CapabilityInputAttachment = 40, + CapabilitySparseResidency = 41, + CapabilityMinLod = 42, + CapabilitySampled1D = 43, + CapabilityImage1D = 44, + CapabilitySampledCubeArray = 45, + CapabilitySampledBuffer = 46, + CapabilityImageBuffer = 47, + CapabilityImageMSArray = 48, + CapabilityStorageImageExtendedFormats = 49, + CapabilityImageQuery = 50, + CapabilityDerivativeControl = 51, + CapabilityInterpolationFunction = 52, + CapabilityTransformFeedback = 53, + CapabilityGeometryStreams = 54, + CapabilityStorageImageReadWithoutFormat = 55, + CapabilityStorageImageWriteWithoutFormat = 56, + CapabilityMultiViewport = 57, + CapabilitySubgroupDispatch = 58, + CapabilityNamedBarrier = 59, + CapabilityPipeStorage = 60, + CapabilityGroupNonUniform = 61, + CapabilityGroupNonUniformVote = 62, + CapabilityGroupNonUniformArithmetic = 63, + CapabilityGroupNonUniformBallot = 64, + CapabilityGroupNonUniformShuffle = 65, + CapabilityGroupNonUniformShuffleRelative = 66, + CapabilityGroupNonUniformClustered = 67, + CapabilityGroupNonUniformQuad = 68, + CapabilityShaderLayer = 69, + CapabilityShaderViewportIndex = 70, + CapabilitySubgroupBallotKHR = 4423, + CapabilityDrawParameters = 4427, + CapabilitySubgroupVoteKHR = 4431, + CapabilityStorageBuffer16BitAccess = 4433, + CapabilityStorageUniformBufferBlock16 = 4433, + CapabilityStorageUniform16 = 4434, + CapabilityUniformAndStorageBuffer16BitAccess = 4434, + CapabilityStoragePushConstant16 = 4435, + CapabilityStorageInputOutput16 = 4436, + CapabilityDeviceGroup = 4437, + CapabilityMultiView = 4439, + CapabilityVariablePointersStorageBuffer = 4441, + CapabilityVariablePointers = 4442, + CapabilityAtomicStorageOps = 4445, + CapabilitySampleMaskPostDepthCoverage = 4447, + CapabilityStorageBuffer8BitAccess = 4448, + CapabilityUniformAndStorageBuffer8BitAccess = 4449, + CapabilityStoragePushConstant8 = 4450, + CapabilityDenormPreserve = 4464, + CapabilityDenormFlushToZero = 4465, + CapabilitySignedZeroInfNanPreserve = 4466, + CapabilityRoundingModeRTE = 4467, + CapabilityRoundingModeRTZ = 4468, + CapabilityRayQueryProvisionalKHR = 4471, + CapabilityRayTraversalPrimitiveCullingProvisionalKHR = 4478, + CapabilityFloat16ImageAMD = 5008, + CapabilityImageGatherBiasLodAMD = 5009, + CapabilityFragmentMaskAMD = 5010, + CapabilityStencilExportEXT = 5013, + CapabilityImageReadWriteLodAMD = 5015, + CapabilityShaderClockKHR = 5055, + CapabilitySampleMaskOverrideCoverageNV = 5249, + CapabilityGeometryShaderPassthroughNV = 5251, + CapabilityShaderViewportIndexLayerEXT = 5254, + CapabilityShaderViewportIndexLayerNV = 5254, + CapabilityShaderViewportMaskNV = 5255, + CapabilityShaderStereoViewNV = 5259, + CapabilityPerViewAttributesNV = 5260, + CapabilityFragmentFullyCoveredEXT = 5265, + CapabilityMeshShadingNV = 5266, + CapabilityImageFootprintNV = 5282, + CapabilityFragmentBarycentricNV = 5284, + CapabilityComputeDerivativeGroupQuadsNV = 5288, + CapabilityFragmentDensityEXT = 5291, + CapabilityShadingRateNV = 5291, + CapabilityGroupNonUniformPartitionedNV = 5297, + CapabilityShaderNonUniform = 5301, + CapabilityShaderNonUniformEXT = 5301, + CapabilityRuntimeDescriptorArray = 5302, + CapabilityRuntimeDescriptorArrayEXT = 5302, + CapabilityInputAttachmentArrayDynamicIndexing = 5303, + CapabilityInputAttachmentArrayDynamicIndexingEXT = 5303, + CapabilityUniformTexelBufferArrayDynamicIndexing = 5304, + CapabilityUniformTexelBufferArrayDynamicIndexingEXT = 5304, + CapabilityStorageTexelBufferArrayDynamicIndexing = 5305, + CapabilityStorageTexelBufferArrayDynamicIndexingEXT = 5305, + CapabilityUniformBufferArrayNonUniformIndexing = 5306, + CapabilityUniformBufferArrayNonUniformIndexingEXT = 5306, + CapabilitySampledImageArrayNonUniformIndexing = 5307, + CapabilitySampledImageArrayNonUniformIndexingEXT = 5307, + CapabilityStorageBufferArrayNonUniformIndexing = 5308, + CapabilityStorageBufferArrayNonUniformIndexingEXT = 5308, + CapabilityStorageImageArrayNonUniformIndexing = 5309, + CapabilityStorageImageArrayNonUniformIndexingEXT = 5309, + CapabilityInputAttachmentArrayNonUniformIndexing = 5310, + CapabilityInputAttachmentArrayNonUniformIndexingEXT = 5310, + CapabilityUniformTexelBufferArrayNonUniformIndexing = 5311, + CapabilityUniformTexelBufferArrayNonUniformIndexingEXT = 5311, + CapabilityStorageTexelBufferArrayNonUniformIndexing = 5312, + CapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312, + CapabilityRayTracingNV = 5340, + CapabilityVulkanMemoryModel = 5345, + CapabilityVulkanMemoryModelKHR = 5345, + CapabilityVulkanMemoryModelDeviceScope = 5346, + CapabilityVulkanMemoryModelDeviceScopeKHR = 5346, + CapabilityPhysicalStorageBufferAddresses = 5347, + CapabilityPhysicalStorageBufferAddressesEXT = 5347, + CapabilityComputeDerivativeGroupLinearNV = 5350, + CapabilityRayTracingProvisionalKHR = 5353, + CapabilityCooperativeMatrixNV = 5357, + CapabilityFragmentShaderSampleInterlockEXT = 5363, + CapabilityFragmentShaderShadingRateInterlockEXT = 5372, + CapabilityShaderSMBuiltinsNV = 5373, + CapabilityFragmentShaderPixelInterlockEXT = 5378, + CapabilityDemoteToHelperInvocationEXT = 5379, + CapabilitySubgroupShuffleINTEL = 5568, + CapabilitySubgroupBufferBlockIOINTEL = 5569, + CapabilitySubgroupImageBlockIOINTEL = 5570, + CapabilitySubgroupImageMediaBlockIOINTEL = 5579, + CapabilityIntegerFunctions2INTEL = 5584, + CapabilitySubgroupAvcMotionEstimationINTEL = 5696, + CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697, + CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698, + CapabilityMax = 0x7fffffff, +}; + +enum RayFlagsShift { + RayFlagsOpaqueKHRShift = 0, + RayFlagsNoOpaqueKHRShift = 1, + RayFlagsTerminateOnFirstHitKHRShift = 2, + RayFlagsSkipClosestHitShaderKHRShift = 3, + RayFlagsCullBackFacingTrianglesKHRShift = 4, + RayFlagsCullFrontFacingTrianglesKHRShift = 5, + RayFlagsCullOpaqueKHRShift = 6, + RayFlagsCullNoOpaqueKHRShift = 7, + RayFlagsSkipTrianglesKHRShift = 8, + RayFlagsSkipAABBsKHRShift = 9, + RayFlagsMax = 0x7fffffff, +}; + +enum RayFlagsMask { + RayFlagsMaskNone = 0, + RayFlagsOpaqueKHRMask = 0x00000001, + RayFlagsNoOpaqueKHRMask = 0x00000002, + RayFlagsTerminateOnFirstHitKHRMask = 0x00000004, + RayFlagsSkipClosestHitShaderKHRMask = 0x00000008, + RayFlagsCullBackFacingTrianglesKHRMask = 0x00000010, + RayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020, + RayFlagsCullOpaqueKHRMask = 0x00000040, + RayFlagsCullNoOpaqueKHRMask = 0x00000080, + RayFlagsSkipTrianglesKHRMask = 0x00000100, + RayFlagsSkipAABBsKHRMask = 0x00000200, +}; + +enum RayQueryIntersection { + RayQueryIntersectionRayQueryCandidateIntersectionKHR = 0, + RayQueryIntersectionRayQueryCommittedIntersectionKHR = 1, + RayQueryIntersectionMax = 0x7fffffff, +}; + +enum RayQueryCommittedIntersectionType { + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR = 0, + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR = 1, + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR = 2, + RayQueryCommittedIntersectionTypeMax = 0x7fffffff, +}; + +enum RayQueryCandidateIntersectionType { + RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR = 0, + RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR = 1, + RayQueryCandidateIntersectionTypeMax = 0x7fffffff, +}; + +enum Op { + OpNop = 0, + OpUndef = 1, + OpSourceContinued = 2, + OpSource = 3, + OpSourceExtension = 4, + OpName = 5, + OpMemberName = 6, + OpString = 7, + OpLine = 8, + OpExtension = 10, + OpExtInstImport = 11, + OpExtInst = 12, + OpMemoryModel = 14, + OpEntryPoint = 15, + OpExecutionMode = 16, + OpCapability = 17, + OpTypeVoid = 19, + OpTypeBool = 20, + OpTypeInt = 21, + OpTypeFloat = 22, + OpTypeVector = 23, + OpTypeMatrix = 24, + OpTypeImage = 25, + OpTypeSampler = 26, + OpTypeSampledImage = 27, + OpTypeArray = 28, + OpTypeRuntimeArray = 29, + OpTypeStruct = 30, + OpTypeOpaque = 31, + OpTypePointer = 32, + OpTypeFunction = 33, + OpTypeEvent = 34, + OpTypeDeviceEvent = 35, + OpTypeReserveId = 36, + OpTypeQueue = 37, + OpTypePipe = 38, + OpTypeForwardPointer = 39, + OpConstantTrue = 41, + OpConstantFalse = 42, + OpConstant = 43, + OpConstantComposite = 44, + OpConstantSampler = 45, + OpConstantNull = 46, + OpSpecConstantTrue = 48, + OpSpecConstantFalse = 49, + OpSpecConstant = 50, + OpSpecConstantComposite = 51, + OpSpecConstantOp = 52, + OpFunction = 54, + OpFunctionParameter = 55, + OpFunctionEnd = 56, + OpFunctionCall = 57, + OpVariable = 59, + OpImageTexelPointer = 60, + OpLoad = 61, + OpStore = 62, + OpCopyMemory = 63, + OpCopyMemorySized = 64, + OpAccessChain = 65, + OpInBoundsAccessChain = 66, + OpPtrAccessChain = 67, + OpArrayLength = 68, + OpGenericPtrMemSemantics = 69, + OpInBoundsPtrAccessChain = 70, + OpDecorate = 71, + OpMemberDecorate = 72, + OpDecorationGroup = 73, + OpGroupDecorate = 74, + OpGroupMemberDecorate = 75, + OpVectorExtractDynamic = 77, + OpVectorInsertDynamic = 78, + OpVectorShuffle = 79, + OpCompositeConstruct = 80, + OpCompositeExtract = 81, + OpCompositeInsert = 82, + OpCopyObject = 83, + OpTranspose = 84, + OpSampledImage = 86, + OpImageSampleImplicitLod = 87, + OpImageSampleExplicitLod = 88, + OpImageSampleDrefImplicitLod = 89, + OpImageSampleDrefExplicitLod = 90, + OpImageSampleProjImplicitLod = 91, + OpImageSampleProjExplicitLod = 92, + OpImageSampleProjDrefImplicitLod = 93, + OpImageSampleProjDrefExplicitLod = 94, + OpImageFetch = 95, + OpImageGather = 96, + OpImageDrefGather = 97, + OpImageRead = 98, + OpImageWrite = 99, + OpImage = 100, + OpImageQueryFormat = 101, + OpImageQueryOrder = 102, + OpImageQuerySizeLod = 103, + OpImageQuerySize = 104, + OpImageQueryLod = 105, + OpImageQueryLevels = 106, + OpImageQuerySamples = 107, + OpConvertFToU = 109, + OpConvertFToS = 110, + OpConvertSToF = 111, + OpConvertUToF = 112, + OpUConvert = 113, + OpSConvert = 114, + OpFConvert = 115, + OpQuantizeToF16 = 116, + OpConvertPtrToU = 117, + OpSatConvertSToU = 118, + OpSatConvertUToS = 119, + OpConvertUToPtr = 120, + OpPtrCastToGeneric = 121, + OpGenericCastToPtr = 122, + OpGenericCastToPtrExplicit = 123, + OpBitcast = 124, + OpSNegate = 126, + OpFNegate = 127, + OpIAdd = 128, + OpFAdd = 129, + OpISub = 130, + OpFSub = 131, + OpIMul = 132, + OpFMul = 133, + OpUDiv = 134, + OpSDiv = 135, + OpFDiv = 136, + OpUMod = 137, + OpSRem = 138, + OpSMod = 139, + OpFRem = 140, + OpFMod = 141, + OpVectorTimesScalar = 142, + OpMatrixTimesScalar = 143, + OpVectorTimesMatrix = 144, + OpMatrixTimesVector = 145, + OpMatrixTimesMatrix = 146, + OpOuterProduct = 147, + OpDot = 148, + OpIAddCarry = 149, + OpISubBorrow = 150, + OpUMulExtended = 151, + OpSMulExtended = 152, + OpAny = 154, + OpAll = 155, + OpIsNan = 156, + OpIsInf = 157, + OpIsFinite = 158, + OpIsNormal = 159, + OpSignBitSet = 160, + OpLessOrGreater = 161, + OpOrdered = 162, + OpUnordered = 163, + OpLogicalEqual = 164, + OpLogicalNotEqual = 165, + OpLogicalOr = 166, + OpLogicalAnd = 167, + OpLogicalNot = 168, + OpSelect = 169, + OpIEqual = 170, + OpINotEqual = 171, + OpUGreaterThan = 172, + OpSGreaterThan = 173, + OpUGreaterThanEqual = 174, + OpSGreaterThanEqual = 175, + OpULessThan = 176, + OpSLessThan = 177, + OpULessThanEqual = 178, + OpSLessThanEqual = 179, + OpFOrdEqual = 180, + OpFUnordEqual = 181, + OpFOrdNotEqual = 182, + OpFUnordNotEqual = 183, + OpFOrdLessThan = 184, + OpFUnordLessThan = 185, + OpFOrdGreaterThan = 186, + OpFUnordGreaterThan = 187, + OpFOrdLessThanEqual = 188, + OpFUnordLessThanEqual = 189, + OpFOrdGreaterThanEqual = 190, + OpFUnordGreaterThanEqual = 191, + OpShiftRightLogical = 194, + OpShiftRightArithmetic = 195, + OpShiftLeftLogical = 196, + OpBitwiseOr = 197, + OpBitwiseXor = 198, + OpBitwiseAnd = 199, + OpNot = 200, + OpBitFieldInsert = 201, + OpBitFieldSExtract = 202, + OpBitFieldUExtract = 203, + OpBitReverse = 204, + OpBitCount = 205, + OpDPdx = 207, + OpDPdy = 208, + OpFwidth = 209, + OpDPdxFine = 210, + OpDPdyFine = 211, + OpFwidthFine = 212, + OpDPdxCoarse = 213, + OpDPdyCoarse = 214, + OpFwidthCoarse = 215, + OpEmitVertex = 218, + OpEndPrimitive = 219, + OpEmitStreamVertex = 220, + OpEndStreamPrimitive = 221, + OpControlBarrier = 224, + OpMemoryBarrier = 225, + OpAtomicLoad = 227, + OpAtomicStore = 228, + OpAtomicExchange = 229, + OpAtomicCompareExchange = 230, + OpAtomicCompareExchangeWeak = 231, + OpAtomicIIncrement = 232, + OpAtomicIDecrement = 233, + OpAtomicIAdd = 234, + OpAtomicISub = 235, + OpAtomicSMin = 236, + OpAtomicUMin = 237, + OpAtomicSMax = 238, + OpAtomicUMax = 239, + OpAtomicAnd = 240, + OpAtomicOr = 241, + OpAtomicXor = 242, + OpPhi = 245, + OpLoopMerge = 246, + OpSelectionMerge = 247, + OpLabel = 248, + OpBranch = 249, + OpBranchConditional = 250, + OpSwitch = 251, + OpKill = 252, + OpReturn = 253, + OpReturnValue = 254, + OpUnreachable = 255, + OpLifetimeStart = 256, + OpLifetimeStop = 257, + OpGroupAsyncCopy = 259, + OpGroupWaitEvents = 260, + OpGroupAll = 261, + OpGroupAny = 262, + OpGroupBroadcast = 263, + OpGroupIAdd = 264, + OpGroupFAdd = 265, + OpGroupFMin = 266, + OpGroupUMin = 267, + OpGroupSMin = 268, + OpGroupFMax = 269, + OpGroupUMax = 270, + OpGroupSMax = 271, + OpReadPipe = 274, + OpWritePipe = 275, + OpReservedReadPipe = 276, + OpReservedWritePipe = 277, + OpReserveReadPipePackets = 278, + OpReserveWritePipePackets = 279, + OpCommitReadPipe = 280, + OpCommitWritePipe = 281, + OpIsValidReserveId = 282, + OpGetNumPipePackets = 283, + OpGetMaxPipePackets = 284, + OpGroupReserveReadPipePackets = 285, + OpGroupReserveWritePipePackets = 286, + OpGroupCommitReadPipe = 287, + OpGroupCommitWritePipe = 288, + OpEnqueueMarker = 291, + OpEnqueueKernel = 292, + OpGetKernelNDrangeSubGroupCount = 293, + OpGetKernelNDrangeMaxSubGroupSize = 294, + OpGetKernelWorkGroupSize = 295, + OpGetKernelPreferredWorkGroupSizeMultiple = 296, + OpRetainEvent = 297, + OpReleaseEvent = 298, + OpCreateUserEvent = 299, + OpIsValidEvent = 300, + OpSetUserEventStatus = 301, + OpCaptureEventProfilingInfo = 302, + OpGetDefaultQueue = 303, + OpBuildNDRange = 304, + OpImageSparseSampleImplicitLod = 305, + OpImageSparseSampleExplicitLod = 306, + OpImageSparseSampleDrefImplicitLod = 307, + OpImageSparseSampleDrefExplicitLod = 308, + OpImageSparseSampleProjImplicitLod = 309, + OpImageSparseSampleProjExplicitLod = 310, + OpImageSparseSampleProjDrefImplicitLod = 311, + OpImageSparseSampleProjDrefExplicitLod = 312, + OpImageSparseFetch = 313, + OpImageSparseGather = 314, + OpImageSparseDrefGather = 315, + OpImageSparseTexelsResident = 316, + OpNoLine = 317, + OpAtomicFlagTestAndSet = 318, + OpAtomicFlagClear = 319, + OpImageSparseRead = 320, + OpSizeOf = 321, + OpTypePipeStorage = 322, + OpConstantPipeStorage = 323, + OpCreatePipeFromPipeStorage = 324, + OpGetKernelLocalSizeForSubgroupCount = 325, + OpGetKernelMaxNumSubgroups = 326, + OpTypeNamedBarrier = 327, + OpNamedBarrierInitialize = 328, + OpMemoryNamedBarrier = 329, + OpModuleProcessed = 330, + OpExecutionModeId = 331, + OpDecorateId = 332, + OpGroupNonUniformElect = 333, + OpGroupNonUniformAll = 334, + OpGroupNonUniformAny = 335, + OpGroupNonUniformAllEqual = 336, + OpGroupNonUniformBroadcast = 337, + OpGroupNonUniformBroadcastFirst = 338, + OpGroupNonUniformBallot = 339, + OpGroupNonUniformInverseBallot = 340, + OpGroupNonUniformBallotBitExtract = 341, + OpGroupNonUniformBallotBitCount = 342, + OpGroupNonUniformBallotFindLSB = 343, + OpGroupNonUniformBallotFindMSB = 344, + OpGroupNonUniformShuffle = 345, + OpGroupNonUniformShuffleXor = 346, + OpGroupNonUniformShuffleUp = 347, + OpGroupNonUniformShuffleDown = 348, + OpGroupNonUniformIAdd = 349, + OpGroupNonUniformFAdd = 350, + OpGroupNonUniformIMul = 351, + OpGroupNonUniformFMul = 352, + OpGroupNonUniformSMin = 353, + OpGroupNonUniformUMin = 354, + OpGroupNonUniformFMin = 355, + OpGroupNonUniformSMax = 356, + OpGroupNonUniformUMax = 357, + OpGroupNonUniformFMax = 358, + OpGroupNonUniformBitwiseAnd = 359, + OpGroupNonUniformBitwiseOr = 360, + OpGroupNonUniformBitwiseXor = 361, + OpGroupNonUniformLogicalAnd = 362, + OpGroupNonUniformLogicalOr = 363, + OpGroupNonUniformLogicalXor = 364, + OpGroupNonUniformQuadBroadcast = 365, + OpGroupNonUniformQuadSwap = 366, + OpCopyLogical = 400, + OpPtrEqual = 401, + OpPtrNotEqual = 402, + OpPtrDiff = 403, + OpSubgroupBallotKHR = 4421, + OpSubgroupFirstInvocationKHR = 4422, + OpSubgroupAllKHR = 4428, + OpSubgroupAnyKHR = 4429, + OpSubgroupAllEqualKHR = 4430, + OpSubgroupReadInvocationKHR = 4432, + OpTypeRayQueryProvisionalKHR = 4472, + OpRayQueryInitializeKHR = 4473, + OpRayQueryTerminateKHR = 4474, + OpRayQueryGenerateIntersectionKHR = 4475, + OpRayQueryConfirmIntersectionKHR = 4476, + OpRayQueryProceedKHR = 4477, + OpRayQueryGetIntersectionTypeKHR = 4479, + OpGroupIAddNonUniformAMD = 5000, + OpGroupFAddNonUniformAMD = 5001, + OpGroupFMinNonUniformAMD = 5002, + OpGroupUMinNonUniformAMD = 5003, + OpGroupSMinNonUniformAMD = 5004, + OpGroupFMaxNonUniformAMD = 5005, + OpGroupUMaxNonUniformAMD = 5006, + OpGroupSMaxNonUniformAMD = 5007, + OpFragmentMaskFetchAMD = 5011, + OpFragmentFetchAMD = 5012, + OpReadClockKHR = 5056, + OpImageSampleFootprintNV = 5283, + OpGroupNonUniformPartitionNV = 5296, + OpWritePackedPrimitiveIndices4x8NV = 5299, + OpReportIntersectionKHR = 5334, + OpReportIntersectionNV = 5334, + OpIgnoreIntersectionKHR = 5335, + OpIgnoreIntersectionNV = 5335, + OpTerminateRayKHR = 5336, + OpTerminateRayNV = 5336, + OpTraceNV = 5337, + OpTraceRayKHR = 5337, + OpTypeAccelerationStructureKHR = 5341, + OpTypeAccelerationStructureNV = 5341, + OpExecuteCallableKHR = 5344, + OpExecuteCallableNV = 5344, + OpTypeCooperativeMatrixNV = 5358, + OpCooperativeMatrixLoadNV = 5359, + OpCooperativeMatrixStoreNV = 5360, + OpCooperativeMatrixMulAddNV = 5361, + OpCooperativeMatrixLengthNV = 5362, + OpBeginInvocationInterlockEXT = 5364, + OpEndInvocationInterlockEXT = 5365, + OpDemoteToHelperInvocationEXT = 5380, + OpIsHelperInvocationEXT = 5381, + OpSubgroupShuffleINTEL = 5571, + OpSubgroupShuffleDownINTEL = 5572, + OpSubgroupShuffleUpINTEL = 5573, + OpSubgroupShuffleXorINTEL = 5574, + OpSubgroupBlockReadINTEL = 5575, + OpSubgroupBlockWriteINTEL = 5576, + OpSubgroupImageBlockReadINTEL = 5577, + OpSubgroupImageBlockWriteINTEL = 5578, + OpSubgroupImageMediaBlockReadINTEL = 5580, + OpSubgroupImageMediaBlockWriteINTEL = 5581, + OpUCountLeadingZerosINTEL = 5585, + OpUCountTrailingZerosINTEL = 5586, + OpAbsISubINTEL = 5587, + OpAbsUSubINTEL = 5588, + OpIAddSatINTEL = 5589, + OpUAddSatINTEL = 5590, + OpIAverageINTEL = 5591, + OpUAverageINTEL = 5592, + OpIAverageRoundedINTEL = 5593, + OpUAverageRoundedINTEL = 5594, + OpISubSatINTEL = 5595, + OpUSubSatINTEL = 5596, + OpIMul32x16INTEL = 5597, + OpUMul32x16INTEL = 5598, + OpDecorateString = 5632, + OpDecorateStringGOOGLE = 5632, + OpMemberDecorateString = 5633, + OpMemberDecorateStringGOOGLE = 5633, + OpVmeImageINTEL = 5699, + OpTypeVmeImageINTEL = 5700, + OpTypeAvcImePayloadINTEL = 5701, + OpTypeAvcRefPayloadINTEL = 5702, + OpTypeAvcSicPayloadINTEL = 5703, + OpTypeAvcMcePayloadINTEL = 5704, + OpTypeAvcMceResultINTEL = 5705, + OpTypeAvcImeResultINTEL = 5706, + OpTypeAvcImeResultSingleReferenceStreamoutINTEL = 5707, + OpTypeAvcImeResultDualReferenceStreamoutINTEL = 5708, + OpTypeAvcImeSingleReferenceStreaminINTEL = 5709, + OpTypeAvcImeDualReferenceStreaminINTEL = 5710, + OpTypeAvcRefResultINTEL = 5711, + OpTypeAvcSicResultINTEL = 5712, + OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL = 5713, + OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL = 5714, + OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL = 5715, + OpSubgroupAvcMceSetInterShapePenaltyINTEL = 5716, + OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL = 5717, + OpSubgroupAvcMceSetInterDirectionPenaltyINTEL = 5718, + OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL = 5719, + OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL = 5720, + OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL = 5721, + OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL = 5722, + OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL = 5723, + OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL = 5724, + OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL = 5725, + OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL = 5726, + OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL = 5727, + OpSubgroupAvcMceSetAcOnlyHaarINTEL = 5728, + OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL = 5729, + OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL = 5730, + OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL = 5731, + OpSubgroupAvcMceConvertToImePayloadINTEL = 5732, + OpSubgroupAvcMceConvertToImeResultINTEL = 5733, + OpSubgroupAvcMceConvertToRefPayloadINTEL = 5734, + OpSubgroupAvcMceConvertToRefResultINTEL = 5735, + OpSubgroupAvcMceConvertToSicPayloadINTEL = 5736, + OpSubgroupAvcMceConvertToSicResultINTEL = 5737, + OpSubgroupAvcMceGetMotionVectorsINTEL = 5738, + OpSubgroupAvcMceGetInterDistortionsINTEL = 5739, + OpSubgroupAvcMceGetBestInterDistortionsINTEL = 5740, + OpSubgroupAvcMceGetInterMajorShapeINTEL = 5741, + OpSubgroupAvcMceGetInterMinorShapeINTEL = 5742, + OpSubgroupAvcMceGetInterDirectionsINTEL = 5743, + OpSubgroupAvcMceGetInterMotionVectorCountINTEL = 5744, + OpSubgroupAvcMceGetInterReferenceIdsINTEL = 5745, + OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL = 5746, + OpSubgroupAvcImeInitializeINTEL = 5747, + OpSubgroupAvcImeSetSingleReferenceINTEL = 5748, + OpSubgroupAvcImeSetDualReferenceINTEL = 5749, + OpSubgroupAvcImeRefWindowSizeINTEL = 5750, + OpSubgroupAvcImeAdjustRefOffsetINTEL = 5751, + OpSubgroupAvcImeConvertToMcePayloadINTEL = 5752, + OpSubgroupAvcImeSetMaxMotionVectorCountINTEL = 5753, + OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL = 5754, + OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL = 5755, + OpSubgroupAvcImeSetWeightedSadINTEL = 5756, + OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL = 5757, + OpSubgroupAvcImeEvaluateWithDualReferenceINTEL = 5758, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL = 5759, + OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL = 5760, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL = 5761, + OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL = 5762, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL = 5763, + OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL = 5764, + OpSubgroupAvcImeConvertToMceResultINTEL = 5765, + OpSubgroupAvcImeGetSingleReferenceStreaminINTEL = 5766, + OpSubgroupAvcImeGetDualReferenceStreaminINTEL = 5767, + OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL = 5768, + OpSubgroupAvcImeStripDualReferenceStreamoutINTEL = 5769, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL = 5770, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL = 5771, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL = 5772, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL = 5773, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL = 5774, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL = 5775, + OpSubgroupAvcImeGetBorderReachedINTEL = 5776, + OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL = 5777, + OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL = 5778, + OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL = 5779, + OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL = 5780, + OpSubgroupAvcFmeInitializeINTEL = 5781, + OpSubgroupAvcBmeInitializeINTEL = 5782, + OpSubgroupAvcRefConvertToMcePayloadINTEL = 5783, + OpSubgroupAvcRefSetBidirectionalMixDisableINTEL = 5784, + OpSubgroupAvcRefSetBilinearFilterEnableINTEL = 5785, + OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL = 5786, + OpSubgroupAvcRefEvaluateWithDualReferenceINTEL = 5787, + OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL = 5788, + OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL = 5789, + OpSubgroupAvcRefConvertToMceResultINTEL = 5790, + OpSubgroupAvcSicInitializeINTEL = 5791, + OpSubgroupAvcSicConfigureSkcINTEL = 5792, + OpSubgroupAvcSicConfigureIpeLumaINTEL = 5793, + OpSubgroupAvcSicConfigureIpeLumaChromaINTEL = 5794, + OpSubgroupAvcSicGetMotionVectorMaskINTEL = 5795, + OpSubgroupAvcSicConvertToMcePayloadINTEL = 5796, + OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL = 5797, + OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL = 5798, + OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL = 5799, + OpSubgroupAvcSicSetBilinearFilterEnableINTEL = 5800, + OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL = 5801, + OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL = 5802, + OpSubgroupAvcSicEvaluateIpeINTEL = 5803, + OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL = 5804, + OpSubgroupAvcSicEvaluateWithDualReferenceINTEL = 5805, + OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL = 5806, + OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL = 5807, + OpSubgroupAvcSicConvertToMceResultINTEL = 5808, + OpSubgroupAvcSicGetIpeLumaShapeINTEL = 5809, + OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL = 5810, + OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL = 5811, + OpSubgroupAvcSicGetPackedIpeLumaModesINTEL = 5812, + OpSubgroupAvcSicGetIpeChromaModeINTEL = 5813, + OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, + OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, + OpSubgroupAvcSicGetInterRawSadsINTEL = 5816, + OpRayQueryGetRayTMinKHR = 6016, + OpRayQueryGetRayFlagsKHR = 6017, + OpRayQueryGetIntersectionTKHR = 6018, + OpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019, + OpRayQueryGetIntersectionInstanceIdKHR = 6020, + OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021, + OpRayQueryGetIntersectionGeometryIndexKHR = 6022, + OpRayQueryGetIntersectionPrimitiveIndexKHR = 6023, + OpRayQueryGetIntersectionBarycentricsKHR = 6024, + OpRayQueryGetIntersectionFrontFaceKHR = 6025, + OpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026, + OpRayQueryGetIntersectionObjectRayDirectionKHR = 6027, + OpRayQueryGetIntersectionObjectRayOriginKHR = 6028, + OpRayQueryGetWorldRayDirectionKHR = 6029, + OpRayQueryGetWorldRayOriginKHR = 6030, + OpRayQueryGetIntersectionObjectToWorldKHR = 6031, + OpRayQueryGetIntersectionWorldToObjectKHR = 6032, + OpMax = 0x7fffffff, +}; + +#ifdef SPV_ENABLE_UTILITY_CODE +inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) { + *hasResult = *hasResultType = false; + switch (opcode) { + default: /* unknown opcode */ break; + case OpNop: *hasResult = false; *hasResultType = false; break; + case OpUndef: *hasResult = true; *hasResultType = true; break; + case OpSourceContinued: *hasResult = false; *hasResultType = false; break; + case OpSource: *hasResult = false; *hasResultType = false; break; + case OpSourceExtension: *hasResult = false; *hasResultType = false; break; + case OpName: *hasResult = false; *hasResultType = false; break; + case OpMemberName: *hasResult = false; *hasResultType = false; break; + case OpString: *hasResult = true; *hasResultType = false; break; + case OpLine: *hasResult = false; *hasResultType = false; break; + case OpExtension: *hasResult = false; *hasResultType = false; break; + case OpExtInstImport: *hasResult = true; *hasResultType = false; break; + case OpExtInst: *hasResult = true; *hasResultType = true; break; + case OpMemoryModel: *hasResult = false; *hasResultType = false; break; + case OpEntryPoint: *hasResult = false; *hasResultType = false; break; + case OpExecutionMode: *hasResult = false; *hasResultType = false; break; + case OpCapability: *hasResult = false; *hasResultType = false; break; + case OpTypeVoid: *hasResult = true; *hasResultType = false; break; + case OpTypeBool: *hasResult = true; *hasResultType = false; break; + case OpTypeInt: *hasResult = true; *hasResultType = false; break; + case OpTypeFloat: *hasResult = true; *hasResultType = false; break; + case OpTypeVector: *hasResult = true; *hasResultType = false; break; + case OpTypeMatrix: *hasResult = true; *hasResultType = false; break; + case OpTypeImage: *hasResult = true; *hasResultType = false; break; + case OpTypeSampler: *hasResult = true; *hasResultType = false; break; + case OpTypeSampledImage: *hasResult = true; *hasResultType = false; break; + case OpTypeArray: *hasResult = true; *hasResultType = false; break; + case OpTypeRuntimeArray: *hasResult = true; *hasResultType = false; break; + case OpTypeStruct: *hasResult = true; *hasResultType = false; break; + case OpTypeOpaque: *hasResult = true; *hasResultType = false; break; + case OpTypePointer: *hasResult = true; *hasResultType = false; break; + case OpTypeFunction: *hasResult = true; *hasResultType = false; break; + case OpTypeEvent: *hasResult = true; *hasResultType = false; break; + case OpTypeDeviceEvent: *hasResult = true; *hasResultType = false; break; + case OpTypeReserveId: *hasResult = true; *hasResultType = false; break; + case OpTypeQueue: *hasResult = true; *hasResultType = false; break; + case OpTypePipe: *hasResult = true; *hasResultType = false; break; + case OpTypeForwardPointer: *hasResult = false; *hasResultType = false; break; + case OpConstantTrue: *hasResult = true; *hasResultType = true; break; + case OpConstantFalse: *hasResult = true; *hasResultType = true; break; + case OpConstant: *hasResult = true; *hasResultType = true; break; + case OpConstantComposite: *hasResult = true; *hasResultType = true; break; + case OpConstantSampler: *hasResult = true; *hasResultType = true; break; + case OpConstantNull: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantTrue: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantFalse: *hasResult = true; *hasResultType = true; break; + case OpSpecConstant: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantComposite: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantOp: *hasResult = true; *hasResultType = true; break; + case OpFunction: *hasResult = true; *hasResultType = true; break; + case OpFunctionParameter: *hasResult = true; *hasResultType = true; break; + case OpFunctionEnd: *hasResult = false; *hasResultType = false; break; + case OpFunctionCall: *hasResult = true; *hasResultType = true; break; + case OpVariable: *hasResult = true; *hasResultType = true; break; + case OpImageTexelPointer: *hasResult = true; *hasResultType = true; break; + case OpLoad: *hasResult = true; *hasResultType = true; break; + case OpStore: *hasResult = false; *hasResultType = false; break; + case OpCopyMemory: *hasResult = false; *hasResultType = false; break; + case OpCopyMemorySized: *hasResult = false; *hasResultType = false; break; + case OpAccessChain: *hasResult = true; *hasResultType = true; break; + case OpInBoundsAccessChain: *hasResult = true; *hasResultType = true; break; + case OpPtrAccessChain: *hasResult = true; *hasResultType = true; break; + case OpArrayLength: *hasResult = true; *hasResultType = true; break; + case OpGenericPtrMemSemantics: *hasResult = true; *hasResultType = true; break; + case OpInBoundsPtrAccessChain: *hasResult = true; *hasResultType = true; break; + case OpDecorate: *hasResult = false; *hasResultType = false; break; + case OpMemberDecorate: *hasResult = false; *hasResultType = false; break; + case OpDecorationGroup: *hasResult = true; *hasResultType = false; break; + case OpGroupDecorate: *hasResult = false; *hasResultType = false; break; + case OpGroupMemberDecorate: *hasResult = false; *hasResultType = false; break; + case OpVectorExtractDynamic: *hasResult = true; *hasResultType = true; break; + case OpVectorInsertDynamic: *hasResult = true; *hasResultType = true; break; + case OpVectorShuffle: *hasResult = true; *hasResultType = true; break; + case OpCompositeConstruct: *hasResult = true; *hasResultType = true; break; + case OpCompositeExtract: *hasResult = true; *hasResultType = true; break; + case OpCompositeInsert: *hasResult = true; *hasResultType = true; break; + case OpCopyObject: *hasResult = true; *hasResultType = true; break; + case OpTranspose: *hasResult = true; *hasResultType = true; break; + case OpSampledImage: *hasResult = true; *hasResultType = true; break; + case OpImageSampleImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageFetch: *hasResult = true; *hasResultType = true; break; + case OpImageGather: *hasResult = true; *hasResultType = true; break; + case OpImageDrefGather: *hasResult = true; *hasResultType = true; break; + case OpImageRead: *hasResult = true; *hasResultType = true; break; + case OpImageWrite: *hasResult = false; *hasResultType = false; break; + case OpImage: *hasResult = true; *hasResultType = true; break; + case OpImageQueryFormat: *hasResult = true; *hasResultType = true; break; + case OpImageQueryOrder: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySizeLod: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySize: *hasResult = true; *hasResultType = true; break; + case OpImageQueryLod: *hasResult = true; *hasResultType = true; break; + case OpImageQueryLevels: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySamples: *hasResult = true; *hasResultType = true; break; + case OpConvertFToU: *hasResult = true; *hasResultType = true; break; + case OpConvertFToS: *hasResult = true; *hasResultType = true; break; + case OpConvertSToF: *hasResult = true; *hasResultType = true; break; + case OpConvertUToF: *hasResult = true; *hasResultType = true; break; + case OpUConvert: *hasResult = true; *hasResultType = true; break; + case OpSConvert: *hasResult = true; *hasResultType = true; break; + case OpFConvert: *hasResult = true; *hasResultType = true; break; + case OpQuantizeToF16: *hasResult = true; *hasResultType = true; break; + case OpConvertPtrToU: *hasResult = true; *hasResultType = true; break; + case OpSatConvertSToU: *hasResult = true; *hasResultType = true; break; + case OpSatConvertUToS: *hasResult = true; *hasResultType = true; break; + case OpConvertUToPtr: *hasResult = true; *hasResultType = true; break; + case OpPtrCastToGeneric: *hasResult = true; *hasResultType = true; break; + case OpGenericCastToPtr: *hasResult = true; *hasResultType = true; break; + case OpGenericCastToPtrExplicit: *hasResult = true; *hasResultType = true; break; + case OpBitcast: *hasResult = true; *hasResultType = true; break; + case OpSNegate: *hasResult = true; *hasResultType = true; break; + case OpFNegate: *hasResult = true; *hasResultType = true; break; + case OpIAdd: *hasResult = true; *hasResultType = true; break; + case OpFAdd: *hasResult = true; *hasResultType = true; break; + case OpISub: *hasResult = true; *hasResultType = true; break; + case OpFSub: *hasResult = true; *hasResultType = true; break; + case OpIMul: *hasResult = true; *hasResultType = true; break; + case OpFMul: *hasResult = true; *hasResultType = true; break; + case OpUDiv: *hasResult = true; *hasResultType = true; break; + case OpSDiv: *hasResult = true; *hasResultType = true; break; + case OpFDiv: *hasResult = true; *hasResultType = true; break; + case OpUMod: *hasResult = true; *hasResultType = true; break; + case OpSRem: *hasResult = true; *hasResultType = true; break; + case OpSMod: *hasResult = true; *hasResultType = true; break; + case OpFRem: *hasResult = true; *hasResultType = true; break; + case OpFMod: *hasResult = true; *hasResultType = true; break; + case OpVectorTimesScalar: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesScalar: *hasResult = true; *hasResultType = true; break; + case OpVectorTimesMatrix: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesVector: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesMatrix: *hasResult = true; *hasResultType = true; break; + case OpOuterProduct: *hasResult = true; *hasResultType = true; break; + case OpDot: *hasResult = true; *hasResultType = true; break; + case OpIAddCarry: *hasResult = true; *hasResultType = true; break; + case OpISubBorrow: *hasResult = true; *hasResultType = true; break; + case OpUMulExtended: *hasResult = true; *hasResultType = true; break; + case OpSMulExtended: *hasResult = true; *hasResultType = true; break; + case OpAny: *hasResult = true; *hasResultType = true; break; + case OpAll: *hasResult = true; *hasResultType = true; break; + case OpIsNan: *hasResult = true; *hasResultType = true; break; + case OpIsInf: *hasResult = true; *hasResultType = true; break; + case OpIsFinite: *hasResult = true; *hasResultType = true; break; + case OpIsNormal: *hasResult = true; *hasResultType = true; break; + case OpSignBitSet: *hasResult = true; *hasResultType = true; break; + case OpLessOrGreater: *hasResult = true; *hasResultType = true; break; + case OpOrdered: *hasResult = true; *hasResultType = true; break; + case OpUnordered: *hasResult = true; *hasResultType = true; break; + case OpLogicalEqual: *hasResult = true; *hasResultType = true; break; + case OpLogicalNotEqual: *hasResult = true; *hasResultType = true; break; + case OpLogicalOr: *hasResult = true; *hasResultType = true; break; + case OpLogicalAnd: *hasResult = true; *hasResultType = true; break; + case OpLogicalNot: *hasResult = true; *hasResultType = true; break; + case OpSelect: *hasResult = true; *hasResultType = true; break; + case OpIEqual: *hasResult = true; *hasResultType = true; break; + case OpINotEqual: *hasResult = true; *hasResultType = true; break; + case OpUGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpSGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpUGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpSGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpULessThan: *hasResult = true; *hasResultType = true; break; + case OpSLessThan: *hasResult = true; *hasResultType = true; break; + case OpULessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpSLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdNotEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordNotEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdLessThan: *hasResult = true; *hasResultType = true; break; + case OpFUnordLessThan: *hasResult = true; *hasResultType = true; break; + case OpFOrdGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpFUnordGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpFOrdLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpShiftRightLogical: *hasResult = true; *hasResultType = true; break; + case OpShiftRightArithmetic: *hasResult = true; *hasResultType = true; break; + case OpShiftLeftLogical: *hasResult = true; *hasResultType = true; break; + case OpBitwiseOr: *hasResult = true; *hasResultType = true; break; + case OpBitwiseXor: *hasResult = true; *hasResultType = true; break; + case OpBitwiseAnd: *hasResult = true; *hasResultType = true; break; + case OpNot: *hasResult = true; *hasResultType = true; break; + case OpBitFieldInsert: *hasResult = true; *hasResultType = true; break; + case OpBitFieldSExtract: *hasResult = true; *hasResultType = true; break; + case OpBitFieldUExtract: *hasResult = true; *hasResultType = true; break; + case OpBitReverse: *hasResult = true; *hasResultType = true; break; + case OpBitCount: *hasResult = true; *hasResultType = true; break; + case OpDPdx: *hasResult = true; *hasResultType = true; break; + case OpDPdy: *hasResult = true; *hasResultType = true; break; + case OpFwidth: *hasResult = true; *hasResultType = true; break; + case OpDPdxFine: *hasResult = true; *hasResultType = true; break; + case OpDPdyFine: *hasResult = true; *hasResultType = true; break; + case OpFwidthFine: *hasResult = true; *hasResultType = true; break; + case OpDPdxCoarse: *hasResult = true; *hasResultType = true; break; + case OpDPdyCoarse: *hasResult = true; *hasResultType = true; break; + case OpFwidthCoarse: *hasResult = true; *hasResultType = true; break; + case OpEmitVertex: *hasResult = false; *hasResultType = false; break; + case OpEndPrimitive: *hasResult = false; *hasResultType = false; break; + case OpEmitStreamVertex: *hasResult = false; *hasResultType = false; break; + case OpEndStreamPrimitive: *hasResult = false; *hasResultType = false; break; + case OpControlBarrier: *hasResult = false; *hasResultType = false; break; + case OpMemoryBarrier: *hasResult = false; *hasResultType = false; break; + case OpAtomicLoad: *hasResult = true; *hasResultType = true; break; + case OpAtomicStore: *hasResult = false; *hasResultType = false; break; + case OpAtomicExchange: *hasResult = true; *hasResultType = true; break; + case OpAtomicCompareExchange: *hasResult = true; *hasResultType = true; break; + case OpAtomicCompareExchangeWeak: *hasResult = true; *hasResultType = true; break; + case OpAtomicIIncrement: *hasResult = true; *hasResultType = true; break; + case OpAtomicIDecrement: *hasResult = true; *hasResultType = true; break; + case OpAtomicIAdd: *hasResult = true; *hasResultType = true; break; + case OpAtomicISub: *hasResult = true; *hasResultType = true; break; + case OpAtomicSMin: *hasResult = true; *hasResultType = true; break; + case OpAtomicUMin: *hasResult = true; *hasResultType = true; break; + case OpAtomicSMax: *hasResult = true; *hasResultType = true; break; + case OpAtomicUMax: *hasResult = true; *hasResultType = true; break; + case OpAtomicAnd: *hasResult = true; *hasResultType = true; break; + case OpAtomicOr: *hasResult = true; *hasResultType = true; break; + case OpAtomicXor: *hasResult = true; *hasResultType = true; break; + case OpPhi: *hasResult = true; *hasResultType = true; break; + case OpLoopMerge: *hasResult = false; *hasResultType = false; break; + case OpSelectionMerge: *hasResult = false; *hasResultType = false; break; + case OpLabel: *hasResult = true; *hasResultType = false; break; + case OpBranch: *hasResult = false; *hasResultType = false; break; + case OpBranchConditional: *hasResult = false; *hasResultType = false; break; + case OpSwitch: *hasResult = false; *hasResultType = false; break; + case OpKill: *hasResult = false; *hasResultType = false; break; + case OpReturn: *hasResult = false; *hasResultType = false; break; + case OpReturnValue: *hasResult = false; *hasResultType = false; break; + case OpUnreachable: *hasResult = false; *hasResultType = false; break; + case OpLifetimeStart: *hasResult = false; *hasResultType = false; break; + case OpLifetimeStop: *hasResult = false; *hasResultType = false; break; + case OpGroupAsyncCopy: *hasResult = true; *hasResultType = true; break; + case OpGroupWaitEvents: *hasResult = false; *hasResultType = false; break; + case OpGroupAll: *hasResult = true; *hasResultType = true; break; + case OpGroupAny: *hasResult = true; *hasResultType = true; break; + case OpGroupBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupIAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupFAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupFMin: *hasResult = true; *hasResultType = true; break; + case OpGroupUMin: *hasResult = true; *hasResultType = true; break; + case OpGroupSMin: *hasResult = true; *hasResultType = true; break; + case OpGroupFMax: *hasResult = true; *hasResultType = true; break; + case OpGroupUMax: *hasResult = true; *hasResultType = true; break; + case OpGroupSMax: *hasResult = true; *hasResultType = true; break; + case OpReadPipe: *hasResult = true; *hasResultType = true; break; + case OpWritePipe: *hasResult = true; *hasResultType = true; break; + case OpReservedReadPipe: *hasResult = true; *hasResultType = true; break; + case OpReservedWritePipe: *hasResult = true; *hasResultType = true; break; + case OpReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; + case OpReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; + case OpCommitReadPipe: *hasResult = false; *hasResultType = false; break; + case OpCommitWritePipe: *hasResult = false; *hasResultType = false; break; + case OpIsValidReserveId: *hasResult = true; *hasResultType = true; break; + case OpGetNumPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGetMaxPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupCommitReadPipe: *hasResult = false; *hasResultType = false; break; + case OpGroupCommitWritePipe: *hasResult = false; *hasResultType = false; break; + case OpEnqueueMarker: *hasResult = true; *hasResultType = true; break; + case OpEnqueueKernel: *hasResult = true; *hasResultType = true; break; + case OpGetKernelNDrangeSubGroupCount: *hasResult = true; *hasResultType = true; break; + case OpGetKernelNDrangeMaxSubGroupSize: *hasResult = true; *hasResultType = true; break; + case OpGetKernelWorkGroupSize: *hasResult = true; *hasResultType = true; break; + case OpGetKernelPreferredWorkGroupSizeMultiple: *hasResult = true; *hasResultType = true; break; + case OpRetainEvent: *hasResult = false; *hasResultType = false; break; + case OpReleaseEvent: *hasResult = false; *hasResultType = false; break; + case OpCreateUserEvent: *hasResult = true; *hasResultType = true; break; + case OpIsValidEvent: *hasResult = true; *hasResultType = true; break; + case OpSetUserEventStatus: *hasResult = false; *hasResultType = false; break; + case OpCaptureEventProfilingInfo: *hasResult = false; *hasResultType = false; break; + case OpGetDefaultQueue: *hasResult = true; *hasResultType = true; break; + case OpBuildNDRange: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseFetch: *hasResult = true; *hasResultType = true; break; + case OpImageSparseGather: *hasResult = true; *hasResultType = true; break; + case OpImageSparseDrefGather: *hasResult = true; *hasResultType = true; break; + case OpImageSparseTexelsResident: *hasResult = true; *hasResultType = true; break; + case OpNoLine: *hasResult = false; *hasResultType = false; break; + case OpAtomicFlagTestAndSet: *hasResult = true; *hasResultType = true; break; + case OpAtomicFlagClear: *hasResult = false; *hasResultType = false; break; + case OpImageSparseRead: *hasResult = true; *hasResultType = true; break; + case OpSizeOf: *hasResult = true; *hasResultType = true; break; + case OpTypePipeStorage: *hasResult = true; *hasResultType = false; break; + case OpConstantPipeStorage: *hasResult = true; *hasResultType = true; break; + case OpCreatePipeFromPipeStorage: *hasResult = true; *hasResultType = true; break; + case OpGetKernelLocalSizeForSubgroupCount: *hasResult = true; *hasResultType = true; break; + case OpGetKernelMaxNumSubgroups: *hasResult = true; *hasResultType = true; break; + case OpTypeNamedBarrier: *hasResult = true; *hasResultType = false; break; + case OpNamedBarrierInitialize: *hasResult = true; *hasResultType = true; break; + case OpMemoryNamedBarrier: *hasResult = false; *hasResultType = false; break; + case OpModuleProcessed: *hasResult = false; *hasResultType = false; break; + case OpExecutionModeId: *hasResult = false; *hasResultType = false; break; + case OpDecorateId: *hasResult = false; *hasResultType = false; break; + case OpGroupNonUniformElect: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAll: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAny: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAllEqual: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBroadcastFirst: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallot: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformInverseBallot: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotBitExtract: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotBitCount: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotFindLSB: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotFindMSB: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffle: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleUp: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleDown: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformIAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformIMul: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMul: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformSMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformUMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformSMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformUMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseAnd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseOr: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalAnd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalOr: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformQuadBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformQuadSwap: *hasResult = true; *hasResultType = true; break; + case OpCopyLogical: *hasResult = true; *hasResultType = true; break; + case OpPtrEqual: *hasResult = true; *hasResultType = true; break; + case OpPtrNotEqual: *hasResult = true; *hasResultType = true; break; + case OpPtrDiff: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break; + case OpTypeRayQueryProvisionalKHR: *hasResult = true; *hasResultType = false; break; + case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break; + case OpGroupIAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupUMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupSMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupUMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupSMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpFragmentMaskFetchAMD: *hasResult = true; *hasResultType = true; break; + case OpFragmentFetchAMD: *hasResult = true; *hasResultType = true; break; + case OpReadClockKHR: *hasResult = true; *hasResultType = true; break; + case OpImageSampleFootprintNV: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformPartitionNV: *hasResult = true; *hasResultType = true; break; + case OpWritePackedPrimitiveIndices4x8NV: *hasResult = false; *hasResultType = false; break; + case OpReportIntersectionNV: *hasResult = true; *hasResultType = true; break; + case OpIgnoreIntersectionNV: *hasResult = false; *hasResultType = false; break; + case OpTerminateRayNV: *hasResult = false; *hasResultType = false; break; + case OpTraceNV: *hasResult = false; *hasResultType = false; break; + case OpTypeAccelerationStructureNV: *hasResult = true; *hasResultType = false; break; + case OpExecuteCallableNV: *hasResult = false; *hasResultType = false; break; + case OpTypeCooperativeMatrixNV: *hasResult = true; *hasResultType = false; break; + case OpCooperativeMatrixLoadNV: *hasResult = true; *hasResultType = true; break; + case OpCooperativeMatrixStoreNV: *hasResult = false; *hasResultType = false; break; + case OpCooperativeMatrixMulAddNV: *hasResult = true; *hasResultType = true; break; + case OpCooperativeMatrixLengthNV: *hasResult = true; *hasResultType = true; break; + case OpBeginInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; + case OpEndInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; + case OpDemoteToHelperInvocationEXT: *hasResult = false; *hasResultType = false; break; + case OpIsHelperInvocationEXT: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleDownINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleUpINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleXorINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpSubgroupImageBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupImageBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpSubgroupImageMediaBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupImageMediaBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpUCountLeadingZerosINTEL: *hasResult = true; *hasResultType = true; break; + case OpUCountTrailingZerosINTEL: *hasResult = true; *hasResultType = true; break; + case OpAbsISubINTEL: *hasResult = true; *hasResultType = true; break; + case OpAbsUSubINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAddSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAddSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAverageINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAverageINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; + case OpISubSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break; + case OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break; + case OpDecorateString: *hasResult = false; *hasResultType = false; break; + case OpMemberDecorateString: *hasResult = false; *hasResultType = false; break; + case OpVmeImageINTEL: *hasResult = true; *hasResultType = true; break; + case OpTypeVmeImageINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImePayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcRefPayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcSicPayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcMcePayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcMceResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcRefResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcSicResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetAcOnlyHaarINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToImePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToImeResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToRefPayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToRefResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToSicPayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToSicResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetBestInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMajorShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMinorShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterDirectionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeRefWindowSizeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeAdjustRefOffsetINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetMaxMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetWeightedSadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeStripDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetBorderReachedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcFmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcBmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefSetBidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureSkcINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureIpeLumaINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureIpeLumaChromaINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetMotionVectorMaskINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateIpeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetIpeLumaShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedIpeLumaModesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetIpeChromaModeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetRayTMinKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetRayFlagsKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionTKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceCustomIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceIdKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionGeometryIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionPrimitiveIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionBarycentricsKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionFrontFaceKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetWorldRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetWorldRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break; + } +} +#endif /* SPV_ENABLE_UTILITY_CODE */ + +// Overload operator| for mask bit combining + +inline ImageOperandsMask operator|(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) | unsigned(b)); } +inline FPFastMathModeMask operator|(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) | unsigned(b)); } +inline SelectionControlMask operator|(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) | unsigned(b)); } +inline LoopControlMask operator|(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) | unsigned(b)); } +inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) | unsigned(b)); } +inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); } +inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); } +inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); } +inline RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); } + +} // end namespace spv + +#endif // #ifndef spirv_HPP + diff --git a/mac/include/SPIRV/spvIR.h b/mac/include/SPIRV/spvIR.h new file mode 100644 index 00000000..6523035e --- /dev/null +++ b/mac/include/SPIRV/spvIR.h @@ -0,0 +1,485 @@ +// +// Copyright (C) 2014 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// SPIRV-IR +// +// Simple in-memory representation (IR) of SPIRV. Just for holding +// Each function's CFG of blocks. Has this hierarchy: +// - Module, which is a list of +// - Function, which is a list of +// - Block, which is a list of +// - Instruction +// + +#pragma once +#ifndef spvIR_H +#define spvIR_H + +#include "spirv.hpp" + +#include +#include +#include +#include +#include +#include + +namespace spv { + +class Block; +class Function; +class Module; + +const Id NoResult = 0; +const Id NoType = 0; + +const Decoration NoPrecision = DecorationMax; + +#ifdef __GNUC__ +# define POTENTIALLY_UNUSED __attribute__((unused)) +#else +# define POTENTIALLY_UNUSED +#endif + +POTENTIALLY_UNUSED +const MemorySemanticsMask MemorySemanticsAllMemory = + (MemorySemanticsMask)(MemorySemanticsUniformMemoryMask | + MemorySemanticsWorkgroupMemoryMask | + MemorySemanticsAtomicCounterMemoryMask | + MemorySemanticsImageMemoryMask); + +struct IdImmediate { + bool isId; // true if word is an Id, false if word is an immediate + unsigned word; + IdImmediate(bool i, unsigned w) : isId(i), word(w) {} +}; + +// +// SPIR-V IR instruction. +// + +class Instruction { +public: + Instruction(Id resultId, Id typeId, Op opCode) : resultId(resultId), typeId(typeId), opCode(opCode), block(nullptr) { } + explicit Instruction(Op opCode) : resultId(NoResult), typeId(NoType), opCode(opCode), block(nullptr) { } + virtual ~Instruction() {} + void addIdOperand(Id id) { + operands.push_back(id); + idOperand.push_back(true); + } + void addImmediateOperand(unsigned int immediate) { + operands.push_back(immediate); + idOperand.push_back(false); + } + void setImmediateOperand(unsigned idx, unsigned int immediate) { + assert(!idOperand[idx]); + operands[idx] = immediate; + } + + void addStringOperand(const char* str) + { + unsigned int word; + char* wordString = (char*)&word; + char* wordPtr = wordString; + int charCount = 0; + char c; + do { + c = *(str++); + *(wordPtr++) = c; + ++charCount; + if (charCount == 4) { + addImmediateOperand(word); + wordPtr = wordString; + charCount = 0; + } + } while (c != 0); + + // deal with partial last word + if (charCount > 0) { + // pad with 0s + for (; charCount < 4; ++charCount) + *(wordPtr++) = 0; + addImmediateOperand(word); + } + } + bool isIdOperand(int op) const { return idOperand[op]; } + void setBlock(Block* b) { block = b; } + Block* getBlock() const { return block; } + Op getOpCode() const { return opCode; } + int getNumOperands() const + { + assert(operands.size() == idOperand.size()); + return (int)operands.size(); + } + Id getResultId() const { return resultId; } + Id getTypeId() const { return typeId; } + Id getIdOperand(int op) const { + assert(idOperand[op]); + return operands[op]; + } + unsigned int getImmediateOperand(int op) const { + assert(!idOperand[op]); + return operands[op]; + } + + // Write out the binary form. + void dump(std::vector& out) const + { + // Compute the wordCount + unsigned int wordCount = 1; + if (typeId) + ++wordCount; + if (resultId) + ++wordCount; + wordCount += (unsigned int)operands.size(); + + // Write out the beginning of the instruction + out.push_back(((wordCount) << WordCountShift) | opCode); + if (typeId) + out.push_back(typeId); + if (resultId) + out.push_back(resultId); + + // Write out the operands + for (int op = 0; op < (int)operands.size(); ++op) + out.push_back(operands[op]); + } + +protected: + Instruction(const Instruction&); + Id resultId; + Id typeId; + Op opCode; + std::vector operands; // operands, both and immediates (both are unsigned int) + std::vector idOperand; // true for operands that are , false for immediates + Block* block; +}; + +// +// SPIR-V IR block. +// + +class Block { +public: + Block(Id id, Function& parent); + virtual ~Block() + { + } + + Id getId() { return instructions.front()->getResultId(); } + + Function& getParent() const { return parent; } + void addInstruction(std::unique_ptr inst); + void addPredecessor(Block* pred) { predecessors.push_back(pred); pred->successors.push_back(this);} + void addLocalVariable(std::unique_ptr inst) { localVariables.push_back(std::move(inst)); } + const std::vector& getPredecessors() const { return predecessors; } + const std::vector& getSuccessors() const { return successors; } + const std::vector >& getInstructions() const { + return instructions; + } + const std::vector >& getLocalVariables() const { return localVariables; } + void setUnreachable() { unreachable = true; } + bool isUnreachable() const { return unreachable; } + // Returns the block's merge instruction, if one exists (otherwise null). + const Instruction* getMergeInstruction() const { + if (instructions.size() < 2) return nullptr; + const Instruction* nextToLast = (instructions.cend() - 2)->get(); + switch (nextToLast->getOpCode()) { + case OpSelectionMerge: + case OpLoopMerge: + return nextToLast; + default: + return nullptr; + } + return nullptr; + } + + // Change this block into a canonical dead merge block. Delete instructions + // as necessary. A canonical dead merge block has only an OpLabel and an + // OpUnreachable. + void rewriteAsCanonicalUnreachableMerge() { + assert(localVariables.empty()); + // Delete all instructions except for the label. + assert(instructions.size() > 0); + instructions.resize(1); + successors.clear(); + addInstruction(std::unique_ptr(new Instruction(OpUnreachable))); + } + // Change this block into a canonical dead continue target branching to the + // given header ID. Delete instructions as necessary. A canonical dead continue + // target has only an OpLabel and an unconditional branch back to the corresponding + // header. + void rewriteAsCanonicalUnreachableContinue(Block* header) { + assert(localVariables.empty()); + // Delete all instructions except for the label. + assert(instructions.size() > 0); + instructions.resize(1); + successors.clear(); + // Add OpBranch back to the header. + assert(header != nullptr); + Instruction* branch = new Instruction(OpBranch); + branch->addIdOperand(header->getId()); + addInstruction(std::unique_ptr(branch)); + successors.push_back(header); + } + + bool isTerminated() const + { + switch (instructions.back()->getOpCode()) { + case OpBranch: + case OpBranchConditional: + case OpSwitch: + case OpKill: + case OpReturn: + case OpReturnValue: + case OpUnreachable: + return true; + default: + return false; + } + } + + void dump(std::vector& out) const + { + instructions[0]->dump(out); + for (int i = 0; i < (int)localVariables.size(); ++i) + localVariables[i]->dump(out); + for (int i = 1; i < (int)instructions.size(); ++i) + instructions[i]->dump(out); + } + +protected: + Block(const Block&); + Block& operator=(Block&); + + // To enforce keeping parent and ownership in sync: + friend Function; + + std::vector > instructions; + std::vector predecessors, successors; + std::vector > localVariables; + Function& parent; + + // track whether this block is known to be uncreachable (not necessarily + // true for all unreachable blocks, but should be set at least + // for the extraneous ones introduced by the builder). + bool unreachable; +}; + +// The different reasons for reaching a block in the inReadableOrder traversal. +enum ReachReason { + // Reachable from the entry block via transfers of control, i.e. branches. + ReachViaControlFlow = 0, + // A continue target that is not reachable via control flow. + ReachDeadContinue, + // A merge block that is not reachable via control flow. + ReachDeadMerge +}; + +// Traverses the control-flow graph rooted at root in an order suited for +// readable code generation. Invokes callback at every node in the traversal +// order. The callback arguments are: +// - the block, +// - the reason we reached the block, +// - if the reason was that block is an unreachable continue or unreachable merge block +// then the last parameter is the corresponding header block. +void inReadableOrder(Block* root, std::function callback); + +// +// SPIR-V IR Function. +// + +class Function { +public: + Function(Id id, Id resultType, Id functionType, Id firstParam, Module& parent); + virtual ~Function() + { + for (int i = 0; i < (int)parameterInstructions.size(); ++i) + delete parameterInstructions[i]; + + for (int i = 0; i < (int)blocks.size(); ++i) + delete blocks[i]; + } + Id getId() const { return functionInstruction.getResultId(); } + Id getParamId(int p) const { return parameterInstructions[p]->getResultId(); } + Id getParamType(int p) const { return parameterInstructions[p]->getTypeId(); } + + void addBlock(Block* block) { blocks.push_back(block); } + void removeBlock(Block* block) + { + auto found = find(blocks.begin(), blocks.end(), block); + assert(found != blocks.end()); + blocks.erase(found); + delete block; + } + + Module& getParent() const { return parent; } + Block* getEntryBlock() const { return blocks.front(); } + Block* getLastBlock() const { return blocks.back(); } + const std::vector& getBlocks() const { return blocks; } + void addLocalVariable(std::unique_ptr inst); + Id getReturnType() const { return functionInstruction.getTypeId(); } + + void setImplicitThis() { implicitThis = true; } + bool hasImplicitThis() const { return implicitThis; } + + void dump(std::vector& out) const + { + // OpFunction + functionInstruction.dump(out); + + // OpFunctionParameter + for (int p = 0; p < (int)parameterInstructions.size(); ++p) + parameterInstructions[p]->dump(out); + + // Blocks + inReadableOrder(blocks[0], [&out](const Block* b, ReachReason, Block*) { b->dump(out); }); + Instruction end(0, 0, OpFunctionEnd); + end.dump(out); + } + +protected: + Function(const Function&); + Function& operator=(Function&); + + Module& parent; + Instruction functionInstruction; + std::vector parameterInstructions; + std::vector blocks; + bool implicitThis; // true if this is a member function expecting to be passed a 'this' as the first argument +}; + +// +// SPIR-V IR Module. +// + +class Module { +public: + Module() {} + virtual ~Module() + { + // TODO delete things + } + + void addFunction(Function *fun) { functions.push_back(fun); } + + void mapInstruction(Instruction *instruction) + { + spv::Id resultId = instruction->getResultId(); + // map the instruction's result id + if (resultId >= idToInstruction.size()) + idToInstruction.resize(resultId + 16); + idToInstruction[resultId] = instruction; + } + + Instruction* getInstruction(Id id) const { return idToInstruction[id]; } + const std::vector& getFunctions() const { return functions; } + spv::Id getTypeId(Id resultId) const { + return idToInstruction[resultId] == nullptr ? NoType : idToInstruction[resultId]->getTypeId(); + } + StorageClass getStorageClass(Id typeId) const + { + assert(idToInstruction[typeId]->getOpCode() == spv::OpTypePointer); + return (StorageClass)idToInstruction[typeId]->getImmediateOperand(0); + } + + void dump(std::vector& out) const + { + for (int f = 0; f < (int)functions.size(); ++f) + functions[f]->dump(out); + } + +protected: + Module(const Module&); + std::vector functions; + + // map from result id to instruction having that result id + std::vector idToInstruction; + + // map from a result id to its type id +}; + +// +// Implementation (it's here due to circular type definitions). +// + +// Add both +// - the OpFunction instruction +// - all the OpFunctionParameter instructions +__inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, Module& parent) + : parent(parent), functionInstruction(id, resultType, OpFunction), implicitThis(false) +{ + // OpFunction + functionInstruction.addImmediateOperand(FunctionControlMaskNone); + functionInstruction.addIdOperand(functionType); + parent.mapInstruction(&functionInstruction); + parent.addFunction(this); + + // OpFunctionParameter + Instruction* typeInst = parent.getInstruction(functionType); + int numParams = typeInst->getNumOperands() - 1; + for (int p = 0; p < numParams; ++p) { + Instruction* param = new Instruction(firstParamId + p, typeInst->getIdOperand(p + 1), OpFunctionParameter); + parent.mapInstruction(param); + parameterInstructions.push_back(param); + } +} + +__inline void Function::addLocalVariable(std::unique_ptr inst) +{ + Instruction* raw_instruction = inst.get(); + blocks[0]->addLocalVariable(std::move(inst)); + parent.mapInstruction(raw_instruction); +} + +__inline Block::Block(Id id, Function& parent) : parent(parent), unreachable(false) +{ + instructions.push_back(std::unique_ptr(new Instruction(id, NoType, OpLabel))); + instructions.back()->setBlock(this); + parent.getParent().mapInstruction(instructions.back().get()); +} + +__inline void Block::addInstruction(std::unique_ptr inst) +{ + Instruction* raw_instruction = inst.get(); + instructions.push_back(std::move(inst)); + raw_instruction->setBlock(this); + if (raw_instruction->getResultId()) + parent.getParent().mapInstruction(raw_instruction); +} + +} // end spv namespace + +#endif // spvIR_H diff --git a/mac/include/glslang/Include/BaseTypes.h b/mac/include/glslang/Include/BaseTypes.h new file mode 100644 index 00000000..816b1794 --- /dev/null +++ b/mac/include/glslang/Include/BaseTypes.h @@ -0,0 +1,565 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 LunarG, Inc. +// Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _BASICTYPES_INCLUDED_ +#define _BASICTYPES_INCLUDED_ + +namespace glslang { + +// +// Basic type. Arrays, vectors, sampler details, etc., are orthogonal to this. +// +enum TBasicType { + EbtVoid, + EbtFloat, + EbtDouble, + EbtFloat16, + EbtInt8, + EbtUint8, + EbtInt16, + EbtUint16, + EbtInt, + EbtUint, + EbtInt64, + EbtUint64, + EbtBool, + EbtAtomicUint, + EbtSampler, + EbtStruct, + EbtBlock, + EbtAccStruct, + EbtReference, + EbtRayQuery, + + // HLSL types that live only temporarily. + EbtString, + + EbtNumTypes +}; + +// +// Storage qualifiers. Should align with different kinds of storage or +// resource or GLSL storage qualifier. Expansion is deprecated. +// +// N.B.: You probably DON'T want to add anything here, but rather just add it +// to the built-in variables. See the comment above TBuiltInVariable. +// +// A new built-in variable will normally be an existing qualifier, like 'in', 'out', etc. +// DO NOT follow the design pattern of, say EvqInstanceId, etc. +// +enum TStorageQualifier { + EvqTemporary, // For temporaries (within a function), read/write + EvqGlobal, // For globals read/write + EvqConst, // User-defined constant values, will be semantically constant and constant folded + EvqVaryingIn, // pipeline input, read only, also supercategory for all built-ins not included in this enum (see TBuiltInVariable) + EvqVaryingOut, // pipeline output, read/write, also supercategory for all built-ins not included in this enum (see TBuiltInVariable) + EvqUniform, // read only, shared with app + EvqBuffer, // read/write, shared with app + EvqShared, // compute shader's read/write 'shared' qualifier + + EvqPayload, + EvqPayloadIn, + EvqHitAttr, + EvqCallableData, + EvqCallableDataIn, + + // parameters + EvqIn, // also, for 'in' in the grammar before we know if it's a pipeline input or an 'in' parameter + EvqOut, // also, for 'out' in the grammar before we know if it's a pipeline output or an 'out' parameter + EvqInOut, + EvqConstReadOnly, // input; also other read-only types having neither a constant value nor constant-value semantics + + // built-ins read by vertex shader + EvqVertexId, + EvqInstanceId, + + // built-ins written by vertex shader + EvqPosition, + EvqPointSize, + EvqClipVertex, + + // built-ins read by fragment shader + EvqFace, + EvqFragCoord, + EvqPointCoord, + + // built-ins written by fragment shader + EvqFragColor, + EvqFragDepth, + + // end of list + EvqLast +}; + +// +// Subcategories of the TStorageQualifier, simply to give a direct mapping +// between built-in variable names and an numerical value (the enum). +// +// For backward compatibility, there is some redundancy between the +// TStorageQualifier and these. Existing members should both be maintained accurately. +// However, any new built-in variable (and any existing non-redundant one) +// must follow the pattern that the specific built-in is here, and only its +// general qualifier is in TStorageQualifier. +// +// Something like gl_Position, which is sometimes 'in' and sometimes 'out' +// shows up as two different built-in variables in a single stage, but +// only has a single enum in TBuiltInVariable, so both the +// TStorageQualifier and the TBuitinVariable are needed to distinguish +// between them. +// +enum TBuiltInVariable { + EbvNone, + EbvNumWorkGroups, + EbvWorkGroupSize, + EbvWorkGroupId, + EbvLocalInvocationId, + EbvGlobalInvocationId, + EbvLocalInvocationIndex, + EbvNumSubgroups, + EbvSubgroupID, + EbvSubGroupSize, + EbvSubGroupInvocation, + EbvSubGroupEqMask, + EbvSubGroupGeMask, + EbvSubGroupGtMask, + EbvSubGroupLeMask, + EbvSubGroupLtMask, + EbvSubgroupSize2, + EbvSubgroupInvocation2, + EbvSubgroupEqMask2, + EbvSubgroupGeMask2, + EbvSubgroupGtMask2, + EbvSubgroupLeMask2, + EbvSubgroupLtMask2, + EbvVertexId, + EbvInstanceId, + EbvVertexIndex, + EbvInstanceIndex, + EbvBaseVertex, + EbvBaseInstance, + EbvDrawId, + EbvPosition, + EbvPointSize, + EbvClipVertex, + EbvClipDistance, + EbvCullDistance, + EbvNormal, + EbvVertex, + EbvMultiTexCoord0, + EbvMultiTexCoord1, + EbvMultiTexCoord2, + EbvMultiTexCoord3, + EbvMultiTexCoord4, + EbvMultiTexCoord5, + EbvMultiTexCoord6, + EbvMultiTexCoord7, + EbvFrontColor, + EbvBackColor, + EbvFrontSecondaryColor, + EbvBackSecondaryColor, + EbvTexCoord, + EbvFogFragCoord, + EbvInvocationId, + EbvPrimitiveId, + EbvLayer, + EbvViewportIndex, + EbvPatchVertices, + EbvTessLevelOuter, + EbvTessLevelInner, + EbvBoundingBox, + EbvTessCoord, + EbvColor, + EbvSecondaryColor, + EbvFace, + EbvFragCoord, + EbvPointCoord, + EbvFragColor, + EbvFragData, + EbvFragDepth, + EbvFragStencilRef, + EbvSampleId, + EbvSamplePosition, + EbvSampleMask, + EbvHelperInvocation, + + EbvBaryCoordNoPersp, + EbvBaryCoordNoPerspCentroid, + EbvBaryCoordNoPerspSample, + EbvBaryCoordSmooth, + EbvBaryCoordSmoothCentroid, + EbvBaryCoordSmoothSample, + EbvBaryCoordPullModel, + + EbvViewIndex, + EbvDeviceIndex, + + EbvFragSizeEXT, + EbvFragInvocationCountEXT, + + EbvViewportMaskNV, + EbvSecondaryPositionNV, + EbvSecondaryViewportMaskNV, + EbvPositionPerViewNV, + EbvViewportMaskPerViewNV, + EbvFragFullyCoveredNV, + EbvFragmentSizeNV, + EbvInvocationsPerPixelNV, + // ray tracing + EbvLaunchId, + EbvLaunchSize, + EbvInstanceCustomIndex, + EbvGeometryIndex, + EbvWorldRayOrigin, + EbvWorldRayDirection, + EbvObjectRayOrigin, + EbvObjectRayDirection, + EbvRayTmin, + EbvRayTmax, + EbvHitT, + EbvHitKind, + EbvObjectToWorld, + EbvObjectToWorld3x4, + EbvWorldToObject, + EbvWorldToObject3x4, + EbvIncomingRayFlags, + // barycentrics + EbvBaryCoordNV, + EbvBaryCoordNoPerspNV, + // mesh shaders + EbvTaskCountNV, + EbvPrimitiveCountNV, + EbvPrimitiveIndicesNV, + EbvClipDistancePerViewNV, + EbvCullDistancePerViewNV, + EbvLayerPerViewNV, + EbvMeshViewCountNV, + EbvMeshViewIndicesNV, + + // sm builtins + EbvWarpsPerSM, + EbvSMCount, + EbvWarpID, + EbvSMID, + + // HLSL built-ins that live only temporarily, until they get remapped + // to one of the above. + EbvFragDepthGreater, + EbvFragDepthLesser, + EbvGsOutputStream, + EbvOutputPatch, + EbvInputPatch, + + // structbuffer types + EbvAppendConsume, // no need to differentiate append and consume + EbvRWStructuredBuffer, + EbvStructuredBuffer, + EbvByteAddressBuffer, + EbvRWByteAddressBuffer, + + EbvLast +}; + +// In this enum, order matters; users can assume higher precision is a bigger value +// and EpqNone is 0. +enum TPrecisionQualifier { + EpqNone = 0, + EpqLow, + EpqMedium, + EpqHigh +}; + +#ifdef GLSLANG_WEB +__inline const char* GetStorageQualifierString(TStorageQualifier q) { return ""; } +__inline const char* GetPrecisionQualifierString(TPrecisionQualifier p) { return ""; } +#else +// These will show up in error messages +__inline const char* GetStorageQualifierString(TStorageQualifier q) +{ + switch (q) { + case EvqTemporary: return "temp"; break; + case EvqGlobal: return "global"; break; + case EvqConst: return "const"; break; + case EvqConstReadOnly: return "const (read only)"; break; + case EvqVaryingIn: return "in"; break; + case EvqVaryingOut: return "out"; break; + case EvqUniform: return "uniform"; break; + case EvqBuffer: return "buffer"; break; + case EvqShared: return "shared"; break; + case EvqIn: return "in"; break; + case EvqOut: return "out"; break; + case EvqInOut: return "inout"; break; + case EvqVertexId: return "gl_VertexId"; break; + case EvqInstanceId: return "gl_InstanceId"; break; + case EvqPosition: return "gl_Position"; break; + case EvqPointSize: return "gl_PointSize"; break; + case EvqClipVertex: return "gl_ClipVertex"; break; + case EvqFace: return "gl_FrontFacing"; break; + case EvqFragCoord: return "gl_FragCoord"; break; + case EvqPointCoord: return "gl_PointCoord"; break; + case EvqFragColor: return "fragColor"; break; + case EvqFragDepth: return "gl_FragDepth"; break; + case EvqPayload: return "rayPayloadNV"; break; + case EvqPayloadIn: return "rayPayloadInNV"; break; + case EvqHitAttr: return "hitAttributeNV"; break; + case EvqCallableData: return "callableDataNV"; break; + case EvqCallableDataIn: return "callableDataInNV"; break; + default: return "unknown qualifier"; + } +} + +__inline const char* GetBuiltInVariableString(TBuiltInVariable v) +{ + switch (v) { + case EbvNone: return ""; + case EbvNumWorkGroups: return "NumWorkGroups"; + case EbvWorkGroupSize: return "WorkGroupSize"; + case EbvWorkGroupId: return "WorkGroupID"; + case EbvLocalInvocationId: return "LocalInvocationID"; + case EbvGlobalInvocationId: return "GlobalInvocationID"; + case EbvLocalInvocationIndex: return "LocalInvocationIndex"; + case EbvNumSubgroups: return "NumSubgroups"; + case EbvSubgroupID: return "SubgroupID"; + case EbvSubGroupSize: return "SubGroupSize"; + case EbvSubGroupInvocation: return "SubGroupInvocation"; + case EbvSubGroupEqMask: return "SubGroupEqMask"; + case EbvSubGroupGeMask: return "SubGroupGeMask"; + case EbvSubGroupGtMask: return "SubGroupGtMask"; + case EbvSubGroupLeMask: return "SubGroupLeMask"; + case EbvSubGroupLtMask: return "SubGroupLtMask"; + case EbvSubgroupSize2: return "SubgroupSize"; + case EbvSubgroupInvocation2: return "SubgroupInvocationID"; + case EbvSubgroupEqMask2: return "SubgroupEqMask"; + case EbvSubgroupGeMask2: return "SubgroupGeMask"; + case EbvSubgroupGtMask2: return "SubgroupGtMask"; + case EbvSubgroupLeMask2: return "SubgroupLeMask"; + case EbvSubgroupLtMask2: return "SubgroupLtMask"; + case EbvVertexId: return "VertexId"; + case EbvInstanceId: return "InstanceId"; + case EbvVertexIndex: return "VertexIndex"; + case EbvInstanceIndex: return "InstanceIndex"; + case EbvBaseVertex: return "BaseVertex"; + case EbvBaseInstance: return "BaseInstance"; + case EbvDrawId: return "DrawId"; + case EbvPosition: return "Position"; + case EbvPointSize: return "PointSize"; + case EbvClipVertex: return "ClipVertex"; + case EbvClipDistance: return "ClipDistance"; + case EbvCullDistance: return "CullDistance"; + case EbvNormal: return "Normal"; + case EbvVertex: return "Vertex"; + case EbvMultiTexCoord0: return "MultiTexCoord0"; + case EbvMultiTexCoord1: return "MultiTexCoord1"; + case EbvMultiTexCoord2: return "MultiTexCoord2"; + case EbvMultiTexCoord3: return "MultiTexCoord3"; + case EbvMultiTexCoord4: return "MultiTexCoord4"; + case EbvMultiTexCoord5: return "MultiTexCoord5"; + case EbvMultiTexCoord6: return "MultiTexCoord6"; + case EbvMultiTexCoord7: return "MultiTexCoord7"; + case EbvFrontColor: return "FrontColor"; + case EbvBackColor: return "BackColor"; + case EbvFrontSecondaryColor: return "FrontSecondaryColor"; + case EbvBackSecondaryColor: return "BackSecondaryColor"; + case EbvTexCoord: return "TexCoord"; + case EbvFogFragCoord: return "FogFragCoord"; + case EbvInvocationId: return "InvocationID"; + case EbvPrimitiveId: return "PrimitiveID"; + case EbvLayer: return "Layer"; + case EbvViewportIndex: return "ViewportIndex"; + case EbvPatchVertices: return "PatchVertices"; + case EbvTessLevelOuter: return "TessLevelOuter"; + case EbvTessLevelInner: return "TessLevelInner"; + case EbvBoundingBox: return "BoundingBox"; + case EbvTessCoord: return "TessCoord"; + case EbvColor: return "Color"; + case EbvSecondaryColor: return "SecondaryColor"; + case EbvFace: return "Face"; + case EbvFragCoord: return "FragCoord"; + case EbvPointCoord: return "PointCoord"; + case EbvFragColor: return "FragColor"; + case EbvFragData: return "FragData"; + case EbvFragDepth: return "FragDepth"; + case EbvFragStencilRef: return "FragStencilRef"; + case EbvSampleId: return "SampleId"; + case EbvSamplePosition: return "SamplePosition"; + case EbvSampleMask: return "SampleMaskIn"; + case EbvHelperInvocation: return "HelperInvocation"; + + case EbvBaryCoordNoPersp: return "BaryCoordNoPersp"; + case EbvBaryCoordNoPerspCentroid: return "BaryCoordNoPerspCentroid"; + case EbvBaryCoordNoPerspSample: return "BaryCoordNoPerspSample"; + case EbvBaryCoordSmooth: return "BaryCoordSmooth"; + case EbvBaryCoordSmoothCentroid: return "BaryCoordSmoothCentroid"; + case EbvBaryCoordSmoothSample: return "BaryCoordSmoothSample"; + case EbvBaryCoordPullModel: return "BaryCoordPullModel"; + + case EbvViewIndex: return "ViewIndex"; + case EbvDeviceIndex: return "DeviceIndex"; + + case EbvFragSizeEXT: return "FragSizeEXT"; + case EbvFragInvocationCountEXT: return "FragInvocationCountEXT"; + + case EbvViewportMaskNV: return "ViewportMaskNV"; + case EbvSecondaryPositionNV: return "SecondaryPositionNV"; + case EbvSecondaryViewportMaskNV: return "SecondaryViewportMaskNV"; + case EbvPositionPerViewNV: return "PositionPerViewNV"; + case EbvViewportMaskPerViewNV: return "ViewportMaskPerViewNV"; + case EbvFragFullyCoveredNV: return "FragFullyCoveredNV"; + case EbvFragmentSizeNV: return "FragmentSizeNV"; + case EbvInvocationsPerPixelNV: return "InvocationsPerPixelNV"; + case EbvLaunchId: return "LaunchIdNV"; + case EbvLaunchSize: return "LaunchSizeNV"; + case EbvInstanceCustomIndex: return "InstanceCustomIndexNV"; + case EbvGeometryIndex: return "GeometryIndexEXT"; + case EbvWorldRayOrigin: return "WorldRayOriginNV"; + case EbvWorldRayDirection: return "WorldRayDirectionNV"; + case EbvObjectRayOrigin: return "ObjectRayOriginNV"; + case EbvObjectRayDirection: return "ObjectRayDirectionNV"; + case EbvRayTmin: return "ObjectRayTminNV"; + case EbvRayTmax: return "ObjectRayTmaxNV"; + case EbvHitT: return "HitTNV"; + case EbvHitKind: return "HitKindNV"; + case EbvIncomingRayFlags: return "IncomingRayFlagsNV"; + case EbvObjectToWorld: return "ObjectToWorldNV"; + case EbvWorldToObject: return "WorldToObjectNV"; + + case EbvBaryCoordNV: return "BaryCoordNV"; + case EbvBaryCoordNoPerspNV: return "BaryCoordNoPerspNV"; + + case EbvTaskCountNV: return "TaskCountNV"; + case EbvPrimitiveCountNV: return "PrimitiveCountNV"; + case EbvPrimitiveIndicesNV: return "PrimitiveIndicesNV"; + case EbvClipDistancePerViewNV: return "ClipDistancePerViewNV"; + case EbvCullDistancePerViewNV: return "CullDistancePerViewNV"; + case EbvLayerPerViewNV: return "LayerPerViewNV"; + case EbvMeshViewCountNV: return "MeshViewCountNV"; + case EbvMeshViewIndicesNV: return "MeshViewIndicesNV"; + + case EbvWarpsPerSM: return "WarpsPerSMNV"; + case EbvSMCount: return "SMCountNV"; + case EbvWarpID: return "WarpIDNV"; + case EbvSMID: return "SMIDNV"; + + default: return "unknown built-in variable"; + } +} + +__inline const char* GetPrecisionQualifierString(TPrecisionQualifier p) +{ + switch (p) { + case EpqNone: return ""; break; + case EpqLow: return "lowp"; break; + case EpqMedium: return "mediump"; break; + case EpqHigh: return "highp"; break; + default: return "unknown precision qualifier"; + } +} +#endif + +__inline bool isTypeSignedInt(TBasicType type) +{ + switch (type) { + case EbtInt8: + case EbtInt16: + case EbtInt: + case EbtInt64: + return true; + default: + return false; + } +} + +__inline bool isTypeUnsignedInt(TBasicType type) +{ + switch (type) { + case EbtUint8: + case EbtUint16: + case EbtUint: + case EbtUint64: + return true; + default: + return false; + } +} + +__inline bool isTypeInt(TBasicType type) +{ + return isTypeSignedInt(type) || isTypeUnsignedInt(type); +} + +__inline bool isTypeFloat(TBasicType type) +{ + switch (type) { + case EbtFloat: + case EbtDouble: + case EbtFloat16: + return true; + default: + return false; + } +} + +__inline int getTypeRank(TBasicType type) +{ + int res = -1; + switch(type) { + case EbtInt8: + case EbtUint8: + res = 0; + break; + case EbtInt16: + case EbtUint16: + res = 1; + break; + case EbtInt: + case EbtUint: + res = 2; + break; + case EbtInt64: + case EbtUint64: + res = 3; + break; + default: + assert(false); + break; + } + return res; +} + +} // end namespace glslang + +#endif // _BASICTYPES_INCLUDED_ diff --git a/mac/include/glslang/Include/Common.h b/mac/include/glslang/Include/Common.h new file mode 100644 index 00000000..733a790c --- /dev/null +++ b/mac/include/glslang/Include/Common.h @@ -0,0 +1,292 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _COMMON_INCLUDED_ +#define _COMMON_INCLUDED_ + + +#if defined(__ANDROID__) || (defined(_MSC_VER) && _MSC_VER < 1700) +#include +namespace std { +template +std::string to_string(const T& val) { + std::ostringstream os; + os << val; + return os.str(); +} +} +#endif + +#if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/) || defined MINGW_HAS_SECURE_API + #include + #ifndef snprintf + #define snprintf sprintf_s + #endif + #define safe_vsprintf(buf,max,format,args) vsnprintf_s((buf), (max), (max), (format), (args)) +#elif defined (solaris) + #define safe_vsprintf(buf,max,format,args) vsnprintf((buf), (max), (format), (args)) + #include + #define UINT_PTR uintptr_t +#else + #define safe_vsprintf(buf,max,format,args) vsnprintf((buf), (max), (format), (args)) + #include + #define UINT_PTR uintptr_t +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1800 + #include + inline long long int strtoll (const char* str, char** endptr, int base) + { + return _strtoi64(str, endptr, base); + } + inline unsigned long long int strtoull (const char* str, char** endptr, int base) + { + return _strtoui64(str, endptr, base); + } + inline long long int atoll (const char* str) + { + return strtoll(str, NULL, 10); + } +#endif + +#if defined(_MSC_VER) +#define strdup _strdup +#endif + +/* windows only pragma */ +#ifdef _MSC_VER + #pragma warning(disable : 4786) // Don't warn about too long identifiers + #pragma warning(disable : 4514) // unused inline method + #pragma warning(disable : 4201) // nameless union +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "PoolAlloc.h" + +// +// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme. +// +#define POOL_ALLOCATOR_NEW_DELETE(A) \ + void* operator new(size_t s) { return (A).allocate(s); } \ + void* operator new(size_t, void *_Where) { return (_Where); } \ + void operator delete(void*) { } \ + void operator delete(void *, void *) { } \ + void* operator new[](size_t s) { return (A).allocate(s); } \ + void* operator new[](size_t, void *_Where) { return (_Where); } \ + void operator delete[](void*) { } \ + void operator delete[](void *, void *) { } + +namespace glslang { + + // + // Pool version of string. + // + typedef pool_allocator TStringAllocator; + typedef std::basic_string , TStringAllocator> TString; + +} // end namespace glslang + +// Repackage the std::hash for use by unordered map/set with a TString key. +namespace std { + + template<> struct hash { + std::size_t operator()(const glslang::TString& s) const + { + const unsigned _FNV_offset_basis = 2166136261U; + const unsigned _FNV_prime = 16777619U; + unsigned _Val = _FNV_offset_basis; + size_t _Count = s.size(); + const char* _First = s.c_str(); + for (size_t _Next = 0; _Next < _Count; ++_Next) + { + _Val ^= (unsigned)_First[_Next]; + _Val *= _FNV_prime; + } + + return _Val; + } + }; +} + +namespace glslang { + +inline TString* NewPoolTString(const char* s) +{ + void* memory = GetThreadPoolAllocator().allocate(sizeof(TString)); + return new(memory) TString(s); +} + +template inline T* NewPoolObject(T*) +{ + return new(GetThreadPoolAllocator().allocate(sizeof(T))) T; +} + +template inline T* NewPoolObject(T, int instances) +{ + return new(GetThreadPoolAllocator().allocate(instances * sizeof(T))) T[instances]; +} + +// +// Pool allocator versions of vectors, lists, and maps +// +template class TVector : public std::vector > { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + typedef typename std::vector >::size_type size_type; + TVector() : std::vector >() {} + TVector(const pool_allocator& a) : std::vector >(a) {} + TVector(size_type i) : std::vector >(i) {} + TVector(size_type i, const T& val) : std::vector >(i, val) {} +}; + +template class TList : public std::list > { +}; + +template > +class TMap : public std::map > > { +}; + +template , class PRED = std::equal_to > +class TUnorderedMap : public std::unordered_map > > { +}; + +// +// Persistent string memory. Should only be used for strings that survive +// across compiles/links. +// +typedef std::basic_string TPersistString; + +// +// templatized min and max functions. +// +template T Min(const T a, const T b) { return a < b ? a : b; } +template T Max(const T a, const T b) { return a > b ? a : b; } + +// +// Create a TString object from an integer. +// +#if defined _MSC_VER || defined MINGW_HAS_SECURE_API +inline const TString String(const int i, const int base = 10) +{ + char text[16]; // 32 bit ints are at most 10 digits in base 10 + _itoa_s(i, text, sizeof(text), base); + return text; +} +#else +inline const TString String(const int i, const int /*base*/ = 10) +{ + char text[16]; // 32 bit ints are at most 10 digits in base 10 + + // we assume base 10 for all cases + snprintf(text, sizeof(text), "%d", i); + + return text; +} +#endif + +struct TSourceLoc { + void init() + { + name = nullptr; string = 0; line = 0; column = 0; + } + void init(int stringNum) { init(); string = stringNum; } + // Returns the name if it exists. Otherwise, returns the string number. + std::string getStringNameOrNum(bool quoteStringName = true) const + { + if (name != nullptr) { + TString qstr = quoteStringName ? ("\"" + *name + "\"") : *name; + std::string ret_str(qstr.c_str()); + return ret_str; + } + return std::to_string((long long)string); + } + const char* getFilename() const + { + if (name == nullptr) + return nullptr; + return name->c_str(); + } + const char* getFilenameStr() const { return name == nullptr ? "" : name->c_str(); } + TString* name; // descriptive name for this string, when a textual name is available, otherwise nullptr + int string; + int line; + int column; +}; + +class TPragmaTable : public TMap { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) +}; + +const int MaxTokenLength = 1024; + +template bool IsPow2(T powerOf2) +{ + if (powerOf2 <= 0) + return false; + + return (powerOf2 & (powerOf2 - 1)) == 0; +} + +// Round number up to a multiple of the given powerOf2, which is not +// a power, just a number that must be a power of 2. +template void RoundToPow2(T& number, int powerOf2) +{ + assert(IsPow2(powerOf2)); + number = (number + powerOf2 - 1) & ~(powerOf2 - 1); +} + +template bool IsMultipleOfPow2(T number, int powerOf2) +{ + assert(IsPow2(powerOf2)); + return ! (number & (powerOf2 - 1)); +} + +} // end namespace glslang + +#endif // _COMMON_INCLUDED_ diff --git a/mac/include/glslang/Include/ConstantUnion.h b/mac/include/glslang/Include/ConstantUnion.h new file mode 100644 index 00000000..c4ffb857 --- /dev/null +++ b/mac/include/glslang/Include/ConstantUnion.h @@ -0,0 +1,974 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013 LunarG, Inc. +// Copyright (C) 2017 ARM Limited. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _CONSTANT_UNION_INCLUDED_ +#define _CONSTANT_UNION_INCLUDED_ + +#include "../Include/Common.h" +#include "../Include/BaseTypes.h" + +namespace glslang { + +class TConstUnion { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + TConstUnion() : iConst(0), type(EbtInt) { } + + void setI8Const(signed char i) + { + i8Const = i; + type = EbtInt8; + } + + void setU8Const(unsigned char u) + { + u8Const = u; + type = EbtUint8; + } + + void setI16Const(signed short i) + { + i16Const = i; + type = EbtInt16; + } + + void setU16Const(unsigned short u) + { + u16Const = u; + type = EbtUint16; + } + + void setIConst(int i) + { + iConst = i; + type = EbtInt; + } + + void setUConst(unsigned int u) + { + uConst = u; + type = EbtUint; + } + + void setI64Const(long long i64) + { + i64Const = i64; + type = EbtInt64; + } + + void setU64Const(unsigned long long u64) + { + u64Const = u64; + type = EbtUint64; + } + + void setDConst(double d) + { + dConst = d; + type = EbtDouble; + } + + void setBConst(bool b) + { + bConst = b; + type = EbtBool; + } + + void setSConst(const TString* s) + { + sConst = s; + type = EbtString; + } + + signed char getI8Const() const { return i8Const; } + unsigned char getU8Const() const { return u8Const; } + signed short getI16Const() const { return i16Const; } + unsigned short getU16Const() const { return u16Const; } + int getIConst() const { return iConst; } + unsigned int getUConst() const { return uConst; } + long long getI64Const() const { return i64Const; } + unsigned long long getU64Const() const { return u64Const; } + double getDConst() const { return dConst; } + bool getBConst() const { return bConst; } + const TString* getSConst() const { return sConst; } + + bool operator==(const signed char i) const + { + if (i == i8Const) + return true; + + return false; + } + + bool operator==(const unsigned char u) const + { + if (u == u8Const) + return true; + + return false; + } + + bool operator==(const signed short i) const + { + if (i == i16Const) + return true; + + return false; + } + + bool operator==(const unsigned short u) const + { + if (u == u16Const) + return true; + + return false; + } + + bool operator==(const int i) const + { + if (i == iConst) + return true; + + return false; + } + + bool operator==(const unsigned int u) const + { + if (u == uConst) + return true; + + return false; + } + + bool operator==(const long long i64) const + { + if (i64 == i64Const) + return true; + + return false; + } + + bool operator==(const unsigned long long u64) const + { + if (u64 == u64Const) + return true; + + return false; + } + + bool operator==(const double d) const + { + if (d == dConst) + return true; + + return false; + } + + bool operator==(const bool b) const + { + if (b == bConst) + return true; + + return false; + } + + bool operator==(const TConstUnion& constant) const + { + if (constant.type != type) + return false; + + switch (type) { + case EbtInt: + if (constant.iConst == iConst) + return true; + + break; + case EbtUint: + if (constant.uConst == uConst) + return true; + + break; + case EbtBool: + if (constant.bConst == bConst) + return true; + + break; + case EbtDouble: + if (constant.dConst == dConst) + return true; + + break; + +#ifndef GLSLANG_WEB + case EbtInt16: + if (constant.i16Const == i16Const) + return true; + + break; + case EbtUint16: + if (constant.u16Const == u16Const) + return true; + + break; + case EbtInt8: + if (constant.i8Const == i8Const) + return true; + + break; + case EbtUint8: + if (constant.u8Const == u8Const) + return true; + + break; + case EbtInt64: + if (constant.i64Const == i64Const) + return true; + + break; + case EbtUint64: + if (constant.u64Const == u64Const) + return true; + + break; +#endif + default: + assert(false && "Default missing"); + } + + return false; + } + + bool operator!=(const signed char i) const + { + return !operator==(i); + } + + bool operator!=(const unsigned char u) const + { + return !operator==(u); + } + + bool operator!=(const signed short i) const + { + return !operator==(i); + } + + bool operator!=(const unsigned short u) const + { + return !operator==(u); + } + + bool operator!=(const int i) const + { + return !operator==(i); + } + + bool operator!=(const unsigned int u) const + { + return !operator==(u); + } + + bool operator!=(const long long i) const + { + return !operator==(i); + } + + bool operator!=(const unsigned long long u) const + { + return !operator==(u); + } + + bool operator!=(const float f) const + { + return !operator==(f); + } + + bool operator!=(const bool b) const + { + return !operator==(b); + } + + bool operator!=(const TConstUnion& constant) const + { + return !operator==(constant); + } + + bool operator>(const TConstUnion& constant) const + { + assert(type == constant.type); + switch (type) { + case EbtInt: + if (iConst > constant.iConst) + return true; + + return false; + case EbtUint: + if (uConst > constant.uConst) + return true; + + return false; + case EbtDouble: + if (dConst > constant.dConst) + return true; + + return false; +#ifndef GLSLANG_WEB + case EbtInt8: + if (i8Const > constant.i8Const) + return true; + + return false; + case EbtUint8: + if (u8Const > constant.u8Const) + return true; + + return false; + case EbtInt16: + if (i16Const > constant.i16Const) + return true; + + return false; + case EbtUint16: + if (u16Const > constant.u16Const) + return true; + + return false; + case EbtInt64: + if (i64Const > constant.i64Const) + return true; + + return false; + case EbtUint64: + if (u64Const > constant.u64Const) + return true; + + return false; +#endif + default: + assert(false && "Default missing"); + return false; + } + } + + bool operator<(const TConstUnion& constant) const + { + assert(type == constant.type); + switch (type) { +#ifndef GLSLANG_WEB + case EbtInt8: + if (i8Const < constant.i8Const) + return true; + + return false; + case EbtUint8: + if (u8Const < constant.u8Const) + return true; + + return false; + case EbtInt16: + if (i16Const < constant.i16Const) + return true; + + return false; + case EbtUint16: + if (u16Const < constant.u16Const) + return true; + return false; + case EbtInt64: + if (i64Const < constant.i64Const) + return true; + + return false; + case EbtUint64: + if (u64Const < constant.u64Const) + return true; + + return false; +#endif + case EbtDouble: + if (dConst < constant.dConst) + return true; + + return false; + case EbtInt: + if (iConst < constant.iConst) + return true; + + return false; + case EbtUint: + if (uConst < constant.uConst) + return true; + + return false; + default: + assert(false && "Default missing"); + return false; + } + } + + TConstUnion operator+(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst + constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst + constant.uConst); break; + case EbtDouble: returnValue.setDConst(dConst + constant.dConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const + constant.i8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const + constant.i16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const + constant.i64Const); break; + case EbtUint8: returnValue.setU8Const(u8Const + constant.u8Const); break; + case EbtUint16: returnValue.setU16Const(u16Const + constant.u16Const); break; + case EbtUint64: returnValue.setU64Const(u64Const + constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator-(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst - constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst - constant.uConst); break; + case EbtDouble: returnValue.setDConst(dConst - constant.dConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const - constant.i8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const - constant.i16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const - constant.i64Const); break; + case EbtUint8: returnValue.setU8Const(u8Const - constant.u8Const); break; + case EbtUint16: returnValue.setU16Const(u16Const - constant.u16Const); break; + case EbtUint64: returnValue.setU64Const(u64Const - constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator*(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst * constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst * constant.uConst); break; + case EbtDouble: returnValue.setDConst(dConst * constant.dConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const * constant.i8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const * constant.i16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const * constant.i64Const); break; + case EbtUint8: returnValue.setU8Const(u8Const * constant.u8Const); break; + case EbtUint16: returnValue.setU16Const(u16Const * constant.u16Const); break; + case EbtUint64: returnValue.setU64Const(u64Const * constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator%(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst % constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst % constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const % constant.i8Const); break; + case EbtInt16: returnValue.setI8Const(i8Const % constant.i16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const % constant.i64Const); break; + case EbtUint8: returnValue.setU8Const(u8Const % constant.u8Const); break; + case EbtUint16: returnValue.setU16Const(u16Const % constant.u16Const); break; + case EbtUint64: returnValue.setU64Const(u64Const % constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator>>(const TConstUnion& constant) const + { + TConstUnion returnValue; + switch (type) { +#ifndef GLSLANG_WEB + case EbtInt8: + switch (constant.type) { + case EbtInt8: returnValue.setI8Const(i8Const >> constant.i8Const); break; + case EbtUint8: returnValue.setI8Const(i8Const >> constant.u8Const); break; + case EbtInt16: returnValue.setI8Const(i8Const >> constant.i16Const); break; + case EbtUint16: returnValue.setI8Const(i8Const >> constant.u16Const); break; + case EbtInt: returnValue.setI8Const(i8Const >> constant.iConst); break; + case EbtUint: returnValue.setI8Const(i8Const >> constant.uConst); break; + case EbtInt64: returnValue.setI8Const(i8Const >> constant.i64Const); break; + case EbtUint64: returnValue.setI8Const(i8Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint8: + switch (constant.type) { + case EbtInt8: returnValue.setU8Const(u8Const >> constant.i8Const); break; + case EbtUint8: returnValue.setU8Const(u8Const >> constant.u8Const); break; + case EbtInt16: returnValue.setU8Const(u8Const >> constant.i16Const); break; + case EbtUint16: returnValue.setU8Const(u8Const >> constant.u16Const); break; + case EbtInt: returnValue.setU8Const(u8Const >> constant.iConst); break; + case EbtUint: returnValue.setU8Const(u8Const >> constant.uConst); break; + case EbtInt64: returnValue.setU8Const(u8Const >> constant.i64Const); break; + case EbtUint64: returnValue.setU8Const(u8Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtInt16: + switch (constant.type) { + case EbtInt8: returnValue.setI16Const(i16Const >> constant.i8Const); break; + case EbtUint8: returnValue.setI16Const(i16Const >> constant.u8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const >> constant.i16Const); break; + case EbtUint16: returnValue.setI16Const(i16Const >> constant.u16Const); break; + case EbtInt: returnValue.setI16Const(i16Const >> constant.iConst); break; + case EbtUint: returnValue.setI16Const(i16Const >> constant.uConst); break; + case EbtInt64: returnValue.setI16Const(i16Const >> constant.i64Const); break; + case EbtUint64: returnValue.setI16Const(i16Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint16: + switch (constant.type) { + case EbtInt8: returnValue.setU16Const(u16Const >> constant.i8Const); break; + case EbtUint8: returnValue.setU16Const(u16Const >> constant.u8Const); break; + case EbtInt16: returnValue.setU16Const(u16Const >> constant.i16Const); break; + case EbtUint16: returnValue.setU16Const(u16Const >> constant.u16Const); break; + case EbtInt: returnValue.setU16Const(u16Const >> constant.iConst); break; + case EbtUint: returnValue.setU16Const(u16Const >> constant.uConst); break; + case EbtInt64: returnValue.setU16Const(u16Const >> constant.i64Const); break; + case EbtUint64: returnValue.setU16Const(u16Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; +#endif + case EbtInt: + switch (constant.type) { + case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break; + case EbtUint: returnValue.setIConst(iConst >> constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setIConst(iConst >> constant.i8Const); break; + case EbtUint8: returnValue.setIConst(iConst >> constant.u8Const); break; + case EbtInt16: returnValue.setIConst(iConst >> constant.i16Const); break; + case EbtUint16: returnValue.setIConst(iConst >> constant.u16Const); break; + case EbtInt64: returnValue.setIConst(iConst >> constant.i64Const); break; + case EbtUint64: returnValue.setIConst(iConst >> constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + break; + case EbtUint: + switch (constant.type) { + case EbtInt: returnValue.setUConst(uConst >> constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst >> constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setUConst(uConst >> constant.i8Const); break; + case EbtUint8: returnValue.setUConst(uConst >> constant.u8Const); break; + case EbtInt16: returnValue.setUConst(uConst >> constant.i16Const); break; + case EbtUint16: returnValue.setUConst(uConst >> constant.u16Const); break; + case EbtInt64: returnValue.setUConst(uConst >> constant.i64Const); break; + case EbtUint64: returnValue.setUConst(uConst >> constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + break; +#ifndef GLSLANG_WEB + case EbtInt64: + switch (constant.type) { + case EbtInt8: returnValue.setI64Const(i64Const >> constant.i8Const); break; + case EbtUint8: returnValue.setI64Const(i64Const >> constant.u8Const); break; + case EbtInt16: returnValue.setI64Const(i64Const >> constant.i16Const); break; + case EbtUint16: returnValue.setI64Const(i64Const >> constant.u16Const); break; + case EbtInt: returnValue.setI64Const(i64Const >> constant.iConst); break; + case EbtUint: returnValue.setI64Const(i64Const >> constant.uConst); break; + case EbtInt64: returnValue.setI64Const(i64Const >> constant.i64Const); break; + case EbtUint64: returnValue.setI64Const(i64Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint64: + switch (constant.type) { + case EbtInt8: returnValue.setU64Const(u64Const >> constant.i8Const); break; + case EbtUint8: returnValue.setU64Const(u64Const >> constant.u8Const); break; + case EbtInt16: returnValue.setU64Const(u64Const >> constant.i16Const); break; + case EbtUint16: returnValue.setU64Const(u64Const >> constant.u16Const); break; + case EbtInt: returnValue.setU64Const(u64Const >> constant.iConst); break; + case EbtUint: returnValue.setU64Const(u64Const >> constant.uConst); break; + case EbtInt64: returnValue.setU64Const(u64Const >> constant.i64Const); break; + case EbtUint64: returnValue.setU64Const(u64Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator<<(const TConstUnion& constant) const + { + TConstUnion returnValue; + switch (type) { +#ifndef GLSLANG_WEB + case EbtInt8: + switch (constant.type) { + case EbtInt8: returnValue.setI8Const(i8Const << constant.i8Const); break; + case EbtUint8: returnValue.setI8Const(i8Const << constant.u8Const); break; + case EbtInt16: returnValue.setI8Const(i8Const << constant.i16Const); break; + case EbtUint16: returnValue.setI8Const(i8Const << constant.u16Const); break; + case EbtInt: returnValue.setI8Const(i8Const << constant.iConst); break; + case EbtUint: returnValue.setI8Const(i8Const << constant.uConst); break; + case EbtInt64: returnValue.setI8Const(i8Const << constant.i64Const); break; + case EbtUint64: returnValue.setI8Const(i8Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint8: + switch (constant.type) { + case EbtInt8: returnValue.setU8Const(u8Const << constant.i8Const); break; + case EbtUint8: returnValue.setU8Const(u8Const << constant.u8Const); break; + case EbtInt16: returnValue.setU8Const(u8Const << constant.i16Const); break; + case EbtUint16: returnValue.setU8Const(u8Const << constant.u16Const); break; + case EbtInt: returnValue.setU8Const(u8Const << constant.iConst); break; + case EbtUint: returnValue.setU8Const(u8Const << constant.uConst); break; + case EbtInt64: returnValue.setU8Const(u8Const << constant.i64Const); break; + case EbtUint64: returnValue.setU8Const(u8Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtInt16: + switch (constant.type) { + case EbtInt8: returnValue.setI16Const(i16Const << constant.i8Const); break; + case EbtUint8: returnValue.setI16Const(i16Const << constant.u8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const << constant.i16Const); break; + case EbtUint16: returnValue.setI16Const(i16Const << constant.u16Const); break; + case EbtInt: returnValue.setI16Const(i16Const << constant.iConst); break; + case EbtUint: returnValue.setI16Const(i16Const << constant.uConst); break; + case EbtInt64: returnValue.setI16Const(i16Const << constant.i64Const); break; + case EbtUint64: returnValue.setI16Const(i16Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint16: + switch (constant.type) { + case EbtInt8: returnValue.setU16Const(u16Const << constant.i8Const); break; + case EbtUint8: returnValue.setU16Const(u16Const << constant.u8Const); break; + case EbtInt16: returnValue.setU16Const(u16Const << constant.i16Const); break; + case EbtUint16: returnValue.setU16Const(u16Const << constant.u16Const); break; + case EbtInt: returnValue.setU16Const(u16Const << constant.iConst); break; + case EbtUint: returnValue.setU16Const(u16Const << constant.uConst); break; + case EbtInt64: returnValue.setU16Const(u16Const << constant.i64Const); break; + case EbtUint64: returnValue.setU16Const(u16Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtInt64: + switch (constant.type) { + case EbtInt8: returnValue.setI64Const(i64Const << constant.i8Const); break; + case EbtUint8: returnValue.setI64Const(i64Const << constant.u8Const); break; + case EbtInt16: returnValue.setI64Const(i64Const << constant.i16Const); break; + case EbtUint16: returnValue.setI64Const(i64Const << constant.u16Const); break; + case EbtInt: returnValue.setI64Const(i64Const << constant.iConst); break; + case EbtUint: returnValue.setI64Const(i64Const << constant.uConst); break; + case EbtInt64: returnValue.setI64Const(i64Const << constant.i64Const); break; + case EbtUint64: returnValue.setI64Const(i64Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint64: + switch (constant.type) { + case EbtInt8: returnValue.setU64Const(u64Const << constant.i8Const); break; + case EbtUint8: returnValue.setU64Const(u64Const << constant.u8Const); break; + case EbtInt16: returnValue.setU64Const(u64Const << constant.i16Const); break; + case EbtUint16: returnValue.setU64Const(u64Const << constant.u16Const); break; + case EbtInt: returnValue.setU64Const(u64Const << constant.iConst); break; + case EbtUint: returnValue.setU64Const(u64Const << constant.uConst); break; + case EbtInt64: returnValue.setU64Const(u64Const << constant.i64Const); break; + case EbtUint64: returnValue.setU64Const(u64Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; +#endif + case EbtInt: + switch (constant.type) { + case EbtInt: returnValue.setIConst(iConst << constant.iConst); break; + case EbtUint: returnValue.setIConst(iConst << constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setIConst(iConst << constant.i8Const); break; + case EbtUint8: returnValue.setIConst(iConst << constant.u8Const); break; + case EbtInt16: returnValue.setIConst(iConst << constant.i16Const); break; + case EbtUint16: returnValue.setIConst(iConst << constant.u16Const); break; + case EbtInt64: returnValue.setIConst(iConst << constant.i64Const); break; + case EbtUint64: returnValue.setIConst(iConst << constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + break; + case EbtUint: + switch (constant.type) { + case EbtInt: returnValue.setUConst(uConst << constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst << constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setUConst(uConst << constant.i8Const); break; + case EbtUint8: returnValue.setUConst(uConst << constant.u8Const); break; + case EbtInt16: returnValue.setUConst(uConst << constant.i16Const); break; + case EbtUint16: returnValue.setUConst(uConst << constant.u16Const); break; + case EbtInt64: returnValue.setUConst(uConst << constant.i64Const); break; + case EbtUint64: returnValue.setUConst(uConst << constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator&(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst & constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst & constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const & constant.i8Const); break; + case EbtUint8: returnValue.setU8Const(u8Const & constant.u8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const & constant.i16Const); break; + case EbtUint16: returnValue.setU16Const(u16Const & constant.u16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const & constant.i64Const); break; + case EbtUint64: returnValue.setU64Const(u64Const & constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator|(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst | constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst | constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const | constant.i8Const); break; + case EbtUint8: returnValue.setU8Const(u8Const | constant.u8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const | constant.i16Const); break; + case EbtUint16: returnValue.setU16Const(u16Const | constant.u16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const | constant.i64Const); break; + case EbtUint64: returnValue.setU64Const(u64Const | constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator^(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst ^ constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst ^ constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const ^ constant.i8Const); break; + case EbtUint8: returnValue.setU8Const(u8Const ^ constant.u8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const ^ constant.i16Const); break; + case EbtUint16: returnValue.setU16Const(u16Const ^ constant.u16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const ^ constant.i64Const); break; + case EbtUint64: returnValue.setU64Const(u64Const ^ constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator~() const + { + TConstUnion returnValue; + switch (type) { + case EbtInt: returnValue.setIConst(~iConst); break; + case EbtUint: returnValue.setUConst(~uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(~i8Const); break; + case EbtUint8: returnValue.setU8Const(~u8Const); break; + case EbtInt16: returnValue.setI16Const(~i16Const); break; + case EbtUint16: returnValue.setU16Const(~u16Const); break; + case EbtInt64: returnValue.setI64Const(~i64Const); break; + case EbtUint64: returnValue.setU64Const(~u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator&&(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtBool: returnValue.setBConst(bConst && constant.bConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator||(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtBool: returnValue.setBConst(bConst || constant.bConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TBasicType getType() const { return type; } + +private: + union { + signed char i8Const; // used for i8vec, scalar int8s + unsigned char u8Const; // used for u8vec, scalar uint8s + signed short i16Const; // used for i16vec, scalar int16s + unsigned short u16Const; // used for u16vec, scalar uint16s + int iConst; // used for ivec, scalar ints + unsigned int uConst; // used for uvec, scalar uints + long long i64Const; // used for i64vec, scalar int64s + unsigned long long u64Const; // used for u64vec, scalar uint64s + bool bConst; // used for bvec, scalar bools + double dConst; // used for vec, dvec, mat, dmat, scalar floats and doubles + const TString* sConst; // string constant + }; + + TBasicType type; +}; + +// Encapsulate having a pointer to an array of TConstUnion, +// which only needs to be allocated if its size is going to be +// bigger than 0. +// +// One convenience is being able to use [] to go inside the array, instead +// of C++ assuming it as an array of pointers to vectors. +// +// General usage is that the size is known up front, and it is +// created once with the proper size. +// +class TConstUnionArray { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + TConstUnionArray() : unionArray(nullptr) { } + virtual ~TConstUnionArray() { } + + explicit TConstUnionArray(int size) + { + if (size == 0) + unionArray = nullptr; + else + unionArray = new TConstUnionVector(size); + } + TConstUnionArray(const TConstUnionArray& a) = default; + TConstUnionArray(const TConstUnionArray& a, int start, int size) + { + unionArray = new TConstUnionVector(size); + for (int i = 0; i < size; ++i) + (*unionArray)[i] = a[start + i]; + } + + // Use this constructor for a smear operation + TConstUnionArray(int size, const TConstUnion& val) + { + unionArray = new TConstUnionVector(size, val); + } + + int size() const { return unionArray ? (int)unionArray->size() : 0; } + TConstUnion& operator[](size_t index) { return (*unionArray)[index]; } + const TConstUnion& operator[](size_t index) const { return (*unionArray)[index]; } + bool operator==(const TConstUnionArray& rhs) const + { + // this includes the case that both are unallocated + if (unionArray == rhs.unionArray) + return true; + + if (! unionArray || ! rhs.unionArray) + return false; + + return *unionArray == *rhs.unionArray; + } + bool operator!=(const TConstUnionArray& rhs) const { return ! operator==(rhs); } + + double dot(const TConstUnionArray& rhs) + { + assert(rhs.unionArray->size() == unionArray->size()); + double sum = 0.0; + + for (size_t comp = 0; comp < unionArray->size(); ++comp) + sum += (*this)[comp].getDConst() * rhs[comp].getDConst(); + + return sum; + } + + bool empty() const { return unionArray == nullptr; } + +protected: + typedef TVector TConstUnionVector; + TConstUnionVector* unionArray; +}; + +} // end namespace glslang + +#endif // _CONSTANT_UNION_INCLUDED_ diff --git a/mac/include/glslang/Include/InfoSink.h b/mac/include/glslang/Include/InfoSink.h new file mode 100644 index 00000000..dceb603c --- /dev/null +++ b/mac/include/glslang/Include/InfoSink.h @@ -0,0 +1,144 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _INFOSINK_INCLUDED_ +#define _INFOSINK_INCLUDED_ + +#include "../Include/Common.h" +#include + +namespace glslang { + +// +// TPrefixType is used to centralize how info log messages start. +// See below. +// +enum TPrefixType { + EPrefixNone, + EPrefixWarning, + EPrefixError, + EPrefixInternalError, + EPrefixUnimplemented, + EPrefixNote +}; + +enum TOutputStream { + ENull = 0, + EDebugger = 0x01, + EStdOut = 0x02, + EString = 0x04, +}; +// +// Encapsulate info logs for all objects that have them. +// +// The methods are a general set of tools for getting a variety of +// messages and types inserted into the log. +// +class TInfoSinkBase { +public: + TInfoSinkBase() : outputStream(4) {} + void erase() { sink.erase(); } + TInfoSinkBase& operator<<(const TPersistString& t) { append(t); return *this; } + TInfoSinkBase& operator<<(char c) { append(1, c); return *this; } + TInfoSinkBase& operator<<(const char* s) { append(s); return *this; } + TInfoSinkBase& operator<<(int n) { append(String(n)); return *this; } + TInfoSinkBase& operator<<(unsigned int n) { append(String(n)); return *this; } + TInfoSinkBase& operator<<(float n) { const int size = 40; char buf[size]; + snprintf(buf, size, (fabs(n) > 1e-8 && fabs(n) < 1e8) || n == 0.0f ? "%f" : "%g", n); + append(buf); + return *this; } + TInfoSinkBase& operator+(const TPersistString& t) { append(t); return *this; } + TInfoSinkBase& operator+(const TString& t) { append(t); return *this; } + TInfoSinkBase& operator<<(const TString& t) { append(t); return *this; } + TInfoSinkBase& operator+(const char* s) { append(s); return *this; } + const char* c_str() const { return sink.c_str(); } + void prefix(TPrefixType message) { + switch(message) { + case EPrefixNone: break; + case EPrefixWarning: append("WARNING: "); break; + case EPrefixError: append("ERROR: "); break; + case EPrefixInternalError: append("INTERNAL ERROR: "); break; + case EPrefixUnimplemented: append("UNIMPLEMENTED: "); break; + case EPrefixNote: append("NOTE: "); break; + default: append("UNKNOWN ERROR: "); break; + } + } + void location(const TSourceLoc& loc) { + const int maxSize = 24; + char locText[maxSize]; + snprintf(locText, maxSize, ":%d", loc.line); + append(loc.getStringNameOrNum(false).c_str()); + append(locText); + append(": "); + } + void message(TPrefixType message, const char* s) { + prefix(message); + append(s); + append("\n"); + } + void message(TPrefixType message, const char* s, const TSourceLoc& loc) { + prefix(message); + location(loc); + append(s); + append("\n"); + } + + void setOutputStream(int output = 4) + { + outputStream = output; + } + +protected: + void append(const char* s); + + void append(int count, char c); + void append(const TPersistString& t); + void append(const TString& t); + + void checkMem(size_t growth) { if (sink.capacity() < sink.size() + growth + 2) + sink.reserve(sink.capacity() + sink.capacity() / 2); } + void appendToStream(const char* s); + TPersistString sink; + int outputStream; +}; + +} // end namespace glslang + +class TInfoSink { +public: + glslang::TInfoSinkBase info; + glslang::TInfoSinkBase debug; +}; + +#endif // _INFOSINK_INCLUDED_ diff --git a/mac/include/glslang/Include/InitializeGlobals.h b/mac/include/glslang/Include/InitializeGlobals.h new file mode 100644 index 00000000..95d0a40e --- /dev/null +++ b/mac/include/glslang/Include/InitializeGlobals.h @@ -0,0 +1,44 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef __INITIALIZE_GLOBALS_INCLUDED_ +#define __INITIALIZE_GLOBALS_INCLUDED_ + +namespace glslang { + +bool InitializePoolIndex(); + +} // end namespace glslang + +#endif // __INITIALIZE_GLOBALS_INCLUDED_ diff --git a/mac/include/glslang/Include/PoolAlloc.h b/mac/include/glslang/Include/PoolAlloc.h new file mode 100644 index 00000000..b8eccb88 --- /dev/null +++ b/mac/include/glslang/Include/PoolAlloc.h @@ -0,0 +1,316 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _POOLALLOC_INCLUDED_ +#define _POOLALLOC_INCLUDED_ + +#ifdef _DEBUG +# define GUARD_BLOCKS // define to enable guard block sanity checking +#endif + +// +// This header defines an allocator that can be used to efficiently +// allocate a large number of small requests for heap memory, with the +// intention that they are not individually deallocated, but rather +// collectively deallocated at one time. +// +// This simultaneously +// +// * Makes each individual allocation much more efficient; the +// typical allocation is trivial. +// * Completely avoids the cost of doing individual deallocation. +// * Saves the trouble of tracking down and plugging a large class of leaks. +// +// Individual classes can use this allocator by supplying their own +// new and delete methods. +// +// STL containers can use this allocator by using the pool_allocator +// class as the allocator (second) template argument. +// + +#include +#include +#include + +namespace glslang { + +// If we are using guard blocks, we must track each individual +// allocation. If we aren't using guard blocks, these +// never get instantiated, so won't have any impact. +// + +class TAllocation { +public: + TAllocation(size_t size, unsigned char* mem, TAllocation* prev = 0) : + size(size), mem(mem), prevAlloc(prev) { + // Allocations are bracketed: + // [allocationHeader][initialGuardBlock][userData][finalGuardBlock] + // This would be cleaner with if (guardBlockSize)..., but that + // makes the compiler print warnings about 0 length memsets, + // even with the if() protecting them. +# ifdef GUARD_BLOCKS + memset(preGuard(), guardBlockBeginVal, guardBlockSize); + memset(data(), userDataFill, size); + memset(postGuard(), guardBlockEndVal, guardBlockSize); +# endif + } + + void check() const { + checkGuardBlock(preGuard(), guardBlockBeginVal, "before"); + checkGuardBlock(postGuard(), guardBlockEndVal, "after"); + } + + void checkAllocList() const; + + // Return total size needed to accommodate user buffer of 'size', + // plus our tracking data. + inline static size_t allocationSize(size_t size) { + return size + 2 * guardBlockSize + headerSize(); + } + + // Offset from surrounding buffer to get to user data buffer. + inline static unsigned char* offsetAllocation(unsigned char* m) { + return m + guardBlockSize + headerSize(); + } + +private: + void checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const; + + // Find offsets to pre and post guard blocks, and user data buffer + unsigned char* preGuard() const { return mem + headerSize(); } + unsigned char* data() const { return preGuard() + guardBlockSize; } + unsigned char* postGuard() const { return data() + size; } + + size_t size; // size of the user data area + unsigned char* mem; // beginning of our allocation (pts to header) + TAllocation* prevAlloc; // prior allocation in the chain + + const static unsigned char guardBlockBeginVal; + const static unsigned char guardBlockEndVal; + const static unsigned char userDataFill; + + const static size_t guardBlockSize; +# ifdef GUARD_BLOCKS + inline static size_t headerSize() { return sizeof(TAllocation); } +# else + inline static size_t headerSize() { return 0; } +# endif +}; + +// +// There are several stacks. One is to track the pushing and popping +// of the user, and not yet implemented. The others are simply a +// repositories of free pages or used pages. +// +// Page stacks are linked together with a simple header at the beginning +// of each allocation obtained from the underlying OS. Multi-page allocations +// are returned to the OS. Individual page allocations are kept for future +// re-use. +// +// The "page size" used is not, nor must it match, the underlying OS +// page size. But, having it be about that size or equal to a set of +// pages is likely most optimal. +// +class TPoolAllocator { +public: + TPoolAllocator(int growthIncrement = 8*1024, int allocationAlignment = 16); + + // + // Don't call the destructor just to free up the memory, call pop() + // + ~TPoolAllocator(); + + // + // Call push() to establish a new place to pop memory too. Does not + // have to be called to get things started. + // + void push(); + + // + // Call pop() to free all memory allocated since the last call to push(), + // or if no last call to push, frees all memory since first allocation. + // + void pop(); + + // + // Call popAll() to free all memory allocated. + // + void popAll(); + + // + // Call allocate() to actually acquire memory. Returns 0 if no memory + // available, otherwise a properly aligned pointer to 'numBytes' of memory. + // + void* allocate(size_t numBytes); + + // + // There is no deallocate. The point of this class is that + // deallocation can be skipped by the user of it, as the model + // of use is to simultaneously deallocate everything at once + // by calling pop(), and to not have to solve memory leak problems. + // + +protected: + friend struct tHeader; + + struct tHeader { + tHeader(tHeader* nextPage, size_t pageCount) : +#ifdef GUARD_BLOCKS + lastAllocation(0), +#endif + nextPage(nextPage), pageCount(pageCount) { } + + ~tHeader() { +#ifdef GUARD_BLOCKS + if (lastAllocation) + lastAllocation->checkAllocList(); +#endif + } + +#ifdef GUARD_BLOCKS + TAllocation* lastAllocation; +#endif + tHeader* nextPage; + size_t pageCount; + }; + + struct tAllocState { + size_t offset; + tHeader* page; + }; + typedef std::vector tAllocStack; + + // Track allocations if and only if we're using guard blocks +#ifndef GUARD_BLOCKS + void* initializeAllocation(tHeader*, unsigned char* memory, size_t) { +#else + void* initializeAllocation(tHeader* block, unsigned char* memory, size_t numBytes) { + new(memory) TAllocation(numBytes, memory, block->lastAllocation); + block->lastAllocation = reinterpret_cast(memory); +#endif + + // This is optimized entirely away if GUARD_BLOCKS is not defined. + return TAllocation::offsetAllocation(memory); + } + + size_t pageSize; // granularity of allocation from the OS + size_t alignment; // all returned allocations will be aligned at + // this granularity, which will be a power of 2 + size_t alignmentMask; + size_t headerSkip; // amount of memory to skip to make room for the + // header (basically, size of header, rounded + // up to make it aligned + size_t currentPageOffset; // next offset in top of inUseList to allocate from + tHeader* freeList; // list of popped memory + tHeader* inUseList; // list of all memory currently being used + tAllocStack stack; // stack of where to allocate from, to partition pool + + int numCalls; // just an interesting statistic + size_t totalBytes; // just an interesting statistic +private: + TPoolAllocator& operator=(const TPoolAllocator&); // don't allow assignment operator + TPoolAllocator(const TPoolAllocator&); // don't allow default copy constructor +}; + +// +// There could potentially be many pools with pops happening at +// different times. But a simple use is to have a global pop +// with everyone using the same global allocator. +// +extern TPoolAllocator& GetThreadPoolAllocator(); +void SetThreadPoolAllocator(TPoolAllocator* poolAllocator); + +// +// This STL compatible allocator is intended to be used as the allocator +// parameter to templatized STL containers, like vector and map. +// +// It will use the pools for allocation, and not +// do any deallocation, but will still do destruction. +// +template +class pool_allocator { +public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T *pointer; + typedef const T *const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T value_type; + template + struct rebind { + typedef pool_allocator other; + }; + pointer address(reference x) const { return &x; } + const_pointer address(const_reference x) const { return &x; } + + pool_allocator() : allocator(GetThreadPoolAllocator()) { } + pool_allocator(TPoolAllocator& a) : allocator(a) { } + pool_allocator(const pool_allocator& p) : allocator(p.allocator) { } + + template + pool_allocator(const pool_allocator& p) : allocator(p.getAllocator()) { } + + pointer allocate(size_type n) { + return reinterpret_cast(getAllocator().allocate(n * sizeof(T))); } + pointer allocate(size_type n, const void*) { + return reinterpret_cast(getAllocator().allocate(n * sizeof(T))); } + + void deallocate(void*, size_type) { } + void deallocate(pointer, size_type) { } + + pointer _Charalloc(size_t n) { + return reinterpret_cast(getAllocator().allocate(n)); } + + void construct(pointer p, const T& val) { new ((void *)p) T(val); } + void destroy(pointer p) { p->T::~T(); } + + bool operator==(const pool_allocator& rhs) const { return &getAllocator() == &rhs.getAllocator(); } + bool operator!=(const pool_allocator& rhs) const { return &getAllocator() != &rhs.getAllocator(); } + + size_type max_size() const { return static_cast(-1) / sizeof(T); } + size_type max_size(int size) const { return static_cast(-1) / size; } + + TPoolAllocator& getAllocator() const { return allocator; } + +protected: + pool_allocator& operator=(const pool_allocator&) { return *this; } + TPoolAllocator& allocator; +}; + +} // end namespace glslang + +#endif // _POOLALLOC_INCLUDED_ diff --git a/mac/include/glslang/Include/ResourceLimits.h b/mac/include/glslang/Include/ResourceLimits.h new file mode 100644 index 00000000..106b21d9 --- /dev/null +++ b/mac/include/glslang/Include/ResourceLimits.h @@ -0,0 +1,149 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _RESOURCE_LIMITS_INCLUDED_ +#define _RESOURCE_LIMITS_INCLUDED_ + +struct TLimits { + bool nonInductiveForLoops; + bool whileLoops; + bool doWhileLoops; + bool generalUniformIndexing; + bool generalAttributeMatrixVectorIndexing; + bool generalVaryingIndexing; + bool generalSamplerIndexing; + bool generalVariableIndexing; + bool generalConstantMatrixVectorIndexing; +}; + +struct TBuiltInResource { + int maxLights; + int maxClipPlanes; + int maxTextureUnits; + int maxTextureCoords; + int maxVertexAttribs; + int maxVertexUniformComponents; + int maxVaryingFloats; + int maxVertexTextureImageUnits; + int maxCombinedTextureImageUnits; + int maxTextureImageUnits; + int maxFragmentUniformComponents; + int maxDrawBuffers; + int maxVertexUniformVectors; + int maxVaryingVectors; + int maxFragmentUniformVectors; + int maxVertexOutputVectors; + int maxFragmentInputVectors; + int minProgramTexelOffset; + int maxProgramTexelOffset; + int maxClipDistances; + int maxComputeWorkGroupCountX; + int maxComputeWorkGroupCountY; + int maxComputeWorkGroupCountZ; + int maxComputeWorkGroupSizeX; + int maxComputeWorkGroupSizeY; + int maxComputeWorkGroupSizeZ; + int maxComputeUniformComponents; + int maxComputeTextureImageUnits; + int maxComputeImageUniforms; + int maxComputeAtomicCounters; + int maxComputeAtomicCounterBuffers; + int maxVaryingComponents; + int maxVertexOutputComponents; + int maxGeometryInputComponents; + int maxGeometryOutputComponents; + int maxFragmentInputComponents; + int maxImageUnits; + int maxCombinedImageUnitsAndFragmentOutputs; + int maxCombinedShaderOutputResources; + int maxImageSamples; + int maxVertexImageUniforms; + int maxTessControlImageUniforms; + int maxTessEvaluationImageUniforms; + int maxGeometryImageUniforms; + int maxFragmentImageUniforms; + int maxCombinedImageUniforms; + int maxGeometryTextureImageUnits; + int maxGeometryOutputVertices; + int maxGeometryTotalOutputComponents; + int maxGeometryUniformComponents; + int maxGeometryVaryingComponents; + int maxTessControlInputComponents; + int maxTessControlOutputComponents; + int maxTessControlTextureImageUnits; + int maxTessControlUniformComponents; + int maxTessControlTotalOutputComponents; + int maxTessEvaluationInputComponents; + int maxTessEvaluationOutputComponents; + int maxTessEvaluationTextureImageUnits; + int maxTessEvaluationUniformComponents; + int maxTessPatchComponents; + int maxPatchVertices; + int maxTessGenLevel; + int maxViewports; + int maxVertexAtomicCounters; + int maxTessControlAtomicCounters; + int maxTessEvaluationAtomicCounters; + int maxGeometryAtomicCounters; + int maxFragmentAtomicCounters; + int maxCombinedAtomicCounters; + int maxAtomicCounterBindings; + int maxVertexAtomicCounterBuffers; + int maxTessControlAtomicCounterBuffers; + int maxTessEvaluationAtomicCounterBuffers; + int maxGeometryAtomicCounterBuffers; + int maxFragmentAtomicCounterBuffers; + int maxCombinedAtomicCounterBuffers; + int maxAtomicCounterBufferSize; + int maxTransformFeedbackBuffers; + int maxTransformFeedbackInterleavedComponents; + int maxCullDistances; + int maxCombinedClipAndCullDistances; + int maxSamples; + int maxMeshOutputVerticesNV; + int maxMeshOutputPrimitivesNV; + int maxMeshWorkGroupSizeX_NV; + int maxMeshWorkGroupSizeY_NV; + int maxMeshWorkGroupSizeZ_NV; + int maxTaskWorkGroupSizeX_NV; + int maxTaskWorkGroupSizeY_NV; + int maxTaskWorkGroupSizeZ_NV; + int maxMeshViewCountNV; + + TLimits limits; +}; + +#endif // _RESOURCE_LIMITS_INCLUDED_ diff --git a/mac/include/glslang/Include/ShHandle.h b/mac/include/glslang/Include/ShHandle.h new file mode 100644 index 00000000..df07bd8e --- /dev/null +++ b/mac/include/glslang/Include/ShHandle.h @@ -0,0 +1,176 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _SHHANDLE_INCLUDED_ +#define _SHHANDLE_INCLUDED_ + +// +// Machine independent part of the compiler private objects +// sent as ShHandle to the driver. +// +// This should not be included by driver code. +// + +#define SH_EXPORTING +#include "../Public/ShaderLang.h" +#include "../MachineIndependent/Versions.h" +#include "InfoSink.h" + +class TCompiler; +class TLinker; +class TUniformMap; + +// +// The base class used to back handles returned to the driver. +// +class TShHandleBase { +public: + TShHandleBase() { pool = new glslang::TPoolAllocator; } + virtual ~TShHandleBase() { delete pool; } + virtual TCompiler* getAsCompiler() { return 0; } + virtual TLinker* getAsLinker() { return 0; } + virtual TUniformMap* getAsUniformMap() { return 0; } + virtual glslang::TPoolAllocator* getPool() const { return pool; } +private: + glslang::TPoolAllocator* pool; +}; + +// +// The base class for the machine dependent linker to derive from +// for managing where uniforms live. +// +class TUniformMap : public TShHandleBase { +public: + TUniformMap() { } + virtual ~TUniformMap() { } + virtual TUniformMap* getAsUniformMap() { return this; } + virtual int getLocation(const char* name) = 0; + virtual TInfoSink& getInfoSink() { return infoSink; } + TInfoSink infoSink; +}; + +class TIntermNode; + +// +// The base class for the machine dependent compiler to derive from +// for managing object code from the compile. +// +class TCompiler : public TShHandleBase { +public: + TCompiler(EShLanguage l, TInfoSink& sink) : infoSink(sink) , language(l), haveValidObjectCode(false) { } + virtual ~TCompiler() { } + EShLanguage getLanguage() { return language; } + virtual TInfoSink& getInfoSink() { return infoSink; } + + virtual bool compile(TIntermNode* root, int version = 0, EProfile profile = ENoProfile) = 0; + + virtual TCompiler* getAsCompiler() { return this; } + virtual bool linkable() { return haveValidObjectCode; } + + TInfoSink& infoSink; +protected: + TCompiler& operator=(TCompiler&); + + EShLanguage language; + bool haveValidObjectCode; +}; + +// +// Link operations are based on a list of compile results... +// +typedef glslang::TVector TCompilerList; +typedef glslang::TVector THandleList; + +// +// The base class for the machine dependent linker to derive from +// to manage the resulting executable. +// + +class TLinker : public TShHandleBase { +public: + TLinker(EShExecutable e, TInfoSink& iSink) : + infoSink(iSink), + executable(e), + haveReturnableObjectCode(false), + appAttributeBindings(0), + fixedAttributeBindings(0), + excludedAttributes(0), + excludedCount(0), + uniformBindings(0) { } + virtual TLinker* getAsLinker() { return this; } + virtual ~TLinker() { } + virtual bool link(TCompilerList&, TUniformMap*) = 0; + virtual bool link(THandleList&) { return false; } + virtual void setAppAttributeBindings(const ShBindingTable* t) { appAttributeBindings = t; } + virtual void setFixedAttributeBindings(const ShBindingTable* t) { fixedAttributeBindings = t; } + virtual void getAttributeBindings(ShBindingTable const **t) const = 0; + virtual void setExcludedAttributes(const int* attributes, int count) { excludedAttributes = attributes; excludedCount = count; } + virtual ShBindingTable* getUniformBindings() const { return uniformBindings; } + virtual const void* getObjectCode() const { return 0; } // a real compiler would be returning object code here + virtual TInfoSink& getInfoSink() { return infoSink; } + TInfoSink& infoSink; +protected: + TLinker& operator=(TLinker&); + EShExecutable executable; + bool haveReturnableObjectCode; // true when objectCode is acceptable to send to driver + + const ShBindingTable* appAttributeBindings; + const ShBindingTable* fixedAttributeBindings; + const int* excludedAttributes; + int excludedCount; + ShBindingTable* uniformBindings; // created by the linker +}; + +// +// This is the interface between the machine independent code +// and the machine dependent code. +// +// The machine dependent code should derive from the classes +// above. Then Construct*() and Delete*() will create and +// destroy the machine dependent objects, which contain the +// above machine independent information. +// +TCompiler* ConstructCompiler(EShLanguage, int); + +TShHandleBase* ConstructLinker(EShExecutable, int); +TShHandleBase* ConstructBindings(); +void DeleteLinker(TShHandleBase*); +void DeleteBindingList(TShHandleBase* bindingList); + +TUniformMap* ConstructUniformMap(); +void DeleteCompiler(TCompiler*); + +void DeleteUniformMap(TUniformMap*); + +#endif // _SHHANDLE_INCLUDED_ diff --git a/mac/include/glslang/Include/Types.h b/mac/include/glslang/Include/Types.h new file mode 100644 index 00000000..b2c416d1 --- /dev/null +++ b/mac/include/glslang/Include/Types.h @@ -0,0 +1,2483 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2016 LunarG, Inc. +// Copyright (C) 2015-2016 Google, Inc. +// Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _TYPES_INCLUDED +#define _TYPES_INCLUDED + +#include "../Include/Common.h" +#include "../Include/BaseTypes.h" +#include "../Public/ShaderLang.h" +#include "arrays.h" + +#include + +namespace glslang { + +const int GlslangMaxTypeLength = 200; // TODO: need to print block/struct one member per line, so this can stay bounded + +const char* const AnonymousPrefix = "anon@"; // for something like a block whose members can be directly accessed +inline bool IsAnonymous(const TString& name) +{ + return name.compare(0, 5, AnonymousPrefix) == 0; +} + +// +// Details within a sampler type +// +enum TSamplerDim { + EsdNone, + Esd1D, + Esd2D, + Esd3D, + EsdCube, + EsdRect, + EsdBuffer, + EsdSubpass, // goes only with non-sampled image (image is true) + EsdNumDims +}; + +struct TSampler { // misnomer now; includes images, textures without sampler, and textures with sampler + TBasicType type : 8; // type returned by sampler + TSamplerDim dim : 8; + bool arrayed : 1; + bool shadow : 1; + bool ms : 1; + bool image : 1; // image, combined should be false + bool combined : 1; // true means texture is combined with a sampler, false means texture with no sampler + bool sampler : 1; // true means a pure sampler, other fields should be clear() + +#ifdef GLSLANG_WEB + bool is1D() const { return false; } + bool isBuffer() const { return false; } + bool isRect() const { return false; } + bool isSubpass() const { return false; } + bool isCombined() const { return true; } + bool isImage() const { return false; } + bool isImageClass() const { return false; } + bool isMultiSample() const { return false; } + bool isExternal() const { return false; } + void setExternal(bool e) { } + bool isYuv() const { return false; } +#else + unsigned int vectorSize : 3; // vector return type size. + // Some languages support structures as sample results. Storing the whole structure in the + // TSampler is too large, so there is an index to a separate table. + static const unsigned structReturnIndexBits = 4; // number of index bits to use. + static const unsigned structReturnSlots = (1< TTypeList; + +typedef TVector TIdentifierList; + +// +// Following are a series of helper enums for managing layouts and qualifiers, +// used for TPublicType, TType, others. +// + +enum TLayoutPacking { + ElpNone, + ElpShared, // default, but different than saying nothing + ElpStd140, + ElpStd430, + ElpPacked, + ElpScalar, + ElpCount // If expanding, see bitfield width below +}; + +enum TLayoutMatrix { + ElmNone, + ElmRowMajor, + ElmColumnMajor, // default, but different than saying nothing + ElmCount // If expanding, see bitfield width below +}; + +// Union of geometry shader and tessellation shader geometry types. +// They don't go into TType, but rather have current state per shader or +// active parser type (TPublicType). +enum TLayoutGeometry { + ElgNone, + ElgPoints, + ElgLines, + ElgLinesAdjacency, + ElgLineStrip, + ElgTriangles, + ElgTrianglesAdjacency, + ElgTriangleStrip, + ElgQuads, + ElgIsolines, +}; + +enum TVertexSpacing { + EvsNone, + EvsEqual, + EvsFractionalEven, + EvsFractionalOdd +}; + +enum TVertexOrder { + EvoNone, + EvoCw, + EvoCcw +}; + +// Note: order matters, as type of format is done by comparison. +enum TLayoutFormat { + ElfNone, + + // Float image + ElfRgba32f, + ElfRgba16f, + ElfR32f, + ElfRgba8, + ElfRgba8Snorm, + + ElfEsFloatGuard, // to help with comparisons + + ElfRg32f, + ElfRg16f, + ElfR11fG11fB10f, + ElfR16f, + ElfRgba16, + ElfRgb10A2, + ElfRg16, + ElfRg8, + ElfR16, + ElfR8, + ElfRgba16Snorm, + ElfRg16Snorm, + ElfRg8Snorm, + ElfR16Snorm, + ElfR8Snorm, + + ElfFloatGuard, // to help with comparisons + + // Int image + ElfRgba32i, + ElfRgba16i, + ElfRgba8i, + ElfR32i, + + ElfEsIntGuard, // to help with comparisons + + ElfRg32i, + ElfRg16i, + ElfRg8i, + ElfR16i, + ElfR8i, + + ElfIntGuard, // to help with comparisons + + // Uint image + ElfRgba32ui, + ElfRgba16ui, + ElfRgba8ui, + ElfR32ui, + + ElfEsUintGuard, // to help with comparisons + + ElfRg32ui, + ElfRg16ui, + ElfRgb10a2ui, + ElfRg8ui, + ElfR16ui, + ElfR8ui, + + ElfCount +}; + +enum TLayoutDepth { + EldNone, + EldAny, + EldGreater, + EldLess, + EldUnchanged, + + EldCount +}; + +enum TBlendEquationShift { + // No 'EBlendNone': + // These are used as bit-shift amounts. A mask of such shifts will have type 'int', + // and in that space, 0 means no bits set, or none. In this enum, 0 means (1 << 0), a bit is set. + EBlendMultiply, + EBlendScreen, + EBlendOverlay, + EBlendDarken, + EBlendLighten, + EBlendColordodge, + EBlendColorburn, + EBlendHardlight, + EBlendSoftlight, + EBlendDifference, + EBlendExclusion, + EBlendHslHue, + EBlendHslSaturation, + EBlendHslColor, + EBlendHslLuminosity, + EBlendAllEquations, + + EBlendCount +}; + +enum TInterlockOrdering { + EioNone, + EioPixelInterlockOrdered, + EioPixelInterlockUnordered, + EioSampleInterlockOrdered, + EioSampleInterlockUnordered, + EioShadingRateInterlockOrdered, + EioShadingRateInterlockUnordered, + + EioCount, +}; + +enum TShaderInterface +{ + // Includes both uniform blocks and buffer blocks + EsiUniform = 0, + EsiInput, + EsiOutput, + EsiNone, + + EsiCount +}; + + +class TQualifier { +public: + static const int layoutNotSet = -1; + + void clear() + { + precision = EpqNone; + invariant = false; + makeTemporary(); + declaredBuiltIn = EbvNone; +#ifndef GLSLANG_WEB + noContraction = false; +#endif + } + + // drop qualifiers that don't belong in a temporary variable + void makeTemporary() + { + semanticName = nullptr; + storage = EvqTemporary; + builtIn = EbvNone; + clearInterstage(); + clearMemory(); + specConstant = false; + nonUniform = false; + clearLayout(); + } + + void clearInterstage() + { + clearInterpolation(); +#ifndef GLSLANG_WEB + patch = false; + sample = false; +#endif + } + + void clearInterpolation() + { + centroid = false; + smooth = false; + flat = false; +#ifndef GLSLANG_WEB + nopersp = false; + explicitInterp = false; + pervertexNV = false; + perPrimitiveNV = false; + perViewNV = false; + perTaskNV = false; +#endif + } + + void clearMemory() + { +#ifndef GLSLANG_WEB + coherent = false; + devicecoherent = false; + queuefamilycoherent = false; + workgroupcoherent = false; + subgroupcoherent = false; + shadercallcoherent = false; + nonprivate = false; + volatil = false; + restrict = false; + readonly = false; + writeonly = false; +#endif + } + + const char* semanticName; + TStorageQualifier storage : 6; + TBuiltInVariable builtIn : 9; + TBuiltInVariable declaredBuiltIn : 9; + static_assert(EbvLast < 256, "need to increase size of TBuiltInVariable bitfields!"); + TPrecisionQualifier precision : 3; + bool invariant : 1; // require canonical treatment for cross-shader invariance + bool centroid : 1; + bool smooth : 1; + bool flat : 1; + // having a constant_id is not sufficient: expressions have no id, but are still specConstant + bool specConstant : 1; + bool nonUniform : 1; + bool explicitOffset : 1; + +#ifdef GLSLANG_WEB + bool isWriteOnly() const { return false; } + bool isReadOnly() const { return false; } + bool isRestrict() const { return false; } + bool isCoherent() const { return false; } + bool isVolatile() const { return false; } + bool isSample() const { return false; } + bool isMemory() const { return false; } + bool isMemoryQualifierImageAndSSBOOnly() const { return false; } + bool bufferReferenceNeedsVulkanMemoryModel() const { return false; } + bool isInterpolation() const { return flat || smooth; } + bool isExplicitInterpolation() const { return false; } + bool isAuxiliary() const { return centroid; } + bool isPatch() const { return false; } + bool isNoContraction() const { return false; } + void setNoContraction() { } + bool isPervertexNV() const { return false; } +#else + bool noContraction: 1; // prevent contraction and reassociation, e.g., for 'precise' keyword, and expressions it affects + bool nopersp : 1; + bool explicitInterp : 1; + bool pervertexNV : 1; + bool perPrimitiveNV : 1; + bool perViewNV : 1; + bool perTaskNV : 1; + bool patch : 1; + bool sample : 1; + bool restrict : 1; + bool readonly : 1; + bool writeonly : 1; + bool coherent : 1; + bool volatil : 1; + bool devicecoherent : 1; + bool queuefamilycoherent : 1; + bool workgroupcoherent : 1; + bool subgroupcoherent : 1; + bool shadercallcoherent : 1; + bool nonprivate : 1; + bool isWriteOnly() const { return writeonly; } + bool isReadOnly() const { return readonly; } + bool isRestrict() const { return restrict; } + bool isCoherent() const { return coherent; } + bool isVolatile() const { return volatil; } + bool isSample() const { return sample; } + bool isMemory() const + { + return shadercallcoherent || subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly || nonprivate; + } + bool isMemoryQualifierImageAndSSBOOnly() const + { + return shadercallcoherent || subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly; + } + bool bufferReferenceNeedsVulkanMemoryModel() const + { + // include qualifiers that map to load/store availability/visibility/nonprivate memory access operands + return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || nonprivate; + } + bool isInterpolation() const + { + return flat || smooth || nopersp || explicitInterp; + } + bool isExplicitInterpolation() const + { + return explicitInterp; + } + bool isAuxiliary() const + { + return centroid || patch || sample || pervertexNV; + } + bool isPatch() const { return patch; } + bool isNoContraction() const { return noContraction; } + void setNoContraction() { noContraction = true; } + bool isPervertexNV() const { return pervertexNV; } +#endif + + bool isPipeInput() const + { + switch (storage) { + case EvqVaryingIn: + case EvqFragCoord: + case EvqPointCoord: + case EvqFace: + case EvqVertexId: + case EvqInstanceId: + return true; + default: + return false; + } + } + + bool isPipeOutput() const + { + switch (storage) { + case EvqPosition: + case EvqPointSize: + case EvqClipVertex: + case EvqVaryingOut: + case EvqFragColor: + case EvqFragDepth: + return true; + default: + return false; + } + } + + bool isParamInput() const + { + switch (storage) { + case EvqIn: + case EvqInOut: + case EvqConstReadOnly: + return true; + default: + return false; + } + } + + bool isParamOutput() const + { + switch (storage) { + case EvqOut: + case EvqInOut: + return true; + default: + return false; + } + } + + bool isUniformOrBuffer() const + { + switch (storage) { + case EvqUniform: + case EvqBuffer: + return true; + default: + return false; + } + } + + bool isIo() const + { + switch (storage) { + case EvqUniform: + case EvqBuffer: + case EvqVaryingIn: + case EvqFragCoord: + case EvqPointCoord: + case EvqFace: + case EvqVertexId: + case EvqInstanceId: + case EvqPosition: + case EvqPointSize: + case EvqClipVertex: + case EvqVaryingOut: + case EvqFragColor: + case EvqFragDepth: + return true; + default: + return false; + } + } + + // non-built-in symbols that might link between compilation units + bool isLinkable() const + { + switch (storage) { + case EvqGlobal: + case EvqVaryingIn: + case EvqVaryingOut: + case EvqUniform: + case EvqBuffer: + case EvqShared: + return true; + default: + return false; + } + } + +#ifdef GLSLANG_WEB + bool isPerView() const { return false; } + bool isTaskMemory() const { return false; } + bool isArrayedIo(EShLanguage language) const { return false; } +#else + bool isPerPrimitive() const { return perPrimitiveNV; } + bool isPerView() const { return perViewNV; } + bool isTaskMemory() const { return perTaskNV; } + + // True if this type of IO is supposed to be arrayed with extra level for per-vertex data + bool isArrayedIo(EShLanguage language) const + { + switch (language) { + case EShLangGeometry: + return isPipeInput(); + case EShLangTessControl: + return ! patch && (isPipeInput() || isPipeOutput()); + case EShLangTessEvaluation: + return ! patch && isPipeInput(); + case EShLangFragment: + return pervertexNV && isPipeInput(); + case EShLangMeshNV: + return ! perTaskNV && isPipeOutput(); + + default: + return false; + } + } +#endif + + // Implementing an embedded layout-qualifier class here, since C++ can't have a real class bitfield + void clearLayout() // all layout + { + clearUniformLayout(); + +#ifndef GLSLANG_WEB + layoutPushConstant = false; + layoutBufferReference = false; + layoutPassthrough = false; + layoutViewportRelative = false; + // -2048 as the default value indicating layoutSecondaryViewportRelative is not set + layoutSecondaryViewportRelativeOffset = -2048; + layoutShaderRecord = false; + layoutBufferReferenceAlign = layoutBufferReferenceAlignEnd; + layoutFormat = ElfNone; +#endif + + clearInterstageLayout(); + + layoutSpecConstantId = layoutSpecConstantIdEnd; + } + void clearInterstageLayout() + { + layoutLocation = layoutLocationEnd; + layoutComponent = layoutComponentEnd; +#ifndef GLSLANG_WEB + layoutIndex = layoutIndexEnd; + clearStreamLayout(); + clearXfbLayout(); +#endif + } + +#ifndef GLSLANG_WEB + void clearStreamLayout() + { + layoutStream = layoutStreamEnd; + } + void clearXfbLayout() + { + layoutXfbBuffer = layoutXfbBufferEnd; + layoutXfbStride = layoutXfbStrideEnd; + layoutXfbOffset = layoutXfbOffsetEnd; + } +#endif + + bool hasNonXfbLayout() const + { + return hasUniformLayout() || + hasAnyLocation() || + hasStream() || + hasFormat() || + isShaderRecord() || + isPushConstant() || + hasBufferReference(); + } + bool hasLayout() const + { + return hasNonXfbLayout() || + hasXfb(); + } + TLayoutMatrix layoutMatrix : 3; + TLayoutPacking layoutPacking : 4; + int layoutOffset; + int layoutAlign; + + unsigned int layoutLocation : 12; + static const unsigned int layoutLocationEnd = 0xFFF; + + unsigned int layoutComponent : 3; + static const unsigned int layoutComponentEnd = 4; + + unsigned int layoutSet : 7; + static const unsigned int layoutSetEnd = 0x3F; + + unsigned int layoutBinding : 16; + static const unsigned int layoutBindingEnd = 0xFFFF; + + unsigned int layoutIndex : 8; + static const unsigned int layoutIndexEnd = 0xFF; + + unsigned int layoutStream : 8; + static const unsigned int layoutStreamEnd = 0xFF; + + unsigned int layoutXfbBuffer : 4; + static const unsigned int layoutXfbBufferEnd = 0xF; + + unsigned int layoutXfbStride : 14; + static const unsigned int layoutXfbStrideEnd = 0x3FFF; + + unsigned int layoutXfbOffset : 13; + static const unsigned int layoutXfbOffsetEnd = 0x1FFF; + + unsigned int layoutAttachment : 8; // for input_attachment_index + static const unsigned int layoutAttachmentEnd = 0XFF; + + unsigned int layoutSpecConstantId : 11; + static const unsigned int layoutSpecConstantIdEnd = 0x7FF; + +#ifndef GLSLANG_WEB + // stored as log2 of the actual alignment value + unsigned int layoutBufferReferenceAlign : 6; + static const unsigned int layoutBufferReferenceAlignEnd = 0x3F; + + TLayoutFormat layoutFormat : 8; + + bool layoutPushConstant; + bool layoutBufferReference; + bool layoutPassthrough; + bool layoutViewportRelative; + int layoutSecondaryViewportRelativeOffset; + bool layoutShaderRecord; +#endif + + bool hasUniformLayout() const + { + return hasMatrix() || + hasPacking() || + hasOffset() || + hasBinding() || + hasSet() || + hasAlign(); + } + void clearUniformLayout() // only uniform specific + { + layoutMatrix = ElmNone; + layoutPacking = ElpNone; + layoutOffset = layoutNotSet; + layoutAlign = layoutNotSet; + + layoutSet = layoutSetEnd; + layoutBinding = layoutBindingEnd; +#ifndef GLSLANG_WEB + layoutAttachment = layoutAttachmentEnd; +#endif + } + + bool hasMatrix() const + { + return layoutMatrix != ElmNone; + } + bool hasPacking() const + { + return layoutPacking != ElpNone; + } + bool hasAlign() const + { + return layoutAlign != layoutNotSet; + } + bool hasAnyLocation() const + { + return hasLocation() || + hasComponent() || + hasIndex(); + } + bool hasLocation() const + { + return layoutLocation != layoutLocationEnd; + } + bool hasSet() const + { + return layoutSet != layoutSetEnd; + } + bool hasBinding() const + { + return layoutBinding != layoutBindingEnd; + } +#ifdef GLSLANG_WEB + bool hasOffset() const { return false; } + bool isNonPerspective() const { return false; } + bool hasIndex() const { return false; } + unsigned getIndex() const { return 0; } + bool hasComponent() const { return false; } + bool hasStream() const { return false; } + bool hasFormat() const { return false; } + bool hasXfb() const { return false; } + bool hasXfbBuffer() const { return false; } + bool hasXfbStride() const { return false; } + bool hasXfbOffset() const { return false; } + bool hasAttachment() const { return false; } + TLayoutFormat getFormat() const { return ElfNone; } + bool isPushConstant() const { return false; } + bool isShaderRecord() const { return false; } + bool hasBufferReference() const { return false; } + bool hasBufferReferenceAlign() const { return false; } + bool isNonUniform() const { return false; } +#else + bool hasOffset() const + { + return layoutOffset != layoutNotSet; + } + bool isNonPerspective() const { return nopersp; } + bool hasIndex() const + { + return layoutIndex != layoutIndexEnd; + } + unsigned getIndex() const { return layoutIndex; } + bool hasComponent() const + { + return layoutComponent != layoutComponentEnd; + } + bool hasStream() const + { + return layoutStream != layoutStreamEnd; + } + bool hasFormat() const + { + return layoutFormat != ElfNone; + } + bool hasXfb() const + { + return hasXfbBuffer() || + hasXfbStride() || + hasXfbOffset(); + } + bool hasXfbBuffer() const + { + return layoutXfbBuffer != layoutXfbBufferEnd; + } + bool hasXfbStride() const + { + return layoutXfbStride != layoutXfbStrideEnd; + } + bool hasXfbOffset() const + { + return layoutXfbOffset != layoutXfbOffsetEnd; + } + bool hasAttachment() const + { + return layoutAttachment != layoutAttachmentEnd; + } + TLayoutFormat getFormat() const { return layoutFormat; } + bool isPushConstant() const { return layoutPushConstant; } + bool isShaderRecord() const { return layoutShaderRecord; } + bool hasBufferReference() const { return layoutBufferReference; } + bool hasBufferReferenceAlign() const + { + return layoutBufferReferenceAlign != layoutBufferReferenceAlignEnd; + } + bool isNonUniform() const + { + return nonUniform; + } +#endif + bool hasSpecConstantId() const + { + // Not the same thing as being a specialization constant, this + // is just whether or not it was declared with an ID. + return layoutSpecConstantId != layoutSpecConstantIdEnd; + } + bool isSpecConstant() const + { + // True if type is a specialization constant, whether or not it + // had a specialization-constant ID, and false if it is not a + // true front-end constant. + return specConstant; + } + bool isFrontEndConstant() const + { + // True if the front-end knows the final constant value. + // This allows front-end constant folding. + return storage == EvqConst && ! specConstant; + } + bool isConstant() const + { + // True if is either kind of constant; specialization or regular. + return isFrontEndConstant() || isSpecConstant(); + } + void makeSpecConstant() + { + storage = EvqConst; + specConstant = true; + } + static const char* getLayoutPackingString(TLayoutPacking packing) + { + switch (packing) { + case ElpStd140: return "std140"; +#ifndef GLSLANG_WEB + case ElpPacked: return "packed"; + case ElpShared: return "shared"; + case ElpStd430: return "std430"; + case ElpScalar: return "scalar"; +#endif + default: return "none"; + } + } + static const char* getLayoutMatrixString(TLayoutMatrix m) + { + switch (m) { + case ElmColumnMajor: return "column_major"; + case ElmRowMajor: return "row_major"; + default: return "none"; + } + } +#ifdef GLSLANG_WEB + static const char* getLayoutFormatString(TLayoutFormat f) { return "none"; } +#else + static const char* getLayoutFormatString(TLayoutFormat f) + { + switch (f) { + case ElfRgba32f: return "rgba32f"; + case ElfRgba16f: return "rgba16f"; + case ElfRg32f: return "rg32f"; + case ElfRg16f: return "rg16f"; + case ElfR11fG11fB10f: return "r11f_g11f_b10f"; + case ElfR32f: return "r32f"; + case ElfR16f: return "r16f"; + case ElfRgba16: return "rgba16"; + case ElfRgb10A2: return "rgb10_a2"; + case ElfRgba8: return "rgba8"; + case ElfRg16: return "rg16"; + case ElfRg8: return "rg8"; + case ElfR16: return "r16"; + case ElfR8: return "r8"; + case ElfRgba16Snorm: return "rgba16_snorm"; + case ElfRgba8Snorm: return "rgba8_snorm"; + case ElfRg16Snorm: return "rg16_snorm"; + case ElfRg8Snorm: return "rg8_snorm"; + case ElfR16Snorm: return "r16_snorm"; + case ElfR8Snorm: return "r8_snorm"; + + case ElfRgba32i: return "rgba32i"; + case ElfRgba16i: return "rgba16i"; + case ElfRgba8i: return "rgba8i"; + case ElfRg32i: return "rg32i"; + case ElfRg16i: return "rg16i"; + case ElfRg8i: return "rg8i"; + case ElfR32i: return "r32i"; + case ElfR16i: return "r16i"; + case ElfR8i: return "r8i"; + + case ElfRgba32ui: return "rgba32ui"; + case ElfRgba16ui: return "rgba16ui"; + case ElfRgba8ui: return "rgba8ui"; + case ElfRg32ui: return "rg32ui"; + case ElfRg16ui: return "rg16ui"; + case ElfRgb10a2ui: return "rgb10_a2ui"; + case ElfRg8ui: return "rg8ui"; + case ElfR32ui: return "r32ui"; + case ElfR16ui: return "r16ui"; + case ElfR8ui: return "r8ui"; + default: return "none"; + } + } + static const char* getLayoutDepthString(TLayoutDepth d) + { + switch (d) { + case EldAny: return "depth_any"; + case EldGreater: return "depth_greater"; + case EldLess: return "depth_less"; + case EldUnchanged: return "depth_unchanged"; + default: return "none"; + } + } + static const char* getBlendEquationString(TBlendEquationShift e) + { + switch (e) { + case EBlendMultiply: return "blend_support_multiply"; + case EBlendScreen: return "blend_support_screen"; + case EBlendOverlay: return "blend_support_overlay"; + case EBlendDarken: return "blend_support_darken"; + case EBlendLighten: return "blend_support_lighten"; + case EBlendColordodge: return "blend_support_colordodge"; + case EBlendColorburn: return "blend_support_colorburn"; + case EBlendHardlight: return "blend_support_hardlight"; + case EBlendSoftlight: return "blend_support_softlight"; + case EBlendDifference: return "blend_support_difference"; + case EBlendExclusion: return "blend_support_exclusion"; + case EBlendHslHue: return "blend_support_hsl_hue"; + case EBlendHslSaturation: return "blend_support_hsl_saturation"; + case EBlendHslColor: return "blend_support_hsl_color"; + case EBlendHslLuminosity: return "blend_support_hsl_luminosity"; + case EBlendAllEquations: return "blend_support_all_equations"; + default: return "unknown"; + } + } + static const char* getGeometryString(TLayoutGeometry geometry) + { + switch (geometry) { + case ElgPoints: return "points"; + case ElgLines: return "lines"; + case ElgLinesAdjacency: return "lines_adjacency"; + case ElgLineStrip: return "line_strip"; + case ElgTriangles: return "triangles"; + case ElgTrianglesAdjacency: return "triangles_adjacency"; + case ElgTriangleStrip: return "triangle_strip"; + case ElgQuads: return "quads"; + case ElgIsolines: return "isolines"; + default: return "none"; + } + } + static const char* getVertexSpacingString(TVertexSpacing spacing) + { + switch (spacing) { + case EvsEqual: return "equal_spacing"; + case EvsFractionalEven: return "fractional_even_spacing"; + case EvsFractionalOdd: return "fractional_odd_spacing"; + default: return "none"; + } + } + static const char* getVertexOrderString(TVertexOrder order) + { + switch (order) { + case EvoCw: return "cw"; + case EvoCcw: return "ccw"; + default: return "none"; + } + } + static int mapGeometryToSize(TLayoutGeometry geometry) + { + switch (geometry) { + case ElgPoints: return 1; + case ElgLines: return 2; + case ElgLinesAdjacency: return 4; + case ElgTriangles: return 3; + case ElgTrianglesAdjacency: return 6; + default: return 0; + } + } + static const char* getInterlockOrderingString(TInterlockOrdering order) + { + switch (order) { + case EioPixelInterlockOrdered: return "pixel_interlock_ordered"; + case EioPixelInterlockUnordered: return "pixel_interlock_unordered"; + case EioSampleInterlockOrdered: return "sample_interlock_ordered"; + case EioSampleInterlockUnordered: return "sample_interlock_unordered"; + case EioShadingRateInterlockOrdered: return "shading_rate_interlock_ordered"; + case EioShadingRateInterlockUnordered: return "shading_rate_interlock_unordered"; + default: return "none"; + } + } +#endif +}; + +// Qualifiers that don't need to be keep per object. They have shader scope, not object scope. +// So, they will not be part of TType, TQualifier, etc. +struct TShaderQualifiers { + TLayoutGeometry geometry; // geometry/tessellation shader in/out primitives + bool pixelCenterInteger; // fragment shader + bool originUpperLeft; // fragment shader + int invocations; + int vertices; // for tessellation "vertices", geometry & mesh "max_vertices" + TVertexSpacing spacing; + TVertexOrder order; + bool pointMode; + int localSize[3]; // compute shader + bool localSizeNotDefault[3]; // compute shader + int localSizeSpecId[3]; // compute shader specialization id for gl_WorkGroupSize +#ifndef GLSLANG_WEB + bool earlyFragmentTests; // fragment input + bool postDepthCoverage; // fragment input + TLayoutDepth layoutDepth; + bool blendEquation; // true if any blend equation was specified + int numViews; // multiview extenstions + TInterlockOrdering interlockOrdering; + bool layoutOverrideCoverage; // true if layout override_coverage set + bool layoutDerivativeGroupQuads; // true if layout derivative_group_quadsNV set + bool layoutDerivativeGroupLinear; // true if layout derivative_group_linearNV set + int primitives; // mesh shader "max_primitives"DerivativeGroupLinear; // true if layout derivative_group_linearNV set + TLayoutDepth getDepth() const { return layoutDepth; } +#else + TLayoutDepth getDepth() const { return EldNone; } +#endif + + void init() + { + geometry = ElgNone; + originUpperLeft = false; + pixelCenterInteger = false; + invocations = TQualifier::layoutNotSet; + vertices = TQualifier::layoutNotSet; + spacing = EvsNone; + order = EvoNone; + pointMode = false; + localSize[0] = 1; + localSize[1] = 1; + localSize[2] = 1; + localSizeNotDefault[0] = false; + localSizeNotDefault[1] = false; + localSizeNotDefault[2] = false; + localSizeSpecId[0] = TQualifier::layoutNotSet; + localSizeSpecId[1] = TQualifier::layoutNotSet; + localSizeSpecId[2] = TQualifier::layoutNotSet; +#ifndef GLSLANG_WEB + earlyFragmentTests = false; + postDepthCoverage = false; + layoutDepth = EldNone; + blendEquation = false; + numViews = TQualifier::layoutNotSet; + layoutOverrideCoverage = false; + layoutDerivativeGroupQuads = false; + layoutDerivativeGroupLinear = false; + primitives = TQualifier::layoutNotSet; + interlockOrdering = EioNone; +#endif + } + +#ifdef GLSLANG_WEB + bool hasBlendEquation() const { return false; } +#else + bool hasBlendEquation() const { return blendEquation; } +#endif + + // Merge in characteristics from the 'src' qualifier. They can override when + // set, but never erase when not set. + void merge(const TShaderQualifiers& src) + { + if (src.geometry != ElgNone) + geometry = src.geometry; + if (src.pixelCenterInteger) + pixelCenterInteger = src.pixelCenterInteger; + if (src.originUpperLeft) + originUpperLeft = src.originUpperLeft; + if (src.invocations != TQualifier::layoutNotSet) + invocations = src.invocations; + if (src.vertices != TQualifier::layoutNotSet) + vertices = src.vertices; + if (src.spacing != EvsNone) + spacing = src.spacing; + if (src.order != EvoNone) + order = src.order; + if (src.pointMode) + pointMode = true; + for (int i = 0; i < 3; ++i) { + if (src.localSize[i] > 1) + localSize[i] = src.localSize[i]; + } + for (int i = 0; i < 3; ++i) { + localSizeNotDefault[i] = src.localSizeNotDefault[i] || localSizeNotDefault[i]; + } + for (int i = 0; i < 3; ++i) { + if (src.localSizeSpecId[i] != TQualifier::layoutNotSet) + localSizeSpecId[i] = src.localSizeSpecId[i]; + } +#ifndef GLSLANG_WEB + if (src.earlyFragmentTests) + earlyFragmentTests = true; + if (src.postDepthCoverage) + postDepthCoverage = true; + if (src.layoutDepth) + layoutDepth = src.layoutDepth; + if (src.blendEquation) + blendEquation = src.blendEquation; + if (src.numViews != TQualifier::layoutNotSet) + numViews = src.numViews; + if (src.layoutOverrideCoverage) + layoutOverrideCoverage = src.layoutOverrideCoverage; + if (src.layoutDerivativeGroupQuads) + layoutDerivativeGroupQuads = src.layoutDerivativeGroupQuads; + if (src.layoutDerivativeGroupLinear) + layoutDerivativeGroupLinear = src.layoutDerivativeGroupLinear; + if (src.primitives != TQualifier::layoutNotSet) + primitives = src.primitives; + if (src.interlockOrdering != EioNone) + interlockOrdering = src.interlockOrdering; +#endif + } +}; + +// +// TPublicType is just temporarily used while parsing and not quite the same +// information kept per node in TType. Due to the bison stack, it can't have +// types that it thinks have non-trivial constructors. It should +// just be used while recognizing the grammar, not anything else. +// Once enough is known about the situation, the proper information +// moved into a TType, or the parse context, etc. +// +class TPublicType { +public: + TBasicType basicType; + TSampler sampler; + TQualifier qualifier; + TShaderQualifiers shaderQualifiers; + int vectorSize : 4; + int matrixCols : 4; + int matrixRows : 4; + bool coopmat : 1; + TArraySizes* arraySizes; + const TType* userDef; + TSourceLoc loc; + TArraySizes* typeParameters; + +#ifdef GLSLANG_WEB + bool isCoopmat() const { return false; } +#else + bool isCoopmat() const { return coopmat; } +#endif + + void initType(const TSourceLoc& l) + { + basicType = EbtVoid; + vectorSize = 1; + matrixRows = 0; + matrixCols = 0; + arraySizes = nullptr; + userDef = nullptr; + loc = l; + typeParameters = nullptr; + coopmat = false; + } + + void initQualifiers(bool global = false) + { + qualifier.clear(); + if (global) + qualifier.storage = EvqGlobal; + } + + void init(const TSourceLoc& l, bool global = false) + { + initType(l); + sampler.clear(); + initQualifiers(global); + shaderQualifiers.init(); + } + + void setVector(int s) + { + matrixRows = 0; + matrixCols = 0; + vectorSize = s; + } + + void setMatrix(int c, int r) + { + matrixRows = r; + matrixCols = c; + vectorSize = 0; + } + + bool isScalar() const + { + return matrixCols == 0 && vectorSize == 1 && arraySizes == nullptr && userDef == nullptr; + } + + // "Image" is a superset of "Subpass" + bool isImage() const { return basicType == EbtSampler && sampler.isImage(); } + bool isSubpass() const { return basicType == EbtSampler && sampler.isSubpass(); } +}; + +// +// Base class for things that have a type. +// +class TType { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + // for "empty" type (no args) or simple scalar/vector/matrix + explicit TType(TBasicType t = EbtVoid, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0, + bool isVector = false) : + basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1), coopmat(false), + arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr) + { + sampler.clear(); + qualifier.clear(); + qualifier.storage = q; + assert(!(isMatrix() && vectorSize != 0)); // prevent vectorSize != 0 on matrices + } + // for explicit precision qualifier + TType(TBasicType t, TStorageQualifier q, TPrecisionQualifier p, int vs = 1, int mc = 0, int mr = 0, + bool isVector = false) : + basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1), coopmat(false), + arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr) + { + sampler.clear(); + qualifier.clear(); + qualifier.storage = q; + qualifier.precision = p; + assert(p >= EpqNone && p <= EpqHigh); + assert(!(isMatrix() && vectorSize != 0)); // prevent vectorSize != 0 on matrices + } + // for turning a TPublicType into a TType, using a shallow copy + explicit TType(const TPublicType& p) : + basicType(p.basicType), + vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), vector1(false), coopmat(p.coopmat), + arraySizes(p.arraySizes), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(p.typeParameters) + { + if (basicType == EbtSampler) + sampler = p.sampler; + else + sampler.clear(); + qualifier = p.qualifier; + if (p.userDef) { + if (p.userDef->basicType == EbtReference) { + basicType = EbtReference; + referentType = p.userDef->referentType; + } else { + structure = p.userDef->getWritableStruct(); // public type is short-lived; there are no sharing issues + } + typeName = NewPoolTString(p.userDef->getTypeName().c_str()); + } + if (p.isCoopmat() && p.typeParameters && p.typeParameters->getNumDims() > 0) { + int numBits = p.typeParameters->getDimSize(0); + if (p.basicType == EbtFloat && numBits == 16) { + basicType = EbtFloat16; + qualifier.precision = EpqNone; + } else if (p.basicType == EbtUint && numBits == 8) { + basicType = EbtUint8; + qualifier.precision = EpqNone; + } else if (p.basicType == EbtInt && numBits == 8) { + basicType = EbtInt8; + qualifier.precision = EpqNone; + } + } + } + // for construction of sampler types + TType(const TSampler& sampler, TStorageQualifier q = EvqUniform, TArraySizes* as = nullptr) : + basicType(EbtSampler), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false), + arraySizes(as), structure(nullptr), fieldName(nullptr), typeName(nullptr), + sampler(sampler), typeParameters(nullptr) + { + qualifier.clear(); + qualifier.storage = q; + } + // to efficiently make a dereferenced type + // without ever duplicating the outer structure that will be thrown away + // and using only shallow copy + TType(const TType& type, int derefIndex, bool rowMajor = false) + { + if (type.isArray()) { + shallowCopy(type); + if (type.getArraySizes()->getNumDims() == 1) { + arraySizes = nullptr; + } else { + // want our own copy of the array, so we can edit it + arraySizes = new TArraySizes; + arraySizes->copyDereferenced(*type.arraySizes); + } + } else if (type.basicType == EbtStruct || type.basicType == EbtBlock) { + // do a structure dereference + const TTypeList& memberList = *type.getStruct(); + shallowCopy(*memberList[derefIndex].type); + return; + } else { + // do a vector/matrix dereference + shallowCopy(type); + if (matrixCols > 0) { + // dereference from matrix to vector + if (rowMajor) + vectorSize = matrixCols; + else + vectorSize = matrixRows; + matrixCols = 0; + matrixRows = 0; + if (vectorSize == 1) + vector1 = true; + } else if (isVector()) { + // dereference from vector to scalar + vectorSize = 1; + vector1 = false; + } else if (isCoopMat()) { + coopmat = false; + typeParameters = nullptr; + } + } + } + // for making structures, ... + TType(TTypeList* userDef, const TString& n) : + basicType(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false), + arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr) + { + sampler.clear(); + qualifier.clear(); + typeName = NewPoolTString(n.c_str()); + } + // For interface blocks + TType(TTypeList* userDef, const TString& n, const TQualifier& q) : + basicType(EbtBlock), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false), + qualifier(q), arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr) + { + sampler.clear(); + typeName = NewPoolTString(n.c_str()); + } + // for block reference (first parameter must be EbtReference) + explicit TType(TBasicType t, const TType &p, const TString& n) : + basicType(t), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), + arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr) + { + assert(t == EbtReference); + typeName = NewPoolTString(n.c_str()); + qualifier.clear(); + qualifier.storage = p.qualifier.storage; + referentType = p.clone(); + } + virtual ~TType() {} + + // Not for use across pool pops; it will cause multiple instances of TType to point to the same information. + // This only works if that information (like a structure's list of types) does not change and + // the instances are sharing the same pool. + void shallowCopy(const TType& copyOf) + { + basicType = copyOf.basicType; + sampler = copyOf.sampler; + qualifier = copyOf.qualifier; + vectorSize = copyOf.vectorSize; + matrixCols = copyOf.matrixCols; + matrixRows = copyOf.matrixRows; + vector1 = copyOf.vector1; + arraySizes = copyOf.arraySizes; // copying the pointer only, not the contents + fieldName = copyOf.fieldName; + typeName = copyOf.typeName; + if (isStruct()) { + structure = copyOf.structure; + } else { + referentType = copyOf.referentType; + } + typeParameters = copyOf.typeParameters; + coopmat = copyOf.isCoopMat(); + } + + // Make complete copy of the whole type graph rooted at 'copyOf'. + void deepCopy(const TType& copyOf) + { + TMap copied; // to enable copying a type graph as a graph, not a tree + deepCopy(copyOf, copied); + } + + // Recursively make temporary + void makeTemporary() + { + getQualifier().makeTemporary(); + + if (isStruct()) + for (unsigned int i = 0; i < structure->size(); ++i) + (*structure)[i].type->makeTemporary(); + } + + TType* clone() const + { + TType *newType = new TType(); + newType->deepCopy(*this); + + return newType; + } + + void makeVector() { vector1 = true; } + + virtual void hideMember() { basicType = EbtVoid; vectorSize = 1; } + virtual bool hiddenMember() const { return basicType == EbtVoid; } + + virtual void setFieldName(const TString& n) { fieldName = NewPoolTString(n.c_str()); } + virtual const TString& getTypeName() const + { + assert(typeName); + return *typeName; + } + + virtual const TString& getFieldName() const + { + assert(fieldName); + return *fieldName; + } + TShaderInterface getShaderInterface() const + { + if (basicType != EbtBlock) + return EsiNone; + + switch (qualifier.storage) { + default: + return EsiNone; + case EvqVaryingIn: + return EsiInput; + case EvqVaryingOut: + return EsiOutput; + case EvqUniform: + case EvqBuffer: + return EsiUniform; + } + } + + virtual TBasicType getBasicType() const { return basicType; } + virtual const TSampler& getSampler() const { return sampler; } + virtual TSampler& getSampler() { return sampler; } + + virtual TQualifier& getQualifier() { return qualifier; } + virtual const TQualifier& getQualifier() const { return qualifier; } + + virtual int getVectorSize() const { return vectorSize; } // returns 1 for either scalar or vector of size 1, valid for both + virtual int getMatrixCols() const { return matrixCols; } + virtual int getMatrixRows() const { return matrixRows; } + virtual int getOuterArraySize() const { return arraySizes->getOuterSize(); } + virtual TIntermTyped* getOuterArrayNode() const { return arraySizes->getOuterNode(); } + virtual int getCumulativeArraySize() const { return arraySizes->getCumulativeSize(); } +#ifdef GLSLANG_WEB + bool isArrayOfArrays() const { return false; } +#else + bool isArrayOfArrays() const { return arraySizes != nullptr && arraySizes->getNumDims() > 1; } +#endif + virtual int getImplicitArraySize() const { return arraySizes->getImplicitSize(); } + virtual const TArraySizes* getArraySizes() const { return arraySizes; } + virtual TArraySizes* getArraySizes() { return arraySizes; } + virtual TType* getReferentType() const { return referentType; } + virtual const TArraySizes* getTypeParameters() const { return typeParameters; } + virtual TArraySizes* getTypeParameters() { return typeParameters; } + + virtual bool isScalar() const { return ! isVector() && ! isMatrix() && ! isStruct() && ! isArray(); } + virtual bool isScalarOrVec1() const { return isScalar() || vector1; } + virtual bool isVector() const { return vectorSize > 1 || vector1; } + virtual bool isMatrix() const { return matrixCols ? true : false; } + virtual bool isArray() const { return arraySizes != nullptr; } + virtual bool isSizedArray() const { return isArray() && arraySizes->isSized(); } + virtual bool isUnsizedArray() const { return isArray() && !arraySizes->isSized(); } + virtual bool isArrayVariablyIndexed() const { assert(isArray()); return arraySizes->isVariablyIndexed(); } + virtual void setArrayVariablyIndexed() { assert(isArray()); arraySizes->setVariablyIndexed(); } + virtual void updateImplicitArraySize(int size) { assert(isArray()); arraySizes->updateImplicitSize(size); } + virtual bool isStruct() const { return basicType == EbtStruct || basicType == EbtBlock; } + virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble || basicType == EbtFloat16; } + virtual bool isIntegerDomain() const + { + switch (basicType) { + case EbtInt8: + case EbtUint8: + case EbtInt16: + case EbtUint16: + case EbtInt: + case EbtUint: + case EbtInt64: + case EbtUint64: + case EbtAtomicUint: + return true; + default: + break; + } + return false; + } + virtual bool isOpaque() const { return basicType == EbtSampler +#ifndef GLSLANG_WEB + || basicType == EbtAtomicUint || basicType == EbtAccStruct || basicType == EbtRayQuery +#endif + ; } + virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; } + + // "Image" is a superset of "Subpass" + virtual bool isImage() const { return basicType == EbtSampler && getSampler().isImage(); } + virtual bool isSubpass() const { return basicType == EbtSampler && getSampler().isSubpass(); } + virtual bool isTexture() const { return basicType == EbtSampler && getSampler().isTexture(); } + // Check the block-name convention of creating a block without populating it's members: + virtual bool isUnusableName() const { return isStruct() && structure == nullptr; } + virtual bool isParameterized() const { return typeParameters != nullptr; } +#ifdef GLSLANG_WEB + bool isAtomic() const { return false; } + bool isCoopMat() const { return false; } + bool isReference() const { return false; } +#else + bool isAtomic() const { return basicType == EbtAtomicUint; } + bool isCoopMat() const { return coopmat; } + bool isReference() const { return getBasicType() == EbtReference; } +#endif + + // return true if this type contains any subtype which satisfies the given predicate. + template + bool contains(P predicate) const + { + if (predicate(this)) + return true; + + const auto hasa = [predicate](const TTypeLoc& tl) { return tl.type->contains(predicate); }; + + return isStruct() && std::any_of(structure->begin(), structure->end(), hasa); + } + + // Recursively checks if the type contains the given basic type + virtual bool containsBasicType(TBasicType checkType) const + { + return contains([checkType](const TType* t) { return t->basicType == checkType; } ); + } + + // Recursively check the structure for any arrays, needed for some error checks + virtual bool containsArray() const + { + return contains([](const TType* t) { return t->isArray(); } ); + } + + // Check the structure for any structures, needed for some error checks + virtual bool containsStructure() const + { + return contains([this](const TType* t) { return t != this && t->isStruct(); } ); + } + + // Recursively check the structure for any unsized arrays, needed for triggering a copyUp(). + virtual bool containsUnsizedArray() const + { + return contains([](const TType* t) { return t->isUnsizedArray(); } ); + } + + virtual bool containsOpaque() const + { + return contains([](const TType* t) { return t->isOpaque(); } ); + } + + // Recursively checks if the type contains a built-in variable + virtual bool containsBuiltIn() const + { + return contains([](const TType* t) { return t->isBuiltIn(); } ); + } + + virtual bool containsNonOpaque() const + { + const auto nonOpaque = [](const TType* t) { + switch (t->basicType) { + case EbtVoid: + case EbtFloat: + case EbtDouble: + case EbtFloat16: + case EbtInt8: + case EbtUint8: + case EbtInt16: + case EbtUint16: + case EbtInt: + case EbtUint: + case EbtInt64: + case EbtUint64: + case EbtBool: + case EbtReference: + return true; + default: + return false; + } + }; + + return contains(nonOpaque); + } + + virtual bool containsSpecializationSize() const + { + return contains([](const TType* t) { return t->isArray() && t->arraySizes->isOuterSpecialization(); } ); + } + +#ifdef GLSLANG_WEB + bool containsDouble() const { return false; } + bool contains16BitFloat() const { return false; } + bool contains64BitInt() const { return false; } + bool contains16BitInt() const { return false; } + bool contains8BitInt() const { return false; } + bool containsCoopMat() const { return false; } + bool containsReference() const { return false; } +#else + bool containsDouble() const + { + return containsBasicType(EbtDouble); + } + bool contains16BitFloat() const + { + return containsBasicType(EbtFloat16); + } + bool contains64BitInt() const + { + return containsBasicType(EbtInt64) || containsBasicType(EbtUint64); + } + bool contains16BitInt() const + { + return containsBasicType(EbtInt16) || containsBasicType(EbtUint16); + } + bool contains8BitInt() const + { + return containsBasicType(EbtInt8) || containsBasicType(EbtUint8); + } + bool containsCoopMat() const + { + return contains([](const TType* t) { return t->coopmat; } ); + } + bool containsReference() const + { + return containsBasicType(EbtReference); + } +#endif + + // Array editing methods. Array descriptors can be shared across + // type instances. This allows all uses of the same array + // to be updated at once. E.g., all nodes can be explicitly sized + // by tracking and correcting one implicit size. Or, all nodes + // can get the explicit size on a redeclaration that gives size. + // + // N.B.: Don't share with the shared symbol tables (symbols are + // marked as isReadOnly(). Such symbols with arrays that will be + // edited need to copyUp() on first use, so that + // A) the edits don't effect the shared symbol table, and + // B) the edits are shared across all users. + void updateArraySizes(const TType& type) + { + // For when we may already be sharing existing array descriptors, + // keeping the pointers the same, just updating the contents. + assert(arraySizes != nullptr); + assert(type.arraySizes != nullptr); + *arraySizes = *type.arraySizes; + } + void copyArraySizes(const TArraySizes& s) + { + // For setting a fresh new set of array sizes, not yet worrying about sharing. + arraySizes = new TArraySizes; + *arraySizes = s; + } + void transferArraySizes(TArraySizes* s) + { + // For setting an already allocated set of sizes that this type can use + // (no copy made). + arraySizes = s; + } + void clearArraySizes() + { + arraySizes = nullptr; + } + + // Add inner array sizes, to any existing sizes, via copy; the + // sizes passed in can still be reused for other purposes. + void copyArrayInnerSizes(const TArraySizes* s) + { + if (s != nullptr) { + if (arraySizes == nullptr) + copyArraySizes(*s); + else + arraySizes->addInnerSizes(*s); + } + } + void changeOuterArraySize(int s) { arraySizes->changeOuterSize(s); } + + // Recursively make the implicit array size the explicit array size. + // Expicit arrays are compile-time or link-time sized, never run-time sized. + // Sometimes, policy calls for an array to be run-time sized even if it was + // never variably indexed: Don't turn a 'skipNonvariablyIndexed' array into + // an explicit array. + void adoptImplicitArraySizes(bool skipNonvariablyIndexed) + { + if (isUnsizedArray() && !(skipNonvariablyIndexed || isArrayVariablyIndexed())) + changeOuterArraySize(getImplicitArraySize()); + // For multi-dim per-view arrays, set unsized inner dimension size to 1 + if (qualifier.isPerView() && arraySizes && arraySizes->isInnerUnsized()) + arraySizes->clearInnerUnsized(); + if (isStruct() && structure->size() > 0) { + int lastMember = (int)structure->size() - 1; + for (int i = 0; i < lastMember; ++i) + (*structure)[i].type->adoptImplicitArraySizes(false); + // implement the "last member of an SSBO" policy + (*structure)[lastMember].type->adoptImplicitArraySizes(getQualifier().storage == EvqBuffer); + } + } + + + void updateTypeParameters(const TType& type) + { + // For when we may already be sharing existing array descriptors, + // keeping the pointers the same, just updating the contents. + assert(typeParameters != nullptr); + assert(type.typeParameters != nullptr); + *typeParameters = *type.typeParameters; + } + void copyTypeParameters(const TArraySizes& s) + { + // For setting a fresh new set of type parameters, not yet worrying about sharing. + typeParameters = new TArraySizes; + *typeParameters = s; + } + void transferTypeParameters(TArraySizes* s) + { + // For setting an already allocated set of sizes that this type can use + // (no copy made). + typeParameters = s; + } + void clearTypeParameters() + { + typeParameters = nullptr; + } + + // Add inner array sizes, to any existing sizes, via copy; the + // sizes passed in can still be reused for other purposes. + void copyTypeParametersInnerSizes(const TArraySizes* s) + { + if (s != nullptr) { + if (typeParameters == nullptr) + copyTypeParameters(*s); + else + typeParameters->addInnerSizes(*s); + } + } + + + + const char* getBasicString() const + { + return TType::getBasicString(basicType); + } + + static const char* getBasicString(TBasicType t) + { + switch (t) { + case EbtFloat: return "float"; + case EbtInt: return "int"; + case EbtUint: return "uint"; + case EbtSampler: return "sampler/image"; +#ifndef GLSLANG_WEB + case EbtVoid: return "void"; + case EbtDouble: return "double"; + case EbtFloat16: return "float16_t"; + case EbtInt8: return "int8_t"; + case EbtUint8: return "uint8_t"; + case EbtInt16: return "int16_t"; + case EbtUint16: return "uint16_t"; + case EbtInt64: return "int64_t"; + case EbtUint64: return "uint64_t"; + case EbtBool: return "bool"; + case EbtAtomicUint: return "atomic_uint"; + case EbtStruct: return "structure"; + case EbtBlock: return "block"; + case EbtAccStruct: return "accelerationStructureNV"; + case EbtRayQuery: return "rayQueryEXT"; + case EbtReference: return "reference"; +#endif + default: return "unknown type"; + } + } + +#ifdef GLSLANG_WEB + TString getCompleteString() const { return ""; } + const char* getStorageQualifierString() const { return ""; } + const char* getBuiltInVariableString() const { return ""; } + const char* getPrecisionQualifierString() const { return ""; } + TString getBasicTypeString() const { return ""; } +#else + TString getCompleteString() const + { + TString typeString; + + const auto appendStr = [&](const char* s) { typeString.append(s); }; + const auto appendUint = [&](unsigned int u) { typeString.append(std::to_string(u).c_str()); }; + const auto appendInt = [&](int i) { typeString.append(std::to_string(i).c_str()); }; + + if (qualifier.hasLayout()) { + // To reduce noise, skip this if the only layout is an xfb_buffer + // with no triggering xfb_offset. + TQualifier noXfbBuffer = qualifier; + noXfbBuffer.layoutXfbBuffer = TQualifier::layoutXfbBufferEnd; + if (noXfbBuffer.hasLayout()) { + appendStr("layout("); + if (qualifier.hasAnyLocation()) { + appendStr(" location="); + appendUint(qualifier.layoutLocation); + if (qualifier.hasComponent()) { + appendStr(" component="); + appendUint(qualifier.layoutComponent); + } + if (qualifier.hasIndex()) { + appendStr(" index="); + appendUint(qualifier.layoutIndex); + } + } + if (qualifier.hasSet()) { + appendStr(" set="); + appendUint(qualifier.layoutSet); + } + if (qualifier.hasBinding()) { + appendStr(" binding="); + appendUint(qualifier.layoutBinding); + } + if (qualifier.hasStream()) { + appendStr(" stream="); + appendUint(qualifier.layoutStream); + } + if (qualifier.hasMatrix()) { + appendStr(" "); + appendStr(TQualifier::getLayoutMatrixString(qualifier.layoutMatrix)); + } + if (qualifier.hasPacking()) { + appendStr(" "); + appendStr(TQualifier::getLayoutPackingString(qualifier.layoutPacking)); + } + if (qualifier.hasOffset()) { + appendStr(" offset="); + appendInt(qualifier.layoutOffset); + } + if (qualifier.hasAlign()) { + appendStr(" align="); + appendInt(qualifier.layoutAlign); + } + if (qualifier.hasFormat()) { + appendStr(" "); + appendStr(TQualifier::getLayoutFormatString(qualifier.layoutFormat)); + } + if (qualifier.hasXfbBuffer() && qualifier.hasXfbOffset()) { + appendStr(" xfb_buffer="); + appendUint(qualifier.layoutXfbBuffer); + } + if (qualifier.hasXfbOffset()) { + appendStr(" xfb_offset="); + appendUint(qualifier.layoutXfbOffset); + } + if (qualifier.hasXfbStride()) { + appendStr(" xfb_stride="); + appendUint(qualifier.layoutXfbStride); + } + if (qualifier.hasAttachment()) { + appendStr(" input_attachment_index="); + appendUint(qualifier.layoutAttachment); + } + if (qualifier.hasSpecConstantId()) { + appendStr(" constant_id="); + appendUint(qualifier.layoutSpecConstantId); + } + if (qualifier.layoutPushConstant) + appendStr(" push_constant"); + if (qualifier.layoutBufferReference) + appendStr(" buffer_reference"); + if (qualifier.hasBufferReferenceAlign()) { + appendStr(" buffer_reference_align="); + appendUint(1u << qualifier.layoutBufferReferenceAlign); + } + + if (qualifier.layoutPassthrough) + appendStr(" passthrough"); + if (qualifier.layoutViewportRelative) + appendStr(" layoutViewportRelative"); + if (qualifier.layoutSecondaryViewportRelativeOffset != -2048) { + appendStr(" layoutSecondaryViewportRelativeOffset="); + appendInt(qualifier.layoutSecondaryViewportRelativeOffset); + } + if (qualifier.layoutShaderRecord) + appendStr(" shaderRecordNV"); + + appendStr(")"); + } + } + + if (qualifier.invariant) + appendStr(" invariant"); + if (qualifier.noContraction) + appendStr(" noContraction"); + if (qualifier.centroid) + appendStr(" centroid"); + if (qualifier.smooth) + appendStr(" smooth"); + if (qualifier.flat) + appendStr(" flat"); + if (qualifier.nopersp) + appendStr(" noperspective"); + if (qualifier.explicitInterp) + appendStr(" __explicitInterpAMD"); + if (qualifier.pervertexNV) + appendStr(" pervertexNV"); + if (qualifier.perPrimitiveNV) + appendStr(" perprimitiveNV"); + if (qualifier.perViewNV) + appendStr(" perviewNV"); + if (qualifier.perTaskNV) + appendStr(" taskNV"); + if (qualifier.patch) + appendStr(" patch"); + if (qualifier.sample) + appendStr(" sample"); + if (qualifier.coherent) + appendStr(" coherent"); + if (qualifier.devicecoherent) + appendStr(" devicecoherent"); + if (qualifier.queuefamilycoherent) + appendStr(" queuefamilycoherent"); + if (qualifier.workgroupcoherent) + appendStr(" workgroupcoherent"); + if (qualifier.subgroupcoherent) + appendStr(" subgroupcoherent"); + if (qualifier.shadercallcoherent) + appendStr(" shadercallcoherent"); + if (qualifier.nonprivate) + appendStr(" nonprivate"); + if (qualifier.volatil) + appendStr(" volatile"); + if (qualifier.restrict) + appendStr(" restrict"); + if (qualifier.readonly) + appendStr(" readonly"); + if (qualifier.writeonly) + appendStr(" writeonly"); + if (qualifier.specConstant) + appendStr(" specialization-constant"); + if (qualifier.nonUniform) + appendStr(" nonuniform"); + appendStr(" "); + appendStr(getStorageQualifierString()); + if (isArray()) { + for(int i = 0; i < (int)arraySizes->getNumDims(); ++i) { + int size = arraySizes->getDimSize(i); + if (size == UnsizedArraySize && i == 0 && arraySizes->isVariablyIndexed()) + appendStr(" runtime-sized array of"); + else { + if (size == UnsizedArraySize) { + appendStr(" unsized"); + if (i == 0) { + appendStr(" "); + appendInt(arraySizes->getImplicitSize()); + } + } else { + appendStr(" "); + appendInt(arraySizes->getDimSize(i)); + } + appendStr("-element array of"); + } + } + } + if (isParameterized()) { + appendStr("<"); + for(int i = 0; i < (int)typeParameters->getNumDims(); ++i) { + appendInt(typeParameters->getDimSize(i)); + if (i != (int)typeParameters->getNumDims() - 1) + appendStr(", "); + } + appendStr(">"); + } + if (qualifier.precision != EpqNone) { + appendStr(" "); + appendStr(getPrecisionQualifierString()); + } + if (isMatrix()) { + appendStr(" "); + appendInt(matrixCols); + appendStr("X"); + appendInt(matrixRows); + appendStr(" matrix of"); + } else if (isVector()) { + appendStr(" "); + appendInt(vectorSize); + appendStr("-component vector of"); + } + + appendStr(" "); + typeString.append(getBasicTypeString()); + + if (qualifier.builtIn != EbvNone) { + appendStr(" "); + appendStr(getBuiltInVariableString()); + } + + // Add struct/block members + if (isStruct() && structure) { + appendStr("{"); + bool hasHiddenMember = true; + for (size_t i = 0; i < structure->size(); ++i) { + if (! (*structure)[i].type->hiddenMember()) { + if (!hasHiddenMember) + appendStr(", "); + typeString.append((*structure)[i].type->getCompleteString()); + typeString.append(" "); + typeString.append((*structure)[i].type->getFieldName()); + hasHiddenMember = false; + } + } + appendStr("}"); + } + + return typeString; + } + + TString getBasicTypeString() const + { + if (basicType == EbtSampler) + return sampler.getString(); + else + return getBasicString(); + } + + const char* getStorageQualifierString() const { return GetStorageQualifierString(qualifier.storage); } + const char* getBuiltInVariableString() const { return GetBuiltInVariableString(qualifier.builtIn); } + const char* getPrecisionQualifierString() const { return GetPrecisionQualifierString(qualifier.precision); } +#endif + + const TTypeList* getStruct() const { assert(isStruct()); return structure; } + void setStruct(TTypeList* s) { assert(isStruct()); structure = s; } + TTypeList* getWritableStruct() const { assert(isStruct()); return structure; } // This should only be used when known to not be sharing with other threads + void setBasicType(const TBasicType& t) { basicType = t; } + + int computeNumComponents() const + { + int components = 0; + + if (getBasicType() == EbtStruct || getBasicType() == EbtBlock) { + for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++) + components += ((*tl).type)->computeNumComponents(); + } else if (matrixCols) + components = matrixCols * matrixRows; + else + components = vectorSize; + + if (arraySizes != nullptr) { + components *= arraySizes->getCumulativeSize(); + } + + return components; + } + + // append this type's mangled name to the passed in 'name' + void appendMangledName(TString& name) const + { + buildMangledName(name); + name += ';' ; + } + + // Do two structure types match? They could be declared independently, + // in different places, but still might satisfy the definition of matching. + // From the spec: + // + // "Structures must have the same name, sequence of type names, and + // type definitions, and member names to be considered the same type. + // This rule applies recursively for nested or embedded types." + // + bool sameStructType(const TType& right) const + { + // Most commonly, they are both nullptr, or the same pointer to the same actual structure + if ((!isStruct() && !right.isStruct()) || + (isStruct() && right.isStruct() && structure == right.structure)) + return true; + + // Both being nullptr was caught above, now they both have to be structures of the same number of elements + if (!isStruct() || !right.isStruct() || + structure->size() != right.structure->size()) + return false; + + // Structure names have to match + if (*typeName != *right.typeName) + return false; + + // Compare the names and types of all the members, which have to match + for (unsigned int i = 0; i < structure->size(); ++i) { + if ((*structure)[i].type->getFieldName() != (*right.structure)[i].type->getFieldName()) + return false; + + if (*(*structure)[i].type != *(*right.structure)[i].type) + return false; + } + + return true; + } + + bool sameReferenceType(const TType& right) const + { + if (isReference() != right.isReference()) + return false; + + if (!isReference() && !right.isReference()) + return true; + + assert(referentType != nullptr); + assert(right.referentType != nullptr); + + if (referentType == right.referentType) + return true; + + return *referentType == *right.referentType; + } + + // See if two types match, in all aspects except arrayness + bool sameElementType(const TType& right) const + { + return basicType == right.basicType && sameElementShape(right); + } + + // See if two type's arrayness match + bool sameArrayness(const TType& right) const + { + return ((arraySizes == nullptr && right.arraySizes == nullptr) || + (arraySizes != nullptr && right.arraySizes != nullptr && *arraySizes == *right.arraySizes)); + } + + // See if two type's arrayness match in everything except their outer dimension + bool sameInnerArrayness(const TType& right) const + { + assert(arraySizes != nullptr && right.arraySizes != nullptr); + return arraySizes->sameInnerArrayness(*right.arraySizes); + } + + // See if two type's parameters match + bool sameTypeParameters(const TType& right) const + { + return ((typeParameters == nullptr && right.typeParameters == nullptr) || + (typeParameters != nullptr && right.typeParameters != nullptr && *typeParameters == *right.typeParameters)); + } + + // See if two type's elements match in all ways except basic type + bool sameElementShape(const TType& right) const + { + return sampler == right.sampler && + vectorSize == right.vectorSize && + matrixCols == right.matrixCols && + matrixRows == right.matrixRows && + vector1 == right.vector1 && + isCoopMat() == right.isCoopMat() && + sameStructType(right) && + sameReferenceType(right); + } + + // See if a cooperative matrix type parameter with unspecified parameters is + // an OK function parameter + bool coopMatParameterOK(const TType& right) const + { + return isCoopMat() && right.isCoopMat() && (getBasicType() == right.getBasicType()) && + typeParameters == nullptr && right.typeParameters != nullptr; + } + + bool sameCoopMatBaseType(const TType &right) const { + bool rv = coopmat && right.coopmat; + if (getBasicType() == EbtFloat || getBasicType() == EbtFloat16) + rv = right.getBasicType() == EbtFloat || right.getBasicType() == EbtFloat16; + else if (getBasicType() == EbtUint || getBasicType() == EbtUint8) + rv = right.getBasicType() == EbtUint || right.getBasicType() == EbtUint8; + else if (getBasicType() == EbtInt || getBasicType() == EbtInt8) + rv = right.getBasicType() == EbtInt || right.getBasicType() == EbtInt8; + else + rv = false; + return rv; + } + + + // See if two types match in all ways (just the actual type, not qualification) + bool operator==(const TType& right) const + { + return sameElementType(right) && sameArrayness(right) && sameTypeParameters(right); + } + + bool operator!=(const TType& right) const + { + return ! operator==(right); + } + + unsigned int getBufferReferenceAlignment() const + { +#ifndef GLSLANG_WEB + if (getBasicType() == glslang::EbtReference) { + return getReferentType()->getQualifier().hasBufferReferenceAlign() ? + (1u << getReferentType()->getQualifier().layoutBufferReferenceAlign) : 16u; + } +#endif + return 0; + } + +protected: + // Require consumer to pick between deep copy and shallow copy. + TType(const TType& type); + TType& operator=(const TType& type); + + // Recursively copy a type graph, while preserving the graph-like + // quality. That is, don't make more than one copy of a structure that + // gets reused multiple times in the type graph. + void deepCopy(const TType& copyOf, TMap& copiedMap) + { + shallowCopy(copyOf); + + if (copyOf.arraySizes) { + arraySizes = new TArraySizes; + *arraySizes = *copyOf.arraySizes; + } + + if (copyOf.typeParameters) { + typeParameters = new TArraySizes; + *typeParameters = *copyOf.typeParameters; + } + + if (copyOf.isStruct() && copyOf.structure) { + auto prevCopy = copiedMap.find(copyOf.structure); + if (prevCopy != copiedMap.end()) + structure = prevCopy->second; + else { + structure = new TTypeList; + copiedMap[copyOf.structure] = structure; + for (unsigned int i = 0; i < copyOf.structure->size(); ++i) { + TTypeLoc typeLoc; + typeLoc.loc = (*copyOf.structure)[i].loc; + typeLoc.type = new TType(); + typeLoc.type->deepCopy(*(*copyOf.structure)[i].type, copiedMap); + structure->push_back(typeLoc); + } + } + } + + if (copyOf.fieldName) + fieldName = NewPoolTString(copyOf.fieldName->c_str()); + if (copyOf.typeName) + typeName = NewPoolTString(copyOf.typeName->c_str()); + } + + + void buildMangledName(TString&) const; + + TBasicType basicType : 8; + int vectorSize : 4; // 1 means either scalar or 1-component vector; see vector1 to disambiguate. + int matrixCols : 4; + int matrixRows : 4; + bool vector1 : 1; // Backward-compatible tracking of a 1-component vector distinguished from a scalar. + // GLSL 4.5 never has a 1-component vector; so this will always be false until such + // functionality is added. + // HLSL does have a 1-component vectors, so this will be true to disambiguate + // from a scalar. + bool coopmat : 1; + TQualifier qualifier; + + TArraySizes* arraySizes; // nullptr unless an array; can be shared across types + // A type can't be both a structure (EbtStruct/EbtBlock) and a reference (EbtReference), so + // conserve space by making these a union + union { + TTypeList* structure; // invalid unless this is a struct; can be shared across types + TType *referentType; // invalid unless this is an EbtReference + }; + TString *fieldName; // for structure field names + TString *typeName; // for structure type name + TSampler sampler; + TArraySizes* typeParameters;// nullptr unless a parameterized type; can be shared across types +}; + +} // end namespace glslang + +#endif // _TYPES_INCLUDED_ diff --git a/mac/include/glslang/Include/arrays.h b/mac/include/glslang/Include/arrays.h new file mode 100644 index 00000000..7f047d9f --- /dev/null +++ b/mac/include/glslang/Include/arrays.h @@ -0,0 +1,341 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +// +// Implement types for tracking GLSL arrays, arrays of arrays, etc. +// + +#ifndef _ARRAYS_INCLUDED +#define _ARRAYS_INCLUDED + +#include + +namespace glslang { + +// This is used to mean there is no size yet (unsized), it is waiting to get a size from somewhere else. +const int UnsizedArraySize = 0; + +class TIntermTyped; +extern bool SameSpecializationConstants(TIntermTyped*, TIntermTyped*); + +// Specialization constants need both a nominal size and a node that defines +// the specialization constant being used. Array types are the same when their +// size and specialization constant nodes are the same. +struct TArraySize { + unsigned int size; + TIntermTyped* node; // nullptr means no specialization constant node + bool operator==(const TArraySize& rhs) const + { + if (size != rhs.size) + return false; + if (node == nullptr || rhs.node == nullptr) + return node == rhs.node; + + return SameSpecializationConstants(node, rhs.node); + } +}; + +// +// TSmallArrayVector is used as the container for the set of sizes in TArraySizes. +// It has generic-container semantics, while TArraySizes has array-of-array semantics. +// That is, TSmallArrayVector should be more focused on mechanism and TArraySizes on policy. +// +struct TSmallArrayVector { + // + // TODO: memory: TSmallArrayVector is intended to be smaller. + // Almost all arrays could be handled by two sizes each fitting + // in 16 bits, needing a real vector only in the cases where there + // are more than 3 sizes or a size needing more than 16 bits. + // + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + TSmallArrayVector() : sizes(nullptr) { } + virtual ~TSmallArrayVector() { dealloc(); } + + // For breaking into two non-shared copies, independently modifiable. + TSmallArrayVector& operator=(const TSmallArrayVector& from) + { + if (from.sizes == nullptr) + sizes = nullptr; + else { + alloc(); + *sizes = *from.sizes; + } + + return *this; + } + + int size() const + { + if (sizes == nullptr) + return 0; + return (int)sizes->size(); + } + + unsigned int frontSize() const + { + assert(sizes != nullptr && sizes->size() > 0); + return sizes->front().size; + } + + TIntermTyped* frontNode() const + { + assert(sizes != nullptr && sizes->size() > 0); + return sizes->front().node; + } + + void changeFront(unsigned int s) + { + assert(sizes != nullptr); + // this should only happen for implicitly sized arrays, not specialization constants + assert(sizes->front().node == nullptr); + sizes->front().size = s; + } + + void push_back(unsigned int e, TIntermTyped* n) + { + alloc(); + TArraySize pair = { e, n }; + sizes->push_back(pair); + } + + void push_back(const TSmallArrayVector& newDims) + { + alloc(); + sizes->insert(sizes->end(), newDims.sizes->begin(), newDims.sizes->end()); + } + + void pop_front() + { + assert(sizes != nullptr && sizes->size() > 0); + if (sizes->size() == 1) + dealloc(); + else + sizes->erase(sizes->begin()); + } + + // 'this' should currently not be holding anything, and copyNonFront + // will make it hold a copy of all but the first element of rhs. + // (This would be useful for making a type that is dereferenced by + // one dimension.) + void copyNonFront(const TSmallArrayVector& rhs) + { + assert(sizes == nullptr); + if (rhs.size() > 1) { + alloc(); + sizes->insert(sizes->begin(), rhs.sizes->begin() + 1, rhs.sizes->end()); + } + } + + unsigned int getDimSize(int i) const + { + assert(sizes != nullptr && (int)sizes->size() > i); + return (*sizes)[i].size; + } + + void setDimSize(int i, unsigned int size) const + { + assert(sizes != nullptr && (int)sizes->size() > i); + assert((*sizes)[i].node == nullptr); + (*sizes)[i].size = size; + } + + TIntermTyped* getDimNode(int i) const + { + assert(sizes != nullptr && (int)sizes->size() > i); + return (*sizes)[i].node; + } + + bool operator==(const TSmallArrayVector& rhs) const + { + if (sizes == nullptr && rhs.sizes == nullptr) + return true; + if (sizes == nullptr || rhs.sizes == nullptr) + return false; + return *sizes == *rhs.sizes; + } + bool operator!=(const TSmallArrayVector& rhs) const { return ! operator==(rhs); } + +protected: + TSmallArrayVector(const TSmallArrayVector&); + + void alloc() + { + if (sizes == nullptr) + sizes = new TVector; + } + void dealloc() + { + delete sizes; + sizes = nullptr; + } + + TVector* sizes; // will either hold such a pointer, or in the future, hold the two array sizes +}; + +// +// Represent an array, or array of arrays, to arbitrary depth. This is not +// done through a hierarchy of types in a type tree, rather all contiguous arrayness +// in the type hierarchy is localized into this single cumulative object. +// +// The arrayness in TTtype is a pointer, so that it can be non-allocated and zero +// for the vast majority of types that are non-array types. +// +// Order Policy: these are all identical: +// - left to right order within a contiguous set of ...[..][..][..]... in the source language +// - index order 0, 1, 2, ... within the 'sizes' member below +// - outer-most to inner-most +// +struct TArraySizes { + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + TArraySizes() : implicitArraySize(1), variablyIndexed(false) { } + + // For breaking into two non-shared copies, independently modifiable. + TArraySizes& operator=(const TArraySizes& from) + { + implicitArraySize = from.implicitArraySize; + variablyIndexed = from.variablyIndexed; + sizes = from.sizes; + + return *this; + } + + // translate from array-of-array semantics to container semantics + int getNumDims() const { return sizes.size(); } + int getDimSize(int dim) const { return sizes.getDimSize(dim); } + TIntermTyped* getDimNode(int dim) const { return sizes.getDimNode(dim); } + void setDimSize(int dim, int size) { sizes.setDimSize(dim, size); } + int getOuterSize() const { return sizes.frontSize(); } + TIntermTyped* getOuterNode() const { return sizes.frontNode(); } + int getCumulativeSize() const + { + int size = 1; + for (int d = 0; d < sizes.size(); ++d) { + // this only makes sense in paths that have a known array size + assert(sizes.getDimSize(d) != UnsizedArraySize); + size *= sizes.getDimSize(d); + } + return size; + } + void addInnerSize() { addInnerSize((unsigned)UnsizedArraySize); } + void addInnerSize(int s) { addInnerSize((unsigned)s, nullptr); } + void addInnerSize(int s, TIntermTyped* n) { sizes.push_back((unsigned)s, n); } + void addInnerSize(TArraySize pair) { + sizes.push_back(pair.size, pair.node); + } + void addInnerSizes(const TArraySizes& s) { sizes.push_back(s.sizes); } + void changeOuterSize(int s) { sizes.changeFront((unsigned)s); } + int getImplicitSize() const { return implicitArraySize; } + void updateImplicitSize(int s) { implicitArraySize = std::max(implicitArraySize, s); } + bool isInnerUnsized() const + { + for (int d = 1; d < sizes.size(); ++d) { + if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize) + return true; + } + + return false; + } + bool clearInnerUnsized() + { + for (int d = 1; d < sizes.size(); ++d) { + if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize) + setDimSize(d, 1); + } + + return false; + } + bool isInnerSpecialization() const + { + for (int d = 1; d < sizes.size(); ++d) { + if (sizes.getDimNode(d) != nullptr) + return true; + } + + return false; + } + bool isOuterSpecialization() + { + return sizes.getDimNode(0) != nullptr; + } + + bool hasUnsized() const { return getOuterSize() == UnsizedArraySize || isInnerUnsized(); } + bool isSized() const { return getOuterSize() != UnsizedArraySize; } + void dereference() { sizes.pop_front(); } + void copyDereferenced(const TArraySizes& rhs) + { + assert(sizes.size() == 0); + if (rhs.sizes.size() > 1) + sizes.copyNonFront(rhs.sizes); + } + + bool sameInnerArrayness(const TArraySizes& rhs) const + { + if (sizes.size() != rhs.sizes.size()) + return false; + + for (int d = 1; d < sizes.size(); ++d) { + if (sizes.getDimSize(d) != rhs.sizes.getDimSize(d) || + sizes.getDimNode(d) != rhs.sizes.getDimNode(d)) + return false; + } + + return true; + } + + void setVariablyIndexed() { variablyIndexed = true; } + bool isVariablyIndexed() const { return variablyIndexed; } + + bool operator==(const TArraySizes& rhs) const { return sizes == rhs.sizes; } + bool operator!=(const TArraySizes& rhs) const { return sizes != rhs.sizes; } + +protected: + TSmallArrayVector sizes; + + TArraySizes(const TArraySizes&); + + // For tracking maximum referenced compile-time constant index. + // Applies only to the outer-most dimension. Potentially becomes + // the implicit size of the array, if not variably indexed and + // otherwise legal. + int implicitArraySize; + bool variablyIndexed; // true if array is indexed with a non compile-time constant +}; + +} // end namespace glslang + +#endif // _ARRAYS_INCLUDED_ diff --git a/mac/include/glslang/Include/glslang_c_interface.h b/mac/include/glslang/Include/glslang_c_interface.h new file mode 100644 index 00000000..5a450e0e --- /dev/null +++ b/mac/include/glslang/Include/glslang_c_interface.h @@ -0,0 +1,232 @@ +/** + This code is based on the glslang_c_interface implementation by Viktor Latypov +**/ + +/** +BSD 2-Clause License + +Copyright (c) 2019, Viktor Latypov +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**/ + +#ifndef GLSLANG_C_IFACE_H_INCLUDED +#define GLSLANG_C_IFACE_H_INCLUDED + +#include +#include + +#include "glslang_c_shader_types.h" + +typedef struct glslang_shader_s glslang_shader_t; +typedef struct glslang_program_s glslang_program_t; + +/* TLimits counterpart */ +typedef struct glslang_limits_s { + bool non_inductive_for_loops; + bool while_loops; + bool do_while_loops; + bool general_uniform_indexing; + bool general_attribute_matrix_vector_indexing; + bool general_varying_indexing; + bool general_sampler_indexing; + bool general_variable_indexing; + bool general_constant_matrix_vector_indexing; +} glslang_limits_t; + +/* TBuiltInResource counterpart */ +typedef struct glslang_resource_s { + int max_lights; + int max_clip_planes; + int max_texture_units; + int max_texture_coords; + int max_vertex_attribs; + int max_vertex_uniform_components; + int max_varying_floats; + int max_vertex_texture_image_units; + int max_combined_texture_image_units; + int max_texture_image_units; + int max_fragment_uniform_components; + int max_draw_buffers; + int max_vertex_uniform_vectors; + int max_varying_vectors; + int max_fragment_uniform_vectors; + int max_vertex_output_vectors; + int max_fragment_input_vectors; + int min_program_texel_offset; + int max_program_texel_offset; + int max_clip_distances; + int max_compute_work_group_count_x; + int max_compute_work_group_count_y; + int max_compute_work_group_count_z; + int max_compute_work_group_size_x; + int max_compute_work_group_size_y; + int max_compute_work_group_size_z; + int max_compute_uniform_components; + int max_compute_texture_image_units; + int max_compute_image_uniforms; + int max_compute_atomic_counters; + int max_compute_atomic_counter_buffers; + int max_varying_components; + int max_vertex_output_components; + int max_geometry_input_components; + int max_geometry_output_components; + int max_fragment_input_components; + int max_image_units; + int max_combined_image_units_and_fragment_outputs; + int max_combined_shader_output_resources; + int max_image_samples; + int max_vertex_image_uniforms; + int max_tess_control_image_uniforms; + int max_tess_evaluation_image_uniforms; + int max_geometry_image_uniforms; + int max_fragment_image_uniforms; + int max_combined_image_uniforms; + int max_geometry_texture_image_units; + int max_geometry_output_vertices; + int max_geometry_total_output_components; + int max_geometry_uniform_components; + int max_geometry_varying_components; + int max_tess_control_input_components; + int max_tess_control_output_components; + int max_tess_control_texture_image_units; + int max_tess_control_uniform_components; + int max_tess_control_total_output_components; + int max_tess_evaluation_input_components; + int max_tess_evaluation_output_components; + int max_tess_evaluation_texture_image_units; + int max_tess_evaluation_uniform_components; + int max_tess_patch_components; + int max_patch_vertices; + int max_tess_gen_level; + int max_viewports; + int max_vertex_atomic_counters; + int max_tess_control_atomic_counters; + int max_tess_evaluation_atomic_counters; + int max_geometry_atomic_counters; + int max_fragment_atomic_counters; + int max_combined_atomic_counters; + int max_atomic_counter_bindings; + int max_vertex_atomic_counter_buffers; + int max_tess_control_atomic_counter_buffers; + int max_tess_evaluation_atomic_counter_buffers; + int max_geometry_atomic_counter_buffers; + int max_fragment_atomic_counter_buffers; + int max_combined_atomic_counter_buffers; + int max_atomic_counter_buffer_size; + int max_transform_feedback_buffers; + int max_transform_feedback_interleaved_components; + int max_cull_distances; + int max_combined_clip_and_cull_distances; + int max_samples; + int max_mesh_output_vertices_nv; + int max_mesh_output_primitives_nv; + int max_mesh_work_group_size_x_nv; + int max_mesh_work_group_size_y_nv; + int max_mesh_work_group_size_z_nv; + int max_task_work_group_size_x_nv; + int max_task_work_group_size_y_nv; + int max_task_work_group_size_z_nv; + int max_mesh_view_count_nv; + + glslang_limits_t limits; +} glslang_resource_t; + +typedef struct glslang_input_s { + glslang_source_t language; + glslang_stage_t stage; + glslang_client_t client; + glslang_target_client_version_t client_version; + glslang_target_language_t target_language; + glslang_target_language_version_t target_language_version; + /** Shader source code */ + const char* code; + int default_version; + glslang_profile_t default_profile; + int force_default_version_and_profile; + int forward_compatible; + glslang_messages_t messages; + const glslang_resource_t* resource; +} glslang_input_t; + +/* Inclusion result structure allocated by C include_local/include_system callbacks */ +typedef struct glsl_include_result_s { + /* Header file name or NULL if inclusion failed */ + const char* header_name; + + /* Header contents or NULL */ + const char* header_data; + size_t header_length; + +} glsl_include_result_t; + +/* Callback for local file inclusion */ +typedef glsl_include_result_t* (*glsl_include_local_func)(void* ctx, const char* header_name, const char* includer_name, + size_t include_depth); + +/* Callback for system file inclusion */ +typedef glsl_include_result_t* (*glsl_include_system_func)(void* ctx, const char* header_name, + const char* includer_name, size_t include_depth); + +/* Callback for include result destruction */ +typedef int (*glsl_free_include_result_func)(void* ctx, glsl_include_result_t* result); + +/* Collection of callbacks for GLSL preprocessor */ +typedef struct glsl_include_callbacks_s { + glsl_include_system_func include_system; + glsl_include_local_func include_local; + glsl_free_include_result_func free_include_result; +} glsl_include_callbacks_t; + +#ifdef __cplusplus +extern "C" { +#endif + +int glslang_initialize_process(); +void glslang_finalize_process(); + +glslang_shader_t* glslang_shader_create(const glslang_input_t* input); +void glslang_shader_delete(glslang_shader_t* shader); +int glslang_shader_preprocess(glslang_shader_t* shader, const glslang_input_t* input); +int glslang_shader_parse(glslang_shader_t* shader, const glslang_input_t* input); +const char* glslang_shader_get_preprocessed_code(glslang_shader_t* shader); +const char* glslang_shader_get_info_log(glslang_shader_t* shader); +const char* glslang_shader_get_info_debug_log(glslang_shader_t* shader); + +glslang_program_t* glslang_program_create(); +void glslang_program_delete(glslang_program_t* program); +void glslang_program_add_shader(glslang_program_t* program, glslang_shader_t* shader); +int glslang_program_link(glslang_program_t* program, int messages); // glslang_messages_t +void glslang_program_SPIRV_generate(glslang_program_t* program, glslang_stage_t stage); +size_t glslang_program_SPIRV_get_size(glslang_program_t* program); +void glslang_program_SPIRV_get(glslang_program_t* program, unsigned int*); +unsigned int* glslang_program_SPIRV_get_ptr(glslang_program_t* program); +const char* glslang_program_SPIRV_get_messages(glslang_program_t* program); +const char* glslang_program_get_info_log(glslang_program_t* program); +const char* glslang_program_get_info_debug_log(glslang_program_t* program); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifdef GLSLANG_C_IFACE_INCLUDED */ diff --git a/mac/include/glslang/Include/glslang_c_shader_types.h b/mac/include/glslang/Include/glslang_c_shader_types.h new file mode 100644 index 00000000..769f4c4a --- /dev/null +++ b/mac/include/glslang/Include/glslang_c_shader_types.h @@ -0,0 +1,182 @@ +/** + This code is based on the glslang_c_interface implementation by Viktor Latypov +**/ + +/** +BSD 2-Clause License + +Copyright (c) 2019, Viktor Latypov +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**/ + +#ifndef C_SHADER_TYPES_H_INCLUDED +#define C_SHADER_TYPES_H_INCLUDED + +#define LAST_ELEMENT_MARKER(x) x + +/* EShLanguage counterpart */ +typedef enum { + GLSLANG_STAGE_VERTEX, + GLSLANG_STAGE_TESSCONTROL, + GLSLANG_STAGE_TESSEVALUATION, + GLSLANG_STAGE_GEOMETRY, + GLSLANG_STAGE_FRAGMENT, + GLSLANG_STAGE_COMPUTE, + GLSLANG_STAGE_RAYGEN_NV, + GLSLANG_STAGE_INTERSECT_NV, + GLSLANG_STAGE_ANYHIT_NV, + GLSLANG_STAGE_CLOSESTHIT_NV, + GLSLANG_STAGE_MISS_NV, + GLSLANG_STAGE_CALLABLE_NV, + GLSLANG_STAGE_TASK_NV, + GLSLANG_STAGE_MESH_NV, + LAST_ELEMENT_MARKER(GLSLANG_STAGE_COUNT), +} glslang_stage_t; // would be better as stage, but this is ancient now + +/* EShLanguageMask counterpart */ +typedef enum { + GLSLANG_STAGE_VERTEX_MASK = (1 << GLSLANG_STAGE_VERTEX), + GLSLANG_STAGE_TESSCONTROL_MASK = (1 << GLSLANG_STAGE_TESSCONTROL), + GLSLANG_STAGE_TESSEVALUATION_MASK = (1 << GLSLANG_STAGE_TESSEVALUATION), + GLSLANG_STAGE_GEOMETRY_MASK = (1 << GLSLANG_STAGE_GEOMETRY), + GLSLANG_STAGE_FRAGMENT_MASK = (1 << GLSLANG_STAGE_FRAGMENT), + GLSLANG_STAGE_COMPUTE_MASK = (1 << GLSLANG_STAGE_COMPUTE), + GLSLANG_STAGE_RAYGEN_NV_MASK = (1 << GLSLANG_STAGE_RAYGEN_NV), + GLSLANG_STAGE_INTERSECT_NV_MASK = (1 << GLSLANG_STAGE_INTERSECT_NV), + GLSLANG_STAGE_ANYHIT_NV_MASK = (1 << GLSLANG_STAGE_ANYHIT_NV), + GLSLANG_STAGE_CLOSESTHIT_NV_MASK = (1 << GLSLANG_STAGE_CLOSESTHIT_NV), + GLSLANG_STAGE_MISS_NV_MASK = (1 << GLSLANG_STAGE_MISS_NV), + GLSLANG_STAGE_CALLABLE_NV_MASK = (1 << GLSLANG_STAGE_CALLABLE_NV), + GLSLANG_STAGE_TASK_NV_MASK = (1 << GLSLANG_STAGE_TASK_NV), + GLSLANG_STAGE_MESH_NV_MASK = (1 << GLSLANG_STAGE_MESH_NV), + LAST_ELEMENT_MARKER(GLSLANG_STAGE_MASK_COUNT), +} glslang_stage_mask_t; + +/* EShSource counterpart */ +typedef enum { + GLSLANG_SOURCE_NONE, + GLSLANG_SOURCE_GLSL, + GLSLANG_SOURCE_HLSL, + LAST_ELEMENT_MARKER(GLSLANG_SOURCE_COUNT), +} glslang_source_t; + +/* EShClient counterpart */ +typedef enum { + GLSLANG_CLIENT_NONE, + GLSLANG_CLIENT_VULKAN, + GLSLANG_CLIENT_OPENGL, + LAST_ELEMENT_MARKER(GLSLANG_CLIENT_COUNT), +} glslang_client_t; + +/* EShTargetLanguage counterpart */ +typedef enum { + GLSLANG_TARGET_NONE, + GLSLANG_TARGET_SPV, + LAST_ELEMENT_MARKER(GLSLANG_TARGET_COUNT), +} glslang_target_language_t; + +/* SH_TARGET_ClientVersion counterpart */ +typedef enum { + GLSLANG_TARGET_VULKAN_1_0 = (1 << 22), + GLSLANG_TARGET_VULKAN_1_1 = (1 << 22) | (1 << 12), + GLSLANG_TARGET_OPENGL_450 = 450, + LAST_ELEMENT_MARKER(GLSLANG_TARGET_CLIENT_VERSION_COUNT), +} glslang_target_client_version_t; + +/* SH_TARGET_LanguageVersion counterpart */ +typedef enum { + GLSLANG_TARGET_SPV_1_0 = (1 << 16), + GLSLANG_TARGET_SPV_1_1 = (1 << 16) | (1 << 8), + GLSLANG_TARGET_SPV_1_2 = (1 << 16) | (2 << 8), + GLSLANG_TARGET_SPV_1_3 = (1 << 16) | (3 << 8), + GLSLANG_TARGET_SPV_1_4 = (1 << 16) | (4 << 8), + GLSLANG_TARGET_SPV_1_5 = (1 << 16) | (5 << 8), + LAST_ELEMENT_MARKER(GLSLANG_TARGET_LANGUAGE_VERSION_COUNT), +} glslang_target_language_version_t; + +/* EShExecutable counterpart */ +typedef enum { GLSLANG_EX_VERTEX_FRAGMENT, GLSLANG_EX_FRAGMENT } glslang_executable_t; + +/* EShOptimizationLevel counterpart */ +typedef enum { + GLSLANG_OPT_NO_GENERATION, + GLSLANG_OPT_NONE, + GLSLANG_OPT_SIMPLE, + GLSLANG_OPT_FULL, + LAST_ELEMENT_MARKER(GLSLANG_OPT_LEVEL_COUNT), +} glslang_optimization_level_t; + +/* EShTextureSamplerTransformMode counterpart */ +typedef enum { + GLSLANG_TEX_SAMP_TRANS_KEEP, + GLSLANG_TEX_SAMP_TRANS_UPGRADE_TEXTURE_REMOVE_SAMPLER, + LAST_ELEMENT_MARKER(GLSLANG_TEX_SAMP_TRANS_COUNT), +} glslang_texture_sampler_transform_mode_t; + +/* EShMessages counterpart */ +typedef enum { + GLSLANG_MSG_DEFAULT_BIT = 0, + GLSLANG_MSG_RELAXED_ERRORS_BIT = (1 << 0), + GLSLANG_MSG_SUPPRESS_WARNINGS_BIT = (1 << 1), + GLSLANG_MSG_AST_BIT = (1 << 2), + GLSLANG_MSG_SPV_RULES_BIT = (1 << 3), + GLSLANG_MSG_VULKAN_RULES_BIT = (1 << 4), + GLSLANG_MSG_ONLY_PREPROCESSOR_BIT = (1 << 5), + GLSLANG_MSG_READ_HLSL_BIT = (1 << 6), + GLSLANG_MSG_CASCADING_ERRORS_BIT = (1 << 7), + GLSLANG_MSG_KEEP_UNCALLED_BIT = (1 << 8), + GLSLANG_MSG_HLSL_OFFSETS_BIT = (1 << 9), + GLSLANG_MSG_DEBUG_INFO_BIT = (1 << 10), + GLSLANG_MSG_HLSL_ENABLE_16BIT_TYPES_BIT = (1 << 11), + GLSLANG_MSG_HLSL_LEGALIZATION_BIT = (1 << 12), + GLSLANG_MSG_HLSL_DX9_COMPATIBLE_BIT = (1 << 13), + GLSLANG_MSG_BUILTIN_SYMBOL_TABLE_BIT = (1 << 14), + LAST_ELEMENT_MARKER(GLSLANG_MSG_COUNT), +} glslang_messages_t; + +/* EShReflectionOptions counterpart */ +typedef enum { + GLSLANG_REFLECTION_DEFAULT_BIT = 0, + GLSLANG_REFLECTION_STRICT_ARRAY_SUFFIX_BIT = (1 << 0), + GLSLANG_REFLECTION_BASIC_ARRAY_SUFFIX_BIT = (1 << 1), + GLSLANG_REFLECTION_INTERMEDIATE_IOO_BIT = (1 << 2), + GLSLANG_REFLECTION_SEPARATE_BUFFERS_BIT = (1 << 3), + GLSLANG_REFLECTION_ALL_BLOCK_VARIABLES_BIT = (1 << 4), + GLSLANG_REFLECTION_UNWRAP_IO_BLOCKS_BIT = (1 << 5), + LAST_ELEMENT_MARKER(GLSLANG_REFLECTION_COUNT), +} glslang_reflection_options_t; + +/* EProfile counterpart (from Versions.h) */ +typedef enum { + GLSLANG_BAD_PROFILE = 0, + GLSLANG_NO_PROFILE = (1 << 0), + GLSLANG_CORE_PROFILE = (1 << 1), + GLSLANG_COMPATIBILITY_PROFILE = (1 << 2), + GLSLANG_ES_PROFILE = (1 << 3), + LAST_ELEMENT_MARKER(GLSLANG_PROFILE_COUNT), +} glslang_profile_t; + +#undef LAST_ELEMENT_MARKER + +#endif diff --git a/mac/include/glslang/Include/intermediate.h b/mac/include/glslang/Include/intermediate.h new file mode 100644 index 00000000..bf12fcf8 --- /dev/null +++ b/mac/include/glslang/Include/intermediate.h @@ -0,0 +1,1805 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2016 LunarG, Inc. +// Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +// +// Definition of the in-memory high-level intermediate representation +// of shaders. This is a tree that parser creates. +// +// Nodes in the tree are defined as a hierarchy of classes derived from +// TIntermNode. Each is a node in a tree. There is no preset branching factor; +// each node can have it's own type of list of children. +// + +#ifndef __INTERMEDIATE_H +#define __INTERMEDIATE_H + +#if defined(_MSC_VER) && _MSC_VER >= 1900 + #pragma warning(disable : 4464) // relative include path contains '..' + #pragma warning(disable : 5026) // 'glslang::TIntermUnary': move constructor was implicitly defined as deleted +#endif + +#include "../Include/Common.h" +#include "../Include/Types.h" +#include "../Include/ConstantUnion.h" + +namespace glslang { + +class TIntermediate; + +// +// Operators used by the high-level (parse tree) representation. +// +enum TOperator { + EOpNull, // if in a node, should only mean a node is still being built + EOpSequence, // denotes a list of statements, or parameters, etc. + EOpLinkerObjects, // for aggregate node of objects the linker may need, if not reference by the rest of the AST + EOpFunctionCall, + EOpFunction, // For function definition + EOpParameters, // an aggregate listing the parameters to a function + + // + // Unary operators + // + + EOpNegative, + EOpLogicalNot, + EOpVectorLogicalNot, + EOpBitwiseNot, + + EOpPostIncrement, + EOpPostDecrement, + EOpPreIncrement, + EOpPreDecrement, + + EOpCopyObject, + + // (u)int* -> bool + EOpConvInt8ToBool, + EOpConvUint8ToBool, + EOpConvInt16ToBool, + EOpConvUint16ToBool, + EOpConvIntToBool, + EOpConvUintToBool, + EOpConvInt64ToBool, + EOpConvUint64ToBool, + + // float* -> bool + EOpConvFloat16ToBool, + EOpConvFloatToBool, + EOpConvDoubleToBool, + + // bool -> (u)int* + EOpConvBoolToInt8, + EOpConvBoolToUint8, + EOpConvBoolToInt16, + EOpConvBoolToUint16, + EOpConvBoolToInt, + EOpConvBoolToUint, + EOpConvBoolToInt64, + EOpConvBoolToUint64, + + // bool -> float* + EOpConvBoolToFloat16, + EOpConvBoolToFloat, + EOpConvBoolToDouble, + + // int8_t -> (u)int* + EOpConvInt8ToInt16, + EOpConvInt8ToInt, + EOpConvInt8ToInt64, + EOpConvInt8ToUint8, + EOpConvInt8ToUint16, + EOpConvInt8ToUint, + EOpConvInt8ToUint64, + + // uint8_t -> (u)int* + EOpConvUint8ToInt8, + EOpConvUint8ToInt16, + EOpConvUint8ToInt, + EOpConvUint8ToInt64, + EOpConvUint8ToUint16, + EOpConvUint8ToUint, + EOpConvUint8ToUint64, + + // int8_t -> float* + EOpConvInt8ToFloat16, + EOpConvInt8ToFloat, + EOpConvInt8ToDouble, + + // uint8_t -> float* + EOpConvUint8ToFloat16, + EOpConvUint8ToFloat, + EOpConvUint8ToDouble, + + // int16_t -> (u)int* + EOpConvInt16ToInt8, + EOpConvInt16ToInt, + EOpConvInt16ToInt64, + EOpConvInt16ToUint8, + EOpConvInt16ToUint16, + EOpConvInt16ToUint, + EOpConvInt16ToUint64, + + // uint16_t -> (u)int* + EOpConvUint16ToInt8, + EOpConvUint16ToInt16, + EOpConvUint16ToInt, + EOpConvUint16ToInt64, + EOpConvUint16ToUint8, + EOpConvUint16ToUint, + EOpConvUint16ToUint64, + + // int16_t -> float* + EOpConvInt16ToFloat16, + EOpConvInt16ToFloat, + EOpConvInt16ToDouble, + + // uint16_t -> float* + EOpConvUint16ToFloat16, + EOpConvUint16ToFloat, + EOpConvUint16ToDouble, + + // int32_t -> (u)int* + EOpConvIntToInt8, + EOpConvIntToInt16, + EOpConvIntToInt64, + EOpConvIntToUint8, + EOpConvIntToUint16, + EOpConvIntToUint, + EOpConvIntToUint64, + + // uint32_t -> (u)int* + EOpConvUintToInt8, + EOpConvUintToInt16, + EOpConvUintToInt, + EOpConvUintToInt64, + EOpConvUintToUint8, + EOpConvUintToUint16, + EOpConvUintToUint64, + + // int32_t -> float* + EOpConvIntToFloat16, + EOpConvIntToFloat, + EOpConvIntToDouble, + + // uint32_t -> float* + EOpConvUintToFloat16, + EOpConvUintToFloat, + EOpConvUintToDouble, + + // int64_t -> (u)int* + EOpConvInt64ToInt8, + EOpConvInt64ToInt16, + EOpConvInt64ToInt, + EOpConvInt64ToUint8, + EOpConvInt64ToUint16, + EOpConvInt64ToUint, + EOpConvInt64ToUint64, + + // uint64_t -> (u)int* + EOpConvUint64ToInt8, + EOpConvUint64ToInt16, + EOpConvUint64ToInt, + EOpConvUint64ToInt64, + EOpConvUint64ToUint8, + EOpConvUint64ToUint16, + EOpConvUint64ToUint, + + // int64_t -> float* + EOpConvInt64ToFloat16, + EOpConvInt64ToFloat, + EOpConvInt64ToDouble, + + // uint64_t -> float* + EOpConvUint64ToFloat16, + EOpConvUint64ToFloat, + EOpConvUint64ToDouble, + + // float16_t -> (u)int* + EOpConvFloat16ToInt8, + EOpConvFloat16ToInt16, + EOpConvFloat16ToInt, + EOpConvFloat16ToInt64, + EOpConvFloat16ToUint8, + EOpConvFloat16ToUint16, + EOpConvFloat16ToUint, + EOpConvFloat16ToUint64, + + // float16_t -> float* + EOpConvFloat16ToFloat, + EOpConvFloat16ToDouble, + + // float -> (u)int* + EOpConvFloatToInt8, + EOpConvFloatToInt16, + EOpConvFloatToInt, + EOpConvFloatToInt64, + EOpConvFloatToUint8, + EOpConvFloatToUint16, + EOpConvFloatToUint, + EOpConvFloatToUint64, + + // float -> float* + EOpConvFloatToFloat16, + EOpConvFloatToDouble, + + // float64 _t-> (u)int* + EOpConvDoubleToInt8, + EOpConvDoubleToInt16, + EOpConvDoubleToInt, + EOpConvDoubleToInt64, + EOpConvDoubleToUint8, + EOpConvDoubleToUint16, + EOpConvDoubleToUint, + EOpConvDoubleToUint64, + + // float64_t -> float* + EOpConvDoubleToFloat16, + EOpConvDoubleToFloat, + + // uint64_t <-> pointer + EOpConvUint64ToPtr, + EOpConvPtrToUint64, + + // uvec2 <-> pointer + EOpConvUvec2ToPtr, + EOpConvPtrToUvec2, + + // + // binary operations + // + + EOpAdd, + EOpSub, + EOpMul, + EOpDiv, + EOpMod, + EOpRightShift, + EOpLeftShift, + EOpAnd, + EOpInclusiveOr, + EOpExclusiveOr, + EOpEqual, + EOpNotEqual, + EOpVectorEqual, + EOpVectorNotEqual, + EOpLessThan, + EOpGreaterThan, + EOpLessThanEqual, + EOpGreaterThanEqual, + EOpComma, + + EOpVectorTimesScalar, + EOpVectorTimesMatrix, + EOpMatrixTimesVector, + EOpMatrixTimesScalar, + + EOpLogicalOr, + EOpLogicalXor, + EOpLogicalAnd, + + EOpIndexDirect, + EOpIndexIndirect, + EOpIndexDirectStruct, + + EOpVectorSwizzle, + + EOpMethod, + EOpScoping, + + // + // Built-in functions mapped to operators + // + + EOpRadians, + EOpDegrees, + EOpSin, + EOpCos, + EOpTan, + EOpAsin, + EOpAcos, + EOpAtan, + EOpSinh, + EOpCosh, + EOpTanh, + EOpAsinh, + EOpAcosh, + EOpAtanh, + + EOpPow, + EOpExp, + EOpLog, + EOpExp2, + EOpLog2, + EOpSqrt, + EOpInverseSqrt, + + EOpAbs, + EOpSign, + EOpFloor, + EOpTrunc, + EOpRound, + EOpRoundEven, + EOpCeil, + EOpFract, + EOpModf, + EOpMin, + EOpMax, + EOpClamp, + EOpMix, + EOpStep, + EOpSmoothStep, + + EOpIsNan, + EOpIsInf, + + EOpFma, + + EOpFrexp, + EOpLdexp, + + EOpFloatBitsToInt, + EOpFloatBitsToUint, + EOpIntBitsToFloat, + EOpUintBitsToFloat, + EOpDoubleBitsToInt64, + EOpDoubleBitsToUint64, + EOpInt64BitsToDouble, + EOpUint64BitsToDouble, + EOpFloat16BitsToInt16, + EOpFloat16BitsToUint16, + EOpInt16BitsToFloat16, + EOpUint16BitsToFloat16, + EOpPackSnorm2x16, + EOpUnpackSnorm2x16, + EOpPackUnorm2x16, + EOpUnpackUnorm2x16, + EOpPackSnorm4x8, + EOpUnpackSnorm4x8, + EOpPackUnorm4x8, + EOpUnpackUnorm4x8, + EOpPackHalf2x16, + EOpUnpackHalf2x16, + EOpPackDouble2x32, + EOpUnpackDouble2x32, + EOpPackInt2x32, + EOpUnpackInt2x32, + EOpPackUint2x32, + EOpUnpackUint2x32, + EOpPackFloat2x16, + EOpUnpackFloat2x16, + EOpPackInt2x16, + EOpUnpackInt2x16, + EOpPackUint2x16, + EOpUnpackUint2x16, + EOpPackInt4x16, + EOpUnpackInt4x16, + EOpPackUint4x16, + EOpUnpackUint4x16, + EOpPack16, + EOpPack32, + EOpPack64, + EOpUnpack32, + EOpUnpack16, + EOpUnpack8, + + EOpLength, + EOpDistance, + EOpDot, + EOpCross, + EOpNormalize, + EOpFaceForward, + EOpReflect, + EOpRefract, + + EOpMin3, + EOpMax3, + EOpMid3, + + EOpDPdx, // Fragment only + EOpDPdy, // Fragment only + EOpFwidth, // Fragment only + EOpDPdxFine, // Fragment only + EOpDPdyFine, // Fragment only + EOpFwidthFine, // Fragment only + EOpDPdxCoarse, // Fragment only + EOpDPdyCoarse, // Fragment only + EOpFwidthCoarse, // Fragment only + + EOpInterpolateAtCentroid, // Fragment only + EOpInterpolateAtSample, // Fragment only + EOpInterpolateAtOffset, // Fragment only + EOpInterpolateAtVertex, + + EOpMatrixTimesMatrix, + EOpOuterProduct, + EOpDeterminant, + EOpMatrixInverse, + EOpTranspose, + + EOpFtransform, + + EOpNoise, + + EOpEmitVertex, // geometry only + EOpEndPrimitive, // geometry only + EOpEmitStreamVertex, // geometry only + EOpEndStreamPrimitive, // geometry only + + EOpBarrier, + EOpMemoryBarrier, + EOpMemoryBarrierAtomicCounter, + EOpMemoryBarrierBuffer, + EOpMemoryBarrierImage, + EOpMemoryBarrierShared, // compute only + EOpGroupMemoryBarrier, // compute only + + EOpBallot, + EOpReadInvocation, + EOpReadFirstInvocation, + + EOpAnyInvocation, + EOpAllInvocations, + EOpAllInvocationsEqual, + + EOpSubgroupGuardStart, + EOpSubgroupBarrier, + EOpSubgroupMemoryBarrier, + EOpSubgroupMemoryBarrierBuffer, + EOpSubgroupMemoryBarrierImage, + EOpSubgroupMemoryBarrierShared, // compute only + EOpSubgroupElect, + EOpSubgroupAll, + EOpSubgroupAny, + EOpSubgroupAllEqual, + EOpSubgroupBroadcast, + EOpSubgroupBroadcastFirst, + EOpSubgroupBallot, + EOpSubgroupInverseBallot, + EOpSubgroupBallotBitExtract, + EOpSubgroupBallotBitCount, + EOpSubgroupBallotInclusiveBitCount, + EOpSubgroupBallotExclusiveBitCount, + EOpSubgroupBallotFindLSB, + EOpSubgroupBallotFindMSB, + EOpSubgroupShuffle, + EOpSubgroupShuffleXor, + EOpSubgroupShuffleUp, + EOpSubgroupShuffleDown, + EOpSubgroupAdd, + EOpSubgroupMul, + EOpSubgroupMin, + EOpSubgroupMax, + EOpSubgroupAnd, + EOpSubgroupOr, + EOpSubgroupXor, + EOpSubgroupInclusiveAdd, + EOpSubgroupInclusiveMul, + EOpSubgroupInclusiveMin, + EOpSubgroupInclusiveMax, + EOpSubgroupInclusiveAnd, + EOpSubgroupInclusiveOr, + EOpSubgroupInclusiveXor, + EOpSubgroupExclusiveAdd, + EOpSubgroupExclusiveMul, + EOpSubgroupExclusiveMin, + EOpSubgroupExclusiveMax, + EOpSubgroupExclusiveAnd, + EOpSubgroupExclusiveOr, + EOpSubgroupExclusiveXor, + EOpSubgroupClusteredAdd, + EOpSubgroupClusteredMul, + EOpSubgroupClusteredMin, + EOpSubgroupClusteredMax, + EOpSubgroupClusteredAnd, + EOpSubgroupClusteredOr, + EOpSubgroupClusteredXor, + EOpSubgroupQuadBroadcast, + EOpSubgroupQuadSwapHorizontal, + EOpSubgroupQuadSwapVertical, + EOpSubgroupQuadSwapDiagonal, + + EOpSubgroupPartition, + EOpSubgroupPartitionedAdd, + EOpSubgroupPartitionedMul, + EOpSubgroupPartitionedMin, + EOpSubgroupPartitionedMax, + EOpSubgroupPartitionedAnd, + EOpSubgroupPartitionedOr, + EOpSubgroupPartitionedXor, + EOpSubgroupPartitionedInclusiveAdd, + EOpSubgroupPartitionedInclusiveMul, + EOpSubgroupPartitionedInclusiveMin, + EOpSubgroupPartitionedInclusiveMax, + EOpSubgroupPartitionedInclusiveAnd, + EOpSubgroupPartitionedInclusiveOr, + EOpSubgroupPartitionedInclusiveXor, + EOpSubgroupPartitionedExclusiveAdd, + EOpSubgroupPartitionedExclusiveMul, + EOpSubgroupPartitionedExclusiveMin, + EOpSubgroupPartitionedExclusiveMax, + EOpSubgroupPartitionedExclusiveAnd, + EOpSubgroupPartitionedExclusiveOr, + EOpSubgroupPartitionedExclusiveXor, + + EOpSubgroupGuardStop, + + EOpMinInvocations, + EOpMaxInvocations, + EOpAddInvocations, + EOpMinInvocationsNonUniform, + EOpMaxInvocationsNonUniform, + EOpAddInvocationsNonUniform, + EOpMinInvocationsInclusiveScan, + EOpMaxInvocationsInclusiveScan, + EOpAddInvocationsInclusiveScan, + EOpMinInvocationsInclusiveScanNonUniform, + EOpMaxInvocationsInclusiveScanNonUniform, + EOpAddInvocationsInclusiveScanNonUniform, + EOpMinInvocationsExclusiveScan, + EOpMaxInvocationsExclusiveScan, + EOpAddInvocationsExclusiveScan, + EOpMinInvocationsExclusiveScanNonUniform, + EOpMaxInvocationsExclusiveScanNonUniform, + EOpAddInvocationsExclusiveScanNonUniform, + EOpSwizzleInvocations, + EOpSwizzleInvocationsMasked, + EOpWriteInvocation, + EOpMbcnt, + + EOpCubeFaceIndex, + EOpCubeFaceCoord, + EOpTime, + + EOpAtomicAdd, + EOpAtomicMin, + EOpAtomicMax, + EOpAtomicAnd, + EOpAtomicOr, + EOpAtomicXor, + EOpAtomicExchange, + EOpAtomicCompSwap, + EOpAtomicLoad, + EOpAtomicStore, + + EOpAtomicCounterIncrement, // results in pre-increment value + EOpAtomicCounterDecrement, // results in post-decrement value + EOpAtomicCounter, + EOpAtomicCounterAdd, + EOpAtomicCounterSubtract, + EOpAtomicCounterMin, + EOpAtomicCounterMax, + EOpAtomicCounterAnd, + EOpAtomicCounterOr, + EOpAtomicCounterXor, + EOpAtomicCounterExchange, + EOpAtomicCounterCompSwap, + + EOpAny, + EOpAll, + + EOpCooperativeMatrixLoad, + EOpCooperativeMatrixStore, + EOpCooperativeMatrixMulAdd, + + EOpBeginInvocationInterlock, // Fragment only + EOpEndInvocationInterlock, // Fragment only + + EOpIsHelperInvocation, + + EOpDebugPrintf, + + // + // Branch + // + + EOpKill, // Fragment only + EOpReturn, + EOpBreak, + EOpContinue, + EOpCase, + EOpDefault, + EOpDemote, // Fragment only + + // + // Constructors + // + + EOpConstructGuardStart, + EOpConstructInt, // these first scalar forms also identify what implicit conversion is needed + EOpConstructUint, + EOpConstructInt8, + EOpConstructUint8, + EOpConstructInt16, + EOpConstructUint16, + EOpConstructInt64, + EOpConstructUint64, + EOpConstructBool, + EOpConstructFloat, + EOpConstructDouble, + // Keep vector and matrix constructors in a consistent relative order for + // TParseContext::constructBuiltIn, which converts between 8/16/32 bit + // vector constructors + EOpConstructVec2, + EOpConstructVec3, + EOpConstructVec4, + EOpConstructMat2x2, + EOpConstructMat2x3, + EOpConstructMat2x4, + EOpConstructMat3x2, + EOpConstructMat3x3, + EOpConstructMat3x4, + EOpConstructMat4x2, + EOpConstructMat4x3, + EOpConstructMat4x4, + EOpConstructDVec2, + EOpConstructDVec3, + EOpConstructDVec4, + EOpConstructBVec2, + EOpConstructBVec3, + EOpConstructBVec4, + EOpConstructI8Vec2, + EOpConstructI8Vec3, + EOpConstructI8Vec4, + EOpConstructU8Vec2, + EOpConstructU8Vec3, + EOpConstructU8Vec4, + EOpConstructI16Vec2, + EOpConstructI16Vec3, + EOpConstructI16Vec4, + EOpConstructU16Vec2, + EOpConstructU16Vec3, + EOpConstructU16Vec4, + EOpConstructIVec2, + EOpConstructIVec3, + EOpConstructIVec4, + EOpConstructUVec2, + EOpConstructUVec3, + EOpConstructUVec4, + EOpConstructI64Vec2, + EOpConstructI64Vec3, + EOpConstructI64Vec4, + EOpConstructU64Vec2, + EOpConstructU64Vec3, + EOpConstructU64Vec4, + EOpConstructDMat2x2, + EOpConstructDMat2x3, + EOpConstructDMat2x4, + EOpConstructDMat3x2, + EOpConstructDMat3x3, + EOpConstructDMat3x4, + EOpConstructDMat4x2, + EOpConstructDMat4x3, + EOpConstructDMat4x4, + EOpConstructIMat2x2, + EOpConstructIMat2x3, + EOpConstructIMat2x4, + EOpConstructIMat3x2, + EOpConstructIMat3x3, + EOpConstructIMat3x4, + EOpConstructIMat4x2, + EOpConstructIMat4x3, + EOpConstructIMat4x4, + EOpConstructUMat2x2, + EOpConstructUMat2x3, + EOpConstructUMat2x4, + EOpConstructUMat3x2, + EOpConstructUMat3x3, + EOpConstructUMat3x4, + EOpConstructUMat4x2, + EOpConstructUMat4x3, + EOpConstructUMat4x4, + EOpConstructBMat2x2, + EOpConstructBMat2x3, + EOpConstructBMat2x4, + EOpConstructBMat3x2, + EOpConstructBMat3x3, + EOpConstructBMat3x4, + EOpConstructBMat4x2, + EOpConstructBMat4x3, + EOpConstructBMat4x4, + EOpConstructFloat16, + EOpConstructF16Vec2, + EOpConstructF16Vec3, + EOpConstructF16Vec4, + EOpConstructF16Mat2x2, + EOpConstructF16Mat2x3, + EOpConstructF16Mat2x4, + EOpConstructF16Mat3x2, + EOpConstructF16Mat3x3, + EOpConstructF16Mat3x4, + EOpConstructF16Mat4x2, + EOpConstructF16Mat4x3, + EOpConstructF16Mat4x4, + EOpConstructStruct, + EOpConstructTextureSampler, + EOpConstructNonuniform, // expected to be transformed away, not present in final AST + EOpConstructReference, + EOpConstructCooperativeMatrix, + EOpConstructGuardEnd, + + // + // moves + // + + EOpAssign, + EOpAddAssign, + EOpSubAssign, + EOpMulAssign, + EOpVectorTimesMatrixAssign, + EOpVectorTimesScalarAssign, + EOpMatrixTimesScalarAssign, + EOpMatrixTimesMatrixAssign, + EOpDivAssign, + EOpModAssign, + EOpAndAssign, + EOpInclusiveOrAssign, + EOpExclusiveOrAssign, + EOpLeftShiftAssign, + EOpRightShiftAssign, + + // + // Array operators + // + + // Can apply to arrays, vectors, or matrices. + // Can be decomposed to a constant at compile time, but this does not always happen, + // due to link-time effects. So, consumer can expect either a link-time sized or + // run-time sized array. + EOpArrayLength, + + // + // Image operations + // + + EOpImageGuardBegin, + + EOpImageQuerySize, + EOpImageQuerySamples, + EOpImageLoad, + EOpImageStore, + EOpImageLoadLod, + EOpImageStoreLod, + EOpImageAtomicAdd, + EOpImageAtomicMin, + EOpImageAtomicMax, + EOpImageAtomicAnd, + EOpImageAtomicOr, + EOpImageAtomicXor, + EOpImageAtomicExchange, + EOpImageAtomicCompSwap, + EOpImageAtomicLoad, + EOpImageAtomicStore, + + EOpSubpassLoad, + EOpSubpassLoadMS, + EOpSparseImageLoad, + EOpSparseImageLoadLod, + + EOpImageGuardEnd, + + // + // Texture operations + // + + EOpTextureGuardBegin, + + EOpTextureQuerySize, + EOpTextureQueryLod, + EOpTextureQueryLevels, + EOpTextureQuerySamples, + + EOpSamplingGuardBegin, + + EOpTexture, + EOpTextureProj, + EOpTextureLod, + EOpTextureOffset, + EOpTextureFetch, + EOpTextureFetchOffset, + EOpTextureProjOffset, + EOpTextureLodOffset, + EOpTextureProjLod, + EOpTextureProjLodOffset, + EOpTextureGrad, + EOpTextureGradOffset, + EOpTextureProjGrad, + EOpTextureProjGradOffset, + EOpTextureGather, + EOpTextureGatherOffset, + EOpTextureGatherOffsets, + EOpTextureClamp, + EOpTextureOffsetClamp, + EOpTextureGradClamp, + EOpTextureGradOffsetClamp, + EOpTextureGatherLod, + EOpTextureGatherLodOffset, + EOpTextureGatherLodOffsets, + EOpFragmentMaskFetch, + EOpFragmentFetch, + + EOpSparseTextureGuardBegin, + + EOpSparseTexture, + EOpSparseTextureLod, + EOpSparseTextureOffset, + EOpSparseTextureFetch, + EOpSparseTextureFetchOffset, + EOpSparseTextureLodOffset, + EOpSparseTextureGrad, + EOpSparseTextureGradOffset, + EOpSparseTextureGather, + EOpSparseTextureGatherOffset, + EOpSparseTextureGatherOffsets, + EOpSparseTexelsResident, + EOpSparseTextureClamp, + EOpSparseTextureOffsetClamp, + EOpSparseTextureGradClamp, + EOpSparseTextureGradOffsetClamp, + EOpSparseTextureGatherLod, + EOpSparseTextureGatherLodOffset, + EOpSparseTextureGatherLodOffsets, + + EOpSparseTextureGuardEnd, + + EOpImageFootprintGuardBegin, + EOpImageSampleFootprintNV, + EOpImageSampleFootprintClampNV, + EOpImageSampleFootprintLodNV, + EOpImageSampleFootprintGradNV, + EOpImageSampleFootprintGradClampNV, + EOpImageFootprintGuardEnd, + EOpSamplingGuardEnd, + EOpTextureGuardEnd, + + // + // Integer operations + // + + EOpAddCarry, + EOpSubBorrow, + EOpUMulExtended, + EOpIMulExtended, + EOpBitfieldExtract, + EOpBitfieldInsert, + EOpBitFieldReverse, + EOpBitCount, + EOpFindLSB, + EOpFindMSB, + + EOpCountLeadingZeros, + EOpCountTrailingZeros, + EOpAbsDifference, + EOpAddSaturate, + EOpSubSaturate, + EOpAverage, + EOpAverageRounded, + EOpMul32x16, + + EOpTrace, + EOpReportIntersection, + EOpIgnoreIntersection, + EOpTerminateRay, + EOpExecuteCallable, + EOpWritePackedPrimitiveIndices4x8NV, + + // + // GL_EXT_ray_query operations + // + + EOpRayQueryInitialize, + EOpRayQueryTerminate, + EOpRayQueryGenerateIntersection, + EOpRayQueryConfirmIntersection, + EOpRayQueryProceed, + EOpRayQueryGetIntersectionType, + EOpRayQueryGetRayTMin, + EOpRayQueryGetRayFlags, + EOpRayQueryGetIntersectionT, + EOpRayQueryGetIntersectionInstanceCustomIndex, + EOpRayQueryGetIntersectionInstanceId, + EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset, + EOpRayQueryGetIntersectionGeometryIndex, + EOpRayQueryGetIntersectionPrimitiveIndex, + EOpRayQueryGetIntersectionBarycentrics, + EOpRayQueryGetIntersectionFrontFace, + EOpRayQueryGetIntersectionCandidateAABBOpaque, + EOpRayQueryGetIntersectionObjectRayDirection, + EOpRayQueryGetIntersectionObjectRayOrigin, + EOpRayQueryGetWorldRayDirection, + EOpRayQueryGetWorldRayOrigin, + EOpRayQueryGetIntersectionObjectToWorld, + EOpRayQueryGetIntersectionWorldToObject, + + // + // HLSL operations + // + + EOpClip, // discard if input value < 0 + EOpIsFinite, + EOpLog10, // base 10 log + EOpRcp, // 1/x + EOpSaturate, // clamp from 0 to 1 + EOpSinCos, // sin and cos in out parameters + EOpGenMul, // mul(x,y) on any of mat/vec/scalars + EOpDst, // x = 1, y=src0.y * src1.y, z=src0.z, w=src1.w + EOpInterlockedAdd, // atomic ops, but uses [optional] out arg instead of return + EOpInterlockedAnd, // ... + EOpInterlockedCompareExchange, // ... + EOpInterlockedCompareStore, // ... + EOpInterlockedExchange, // ... + EOpInterlockedMax, // ... + EOpInterlockedMin, // ... + EOpInterlockedOr, // ... + EOpInterlockedXor, // ... + EOpAllMemoryBarrierWithGroupSync, // memory barriers without non-hlsl AST equivalents + EOpDeviceMemoryBarrier, // ... + EOpDeviceMemoryBarrierWithGroupSync, // ... + EOpWorkgroupMemoryBarrier, // ... + EOpWorkgroupMemoryBarrierWithGroupSync, // ... + EOpEvaluateAttributeSnapped, // InterpolateAtOffset with int position on 16x16 grid + EOpF32tof16, // HLSL conversion: half of a PackHalf2x16 + EOpF16tof32, // HLSL conversion: half of an UnpackHalf2x16 + EOpLit, // HLSL lighting coefficient vector + EOpTextureBias, // HLSL texture bias: will be lowered to EOpTexture + EOpAsDouble, // slightly different from EOpUint64BitsToDouble + EOpD3DCOLORtoUBYTE4, // convert and swizzle 4-component color to UBYTE4 range + + EOpMethodSample, // Texture object methods. These are translated to existing + EOpMethodSampleBias, // AST methods, and exist to represent HLSL semantics until that + EOpMethodSampleCmp, // translation is performed. See HlslParseContext::decomposeSampleMethods(). + EOpMethodSampleCmpLevelZero, // ... + EOpMethodSampleGrad, // ... + EOpMethodSampleLevel, // ... + EOpMethodLoad, // ... + EOpMethodGetDimensions, // ... + EOpMethodGetSamplePosition, // ... + EOpMethodGather, // ... + EOpMethodCalculateLevelOfDetail, // ... + EOpMethodCalculateLevelOfDetailUnclamped, // ... + + // Load already defined above for textures + EOpMethodLoad2, // Structure buffer object methods. These are translated to existing + EOpMethodLoad3, // AST methods, and exist to represent HLSL semantics until that + EOpMethodLoad4, // translation is performed. See HlslParseContext::decomposeSampleMethods(). + EOpMethodStore, // ... + EOpMethodStore2, // ... + EOpMethodStore3, // ... + EOpMethodStore4, // ... + EOpMethodIncrementCounter, // ... + EOpMethodDecrementCounter, // ... + // EOpMethodAppend is defined for geo shaders below + EOpMethodConsume, + + // SM5 texture methods + EOpMethodGatherRed, // These are covered under the above EOpMethodSample comment about + EOpMethodGatherGreen, // translation to existing AST opcodes. They exist temporarily + EOpMethodGatherBlue, // because HLSL arguments are slightly different. + EOpMethodGatherAlpha, // ... + EOpMethodGatherCmp, // ... + EOpMethodGatherCmpRed, // ... + EOpMethodGatherCmpGreen, // ... + EOpMethodGatherCmpBlue, // ... + EOpMethodGatherCmpAlpha, // ... + + // geometry methods + EOpMethodAppend, // Geometry shader methods + EOpMethodRestartStrip, // ... + + // matrix + EOpMatrixSwizzle, // select multiple matrix components (non-column) + + // SM6 wave ops + EOpWaveGetLaneCount, // Will decompose to gl_SubgroupSize. + EOpWaveGetLaneIndex, // Will decompose to gl_SubgroupInvocationID. + EOpWaveActiveCountBits, // Will decompose to subgroupBallotBitCount(subgroupBallot()). + EOpWavePrefixCountBits, // Will decompose to subgroupBallotInclusiveBitCount(subgroupBallot()). + + // Shader Clock Ops + EOpReadClockSubgroupKHR, + EOpReadClockDeviceKHR, +}; + +class TIntermTraverser; +class TIntermOperator; +class TIntermAggregate; +class TIntermUnary; +class TIntermBinary; +class TIntermConstantUnion; +class TIntermSelection; +class TIntermSwitch; +class TIntermBranch; +class TIntermTyped; +class TIntermMethod; +class TIntermSymbol; +class TIntermLoop; + +} // end namespace glslang + +// +// Base class for the tree nodes +// +// (Put outside the glslang namespace, as it's used as part of the external interface.) +// +class TIntermNode { +public: + POOL_ALLOCATOR_NEW_DELETE(glslang::GetThreadPoolAllocator()) + + TIntermNode() { loc.init(); } + virtual const glslang::TSourceLoc& getLoc() const { return loc; } + virtual void setLoc(const glslang::TSourceLoc& l) { loc = l; } + virtual void traverse(glslang::TIntermTraverser*) = 0; + virtual glslang::TIntermTyped* getAsTyped() { return 0; } + virtual glslang::TIntermOperator* getAsOperator() { return 0; } + virtual glslang::TIntermConstantUnion* getAsConstantUnion() { return 0; } + virtual glslang::TIntermAggregate* getAsAggregate() { return 0; } + virtual glslang::TIntermUnary* getAsUnaryNode() { return 0; } + virtual glslang::TIntermBinary* getAsBinaryNode() { return 0; } + virtual glslang::TIntermSelection* getAsSelectionNode() { return 0; } + virtual glslang::TIntermSwitch* getAsSwitchNode() { return 0; } + virtual glslang::TIntermMethod* getAsMethodNode() { return 0; } + virtual glslang::TIntermSymbol* getAsSymbolNode() { return 0; } + virtual glslang::TIntermBranch* getAsBranchNode() { return 0; } + virtual glslang::TIntermLoop* getAsLoopNode() { return 0; } + + virtual const glslang::TIntermTyped* getAsTyped() const { return 0; } + virtual const glslang::TIntermOperator* getAsOperator() const { return 0; } + virtual const glslang::TIntermConstantUnion* getAsConstantUnion() const { return 0; } + virtual const glslang::TIntermAggregate* getAsAggregate() const { return 0; } + virtual const glslang::TIntermUnary* getAsUnaryNode() const { return 0; } + virtual const glslang::TIntermBinary* getAsBinaryNode() const { return 0; } + virtual const glslang::TIntermSelection* getAsSelectionNode() const { return 0; } + virtual const glslang::TIntermSwitch* getAsSwitchNode() const { return 0; } + virtual const glslang::TIntermMethod* getAsMethodNode() const { return 0; } + virtual const glslang::TIntermSymbol* getAsSymbolNode() const { return 0; } + virtual const glslang::TIntermBranch* getAsBranchNode() const { return 0; } + virtual const glslang::TIntermLoop* getAsLoopNode() const { return 0; } + virtual ~TIntermNode() { } + +protected: + TIntermNode(const TIntermNode&); + TIntermNode& operator=(const TIntermNode&); + glslang::TSourceLoc loc; +}; + +namespace glslang { + +// +// This is just to help yacc. +// +struct TIntermNodePair { + TIntermNode* node1; + TIntermNode* node2; +}; + +// +// Intermediate class for nodes that have a type. +// +class TIntermTyped : public TIntermNode { +public: + TIntermTyped(const TType& t) { type.shallowCopy(t); } + TIntermTyped(TBasicType basicType) { TType bt(basicType); type.shallowCopy(bt); } + virtual TIntermTyped* getAsTyped() { return this; } + virtual const TIntermTyped* getAsTyped() const { return this; } + virtual void setType(const TType& t) { type.shallowCopy(t); } + virtual const TType& getType() const { return type; } + virtual TType& getWritableType() { return type; } + + virtual TBasicType getBasicType() const { return type.getBasicType(); } + virtual TQualifier& getQualifier() { return type.getQualifier(); } + virtual const TQualifier& getQualifier() const { return type.getQualifier(); } + virtual void propagatePrecision(TPrecisionQualifier); + virtual int getVectorSize() const { return type.getVectorSize(); } + virtual int getMatrixCols() const { return type.getMatrixCols(); } + virtual int getMatrixRows() const { return type.getMatrixRows(); } + virtual bool isMatrix() const { return type.isMatrix(); } + virtual bool isArray() const { return type.isArray(); } + virtual bool isVector() const { return type.isVector(); } + virtual bool isScalar() const { return type.isScalar(); } + virtual bool isStruct() const { return type.isStruct(); } + virtual bool isFloatingDomain() const { return type.isFloatingDomain(); } + virtual bool isIntegerDomain() const { return type.isIntegerDomain(); } + bool isAtomic() const { return type.isAtomic(); } + bool isReference() const { return type.isReference(); } + TString getCompleteString() const { return type.getCompleteString(); } + +protected: + TIntermTyped& operator=(const TIntermTyped&); + TType type; +}; + +// +// Handle for, do-while, and while loops. +// +class TIntermLoop : public TIntermNode { +public: + TIntermLoop(TIntermNode* aBody, TIntermTyped* aTest, TIntermTyped* aTerminal, bool testFirst) : + body(aBody), + test(aTest), + terminal(aTerminal), + first(testFirst), + unroll(false), + dontUnroll(false), + dependency(0), + minIterations(0), + maxIterations(iterationsInfinite), + iterationMultiple(1), + peelCount(0), + partialCount(0) + { } + + virtual TIntermLoop* getAsLoopNode() { return this; } + virtual const TIntermLoop* getAsLoopNode() const { return this; } + virtual void traverse(TIntermTraverser*); + TIntermNode* getBody() const { return body; } + TIntermTyped* getTest() const { return test; } + TIntermTyped* getTerminal() const { return terminal; } + bool testFirst() const { return first; } + + void setUnroll() { unroll = true; } + void setDontUnroll() { + dontUnroll = true; + peelCount = 0; + partialCount = 0; + } + bool getUnroll() const { return unroll; } + bool getDontUnroll() const { return dontUnroll; } + + static const unsigned int dependencyInfinite = 0xFFFFFFFF; + static const unsigned int iterationsInfinite = 0xFFFFFFFF; + void setLoopDependency(int d) { dependency = d; } + int getLoopDependency() const { return dependency; } + + void setMinIterations(unsigned int v) { minIterations = v; } + unsigned int getMinIterations() const { return minIterations; } + void setMaxIterations(unsigned int v) { maxIterations = v; } + unsigned int getMaxIterations() const { return maxIterations; } + void setIterationMultiple(unsigned int v) { iterationMultiple = v; } + unsigned int getIterationMultiple() const { return iterationMultiple; } + void setPeelCount(unsigned int v) { + peelCount = v; + dontUnroll = false; + } + unsigned int getPeelCount() const { return peelCount; } + void setPartialCount(unsigned int v) { + partialCount = v; + dontUnroll = false; + } + unsigned int getPartialCount() const { return partialCount; } + +protected: + TIntermNode* body; // code to loop over + TIntermTyped* test; // exit condition associated with loop, could be 0 for 'for' loops + TIntermTyped* terminal; // exists for for-loops + bool first; // true for while and for, not for do-while + bool unroll; // true if unroll requested + bool dontUnroll; // true if request to not unroll + unsigned int dependency; // loop dependency hint; 0 means not set or unknown + unsigned int minIterations; // as per the SPIR-V specification + unsigned int maxIterations; // as per the SPIR-V specification + unsigned int iterationMultiple; // as per the SPIR-V specification + unsigned int peelCount; // as per the SPIR-V specification + unsigned int partialCount; // as per the SPIR-V specification +}; + +// +// Handle case, break, continue, return, and kill. +// +class TIntermBranch : public TIntermNode { +public: + TIntermBranch(TOperator op, TIntermTyped* e) : + flowOp(op), + expression(e) { } + virtual TIntermBranch* getAsBranchNode() { return this; } + virtual const TIntermBranch* getAsBranchNode() const { return this; } + virtual void traverse(TIntermTraverser*); + TOperator getFlowOp() const { return flowOp; } + TIntermTyped* getExpression() const { return expression; } + void setExpression(TIntermTyped* pExpression) { expression = pExpression; } +protected: + TOperator flowOp; + TIntermTyped* expression; +}; + +// +// Represent method names before seeing their calling signature +// or resolving them to operations. Just an expression as the base object +// and a textural name. +// +class TIntermMethod : public TIntermTyped { +public: + TIntermMethod(TIntermTyped* o, const TType& t, const TString& m) : TIntermTyped(t), object(o), method(m) { } + virtual TIntermMethod* getAsMethodNode() { return this; } + virtual const TIntermMethod* getAsMethodNode() const { return this; } + virtual const TString& getMethodName() const { return method; } + virtual TIntermTyped* getObject() const { return object; } + virtual void traverse(TIntermTraverser*); +protected: + TIntermTyped* object; + TString method; +}; + +// +// Nodes that correspond to symbols or constants in the source code. +// +class TIntermSymbol : public TIntermTyped { +public: + // if symbol is initialized as symbol(sym), the memory comes from the pool allocator of sym. If sym comes from + // per process threadPoolAllocator, then it causes increased memory usage per compile + // it is essential to use "symbol = sym" to assign to symbol + TIntermSymbol(int i, const TString& n, const TType& t) + : TIntermTyped(t), id(i), +#ifndef GLSLANG_WEB + flattenSubset(-1), +#endif + constSubtree(nullptr) + { name = n; } + virtual int getId() const { return id; } + virtual void changeId(int i) { id = i; } + virtual const TString& getName() const { return name; } + virtual void traverse(TIntermTraverser*); + virtual TIntermSymbol* getAsSymbolNode() { return this; } + virtual const TIntermSymbol* getAsSymbolNode() const { return this; } + void setConstArray(const TConstUnionArray& c) { constArray = c; } + const TConstUnionArray& getConstArray() const { return constArray; } + void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; } + TIntermTyped* getConstSubtree() const { return constSubtree; } +#ifndef GLSLANG_WEB + void setFlattenSubset(int subset) { flattenSubset = subset; } + int getFlattenSubset() const { return flattenSubset; } // -1 means full object +#endif + + // This is meant for cases where a node has already been constructed, and + // later on, it becomes necessary to switch to a different symbol. + virtual void switchId(int newId) { id = newId; } + +protected: + int id; // the unique id of the symbol this node represents +#ifndef GLSLANG_WEB + int flattenSubset; // how deeply the flattened object rooted at id has been dereferenced +#endif + TString name; // the name of the symbol this node represents + TConstUnionArray constArray; // if the symbol is a front-end compile-time constant, this is its value + TIntermTyped* constSubtree; +}; + +class TIntermConstantUnion : public TIntermTyped { +public: + TIntermConstantUnion(const TConstUnionArray& ua, const TType& t) : TIntermTyped(t), constArray(ua), literal(false) { } + const TConstUnionArray& getConstArray() const { return constArray; } + virtual TIntermConstantUnion* getAsConstantUnion() { return this; } + virtual const TIntermConstantUnion* getAsConstantUnion() const { return this; } + virtual void traverse(TIntermTraverser*); + virtual TIntermTyped* fold(TOperator, const TIntermTyped*) const; + virtual TIntermTyped* fold(TOperator, const TType&) const; + void setLiteral() { literal = true; } + void setExpression() { literal = false; } + bool isLiteral() const { return literal; } + +protected: + TIntermConstantUnion& operator=(const TIntermConstantUnion&); + + const TConstUnionArray constArray; + bool literal; // true if node represents a literal in the source code +}; + +// Represent the independent aspects of a texturing TOperator +struct TCrackedTextureOp { + bool query; + bool proj; + bool lod; + bool fetch; + bool offset; + bool offsets; + bool gather; + bool grad; + bool subpass; + bool lodClamp; + bool fragMask; +}; + +// +// Intermediate class for node types that hold operators. +// +class TIntermOperator : public TIntermTyped { +public: + virtual TIntermOperator* getAsOperator() { return this; } + virtual const TIntermOperator* getAsOperator() const { return this; } + TOperator getOp() const { return op; } + void setOp(TOperator newOp) { op = newOp; } + bool modifiesState() const; + bool isConstructor() const; + bool isTexture() const { return op > EOpTextureGuardBegin && op < EOpTextureGuardEnd; } + bool isSampling() const { return op > EOpSamplingGuardBegin && op < EOpSamplingGuardEnd; } +#ifdef GLSLANG_WEB + bool isImage() const { return false; } + bool isSparseTexture() const { return false; } + bool isImageFootprint() const { return false; } + bool isSparseImage() const { return false; } + bool isSubgroup() const { return false; } +#else + bool isImage() const { return op > EOpImageGuardBegin && op < EOpImageGuardEnd; } + bool isSparseTexture() const { return op > EOpSparseTextureGuardBegin && op < EOpSparseTextureGuardEnd; } + bool isImageFootprint() const { return op > EOpImageFootprintGuardBegin && op < EOpImageFootprintGuardEnd; } + bool isSparseImage() const { return op == EOpSparseImageLoad; } + bool isSubgroup() const { return op > EOpSubgroupGuardStart && op < EOpSubgroupGuardStop; } +#endif + + void setOperationPrecision(TPrecisionQualifier p) { operationPrecision = p; } + TPrecisionQualifier getOperationPrecision() const { return operationPrecision != EpqNone ? + operationPrecision : + type.getQualifier().precision; } + TString getCompleteString() const + { + TString cs = type.getCompleteString(); + if (getOperationPrecision() != type.getQualifier().precision) { + cs += ", operation at "; + cs += GetPrecisionQualifierString(getOperationPrecision()); + } + + return cs; + } + + // Crack the op into the individual dimensions of texturing operation. + void crackTexture(TSampler sampler, TCrackedTextureOp& cracked) const + { + cracked.query = false; + cracked.proj = false; + cracked.lod = false; + cracked.fetch = false; + cracked.offset = false; + cracked.offsets = false; + cracked.gather = false; + cracked.grad = false; + cracked.subpass = false; + cracked.lodClamp = false; + cracked.fragMask = false; + + switch (op) { + case EOpImageQuerySize: + case EOpImageQuerySamples: + case EOpTextureQuerySize: + case EOpTextureQueryLod: + case EOpTextureQueryLevels: + case EOpTextureQuerySamples: + case EOpSparseTexelsResident: + cracked.query = true; + break; + case EOpTexture: + case EOpSparseTexture: + break; + case EOpTextureProj: + cracked.proj = true; + break; + case EOpTextureLod: + case EOpSparseTextureLod: + cracked.lod = true; + break; + case EOpTextureOffset: + case EOpSparseTextureOffset: + cracked.offset = true; + break; + case EOpTextureFetch: + case EOpSparseTextureFetch: + cracked.fetch = true; + if (sampler.is1D() || (sampler.dim == Esd2D && ! sampler.isMultiSample()) || sampler.dim == Esd3D) + cracked.lod = true; + break; + case EOpTextureFetchOffset: + case EOpSparseTextureFetchOffset: + cracked.fetch = true; + cracked.offset = true; + if (sampler.is1D() || (sampler.dim == Esd2D && ! sampler.isMultiSample()) || sampler.dim == Esd3D) + cracked.lod = true; + break; + case EOpTextureProjOffset: + cracked.offset = true; + cracked.proj = true; + break; + case EOpTextureLodOffset: + case EOpSparseTextureLodOffset: + cracked.offset = true; + cracked.lod = true; + break; + case EOpTextureProjLod: + cracked.lod = true; + cracked.proj = true; + break; + case EOpTextureProjLodOffset: + cracked.offset = true; + cracked.lod = true; + cracked.proj = true; + break; + case EOpTextureGrad: + case EOpSparseTextureGrad: + cracked.grad = true; + break; + case EOpTextureGradOffset: + case EOpSparseTextureGradOffset: + cracked.grad = true; + cracked.offset = true; + break; + case EOpTextureProjGrad: + cracked.grad = true; + cracked.proj = true; + break; + case EOpTextureProjGradOffset: + cracked.grad = true; + cracked.offset = true; + cracked.proj = true; + break; +#ifndef GLSLANG_WEB + case EOpTextureClamp: + case EOpSparseTextureClamp: + cracked.lodClamp = true; + break; + case EOpTextureOffsetClamp: + case EOpSparseTextureOffsetClamp: + cracked.offset = true; + cracked.lodClamp = true; + break; + case EOpTextureGradClamp: + case EOpSparseTextureGradClamp: + cracked.grad = true; + cracked.lodClamp = true; + break; + case EOpTextureGradOffsetClamp: + case EOpSparseTextureGradOffsetClamp: + cracked.grad = true; + cracked.offset = true; + cracked.lodClamp = true; + break; + case EOpTextureGather: + case EOpSparseTextureGather: + cracked.gather = true; + break; + case EOpTextureGatherOffset: + case EOpSparseTextureGatherOffset: + cracked.gather = true; + cracked.offset = true; + break; + case EOpTextureGatherOffsets: + case EOpSparseTextureGatherOffsets: + cracked.gather = true; + cracked.offsets = true; + break; + case EOpTextureGatherLod: + case EOpSparseTextureGatherLod: + cracked.gather = true; + cracked.lod = true; + break; + case EOpTextureGatherLodOffset: + case EOpSparseTextureGatherLodOffset: + cracked.gather = true; + cracked.offset = true; + cracked.lod = true; + break; + case EOpTextureGatherLodOffsets: + case EOpSparseTextureGatherLodOffsets: + cracked.gather = true; + cracked.offsets = true; + cracked.lod = true; + break; + case EOpImageLoadLod: + case EOpImageStoreLod: + case EOpSparseImageLoadLod: + cracked.lod = true; + break; + case EOpFragmentMaskFetch: + cracked.subpass = sampler.dim == EsdSubpass; + cracked.fragMask = true; + break; + case EOpFragmentFetch: + cracked.subpass = sampler.dim == EsdSubpass; + cracked.fragMask = true; + break; + case EOpImageSampleFootprintNV: + break; + case EOpImageSampleFootprintClampNV: + cracked.lodClamp = true; + break; + case EOpImageSampleFootprintLodNV: + cracked.lod = true; + break; + case EOpImageSampleFootprintGradNV: + cracked.grad = true; + break; + case EOpImageSampleFootprintGradClampNV: + cracked.lodClamp = true; + cracked.grad = true; + break; + case EOpSubpassLoad: + case EOpSubpassLoadMS: + cracked.subpass = true; + break; +#endif + default: + break; + } + } + +protected: + TIntermOperator(TOperator o) : TIntermTyped(EbtFloat), op(o), operationPrecision(EpqNone) {} + TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o), operationPrecision(EpqNone) {} + TOperator op; + // The result precision is in the inherited TType, and is usually meant to be both + // the operation precision and the result precision. However, some more complex things, + // like built-in function calls, distinguish between the two, in which case non-EqpNone + // 'operationPrecision' overrides the result precision as far as operation precision + // is concerned. + TPrecisionQualifier operationPrecision; +}; + +// +// Nodes for all the basic binary math operators. +// +class TIntermBinary : public TIntermOperator { +public: + TIntermBinary(TOperator o) : TIntermOperator(o) {} + virtual void traverse(TIntermTraverser*); + virtual void setLeft(TIntermTyped* n) { left = n; } + virtual void setRight(TIntermTyped* n) { right = n; } + virtual TIntermTyped* getLeft() const { return left; } + virtual TIntermTyped* getRight() const { return right; } + virtual TIntermBinary* getAsBinaryNode() { return this; } + virtual const TIntermBinary* getAsBinaryNode() const { return this; } + virtual void updatePrecision(); +protected: + TIntermTyped* left; + TIntermTyped* right; +}; + +// +// Nodes for unary math operators. +// +class TIntermUnary : public TIntermOperator { +public: + TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {} + TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {} + virtual void traverse(TIntermTraverser*); + virtual void setOperand(TIntermTyped* o) { operand = o; } + virtual TIntermTyped* getOperand() { return operand; } + virtual const TIntermTyped* getOperand() const { return operand; } + virtual TIntermUnary* getAsUnaryNode() { return this; } + virtual const TIntermUnary* getAsUnaryNode() const { return this; } + virtual void updatePrecision(); +protected: + TIntermTyped* operand; +}; + +typedef TVector TIntermSequence; +typedef TVector TQualifierList; +// +// Nodes that operate on an arbitrary sized set of children. +// +class TIntermAggregate : public TIntermOperator { +public: + TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(nullptr) { } + TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(nullptr) { } + ~TIntermAggregate() { delete pragmaTable; } + virtual TIntermAggregate* getAsAggregate() { return this; } + virtual const TIntermAggregate* getAsAggregate() const { return this; } + virtual void setOperator(TOperator o) { op = o; } + virtual TIntermSequence& getSequence() { return sequence; } + virtual const TIntermSequence& getSequence() const { return sequence; } + virtual void setName(const TString& n) { name = n; } + virtual const TString& getName() const { return name; } + virtual void traverse(TIntermTraverser*); + virtual void setUserDefined() { userDefined = true; } + virtual bool isUserDefined() { return userDefined; } + virtual TQualifierList& getQualifierList() { return qualifier; } + virtual const TQualifierList& getQualifierList() const { return qualifier; } + void setOptimize(bool o) { optimize = o; } + void setDebug(bool d) { debug = d; } + bool getOptimize() const { return optimize; } + bool getDebug() const { return debug; } + void setPragmaTable(const TPragmaTable& pTable); + const TPragmaTable& getPragmaTable() const { return *pragmaTable; } +protected: + TIntermAggregate(const TIntermAggregate&); // disallow copy constructor + TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator + TIntermSequence sequence; + TQualifierList qualifier; + TString name; + bool userDefined; // used for user defined function names + bool optimize; + bool debug; + TPragmaTable* pragmaTable; +}; + +// +// For if tests. +// +class TIntermSelection : public TIntermTyped { +public: + TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) : + TIntermTyped(EbtVoid), condition(cond), trueBlock(trueB), falseBlock(falseB), + shortCircuit(true), + flatten(false), dontFlatten(false) {} + TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) : + TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB), + shortCircuit(true), + flatten(false), dontFlatten(false) {} + virtual void traverse(TIntermTraverser*); + virtual TIntermTyped* getCondition() const { return condition; } + virtual TIntermNode* getTrueBlock() const { return trueBlock; } + virtual TIntermNode* getFalseBlock() const { return falseBlock; } + virtual TIntermSelection* getAsSelectionNode() { return this; } + virtual const TIntermSelection* getAsSelectionNode() const { return this; } + + void setNoShortCircuit() { shortCircuit = false; } + bool getShortCircuit() const { return shortCircuit; } + + void setFlatten() { flatten = true; } + void setDontFlatten() { dontFlatten = true; } + bool getFlatten() const { return flatten; } + bool getDontFlatten() const { return dontFlatten; } + +protected: + TIntermTyped* condition; + TIntermNode* trueBlock; + TIntermNode* falseBlock; + bool shortCircuit; // normally all if-then-else and all GLSL ?: short-circuit, but HLSL ?: does not + bool flatten; // true if flatten requested + bool dontFlatten; // true if requested to not flatten +}; + +// +// For switch statements. Designed use is that a switch will have sequence of nodes +// that are either case/default nodes or a *single* node that represents all the code +// in between (if any) consecutive case/defaults. So, a traversal need only deal with +// 0 or 1 nodes per case/default statement. +// +class TIntermSwitch : public TIntermNode { +public: + TIntermSwitch(TIntermTyped* cond, TIntermAggregate* b) : condition(cond), body(b), + flatten(false), dontFlatten(false) {} + virtual void traverse(TIntermTraverser*); + virtual TIntermNode* getCondition() const { return condition; } + virtual TIntermAggregate* getBody() const { return body; } + virtual TIntermSwitch* getAsSwitchNode() { return this; } + virtual const TIntermSwitch* getAsSwitchNode() const { return this; } + + void setFlatten() { flatten = true; } + void setDontFlatten() { dontFlatten = true; } + bool getFlatten() const { return flatten; } + bool getDontFlatten() const { return dontFlatten; } + +protected: + TIntermTyped* condition; + TIntermAggregate* body; + bool flatten; // true if flatten requested + bool dontFlatten; // true if requested to not flatten +}; + +enum TVisit +{ + EvPreVisit, + EvInVisit, + EvPostVisit +}; + +// +// For traversing the tree. User should derive from this, +// put their traversal specific data in it, and then pass +// it to a Traverse method. +// +// When using this, just fill in the methods for nodes you want visited. +// Return false from a pre-visit to skip visiting that node's subtree. +// +// Explicitly set postVisit to true if you want post visiting, otherwise, +// filled in methods will only be called at pre-visit time (before processing +// the subtree). Similarly for inVisit for in-order visiting of nodes with +// multiple children. +// +// If you only want post-visits, explicitly turn off preVisit (and inVisit) +// and turn on postVisit. +// +// In general, for the visit*() methods, return true from interior nodes +// to have the traversal continue on to children. +// +// If you process children yourself, or don't want them processed, return false. +// +class TIntermTraverser { +public: + POOL_ALLOCATOR_NEW_DELETE(glslang::GetThreadPoolAllocator()) + TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) : + preVisit(preVisit), + inVisit(inVisit), + postVisit(postVisit), + rightToLeft(rightToLeft), + depth(0), + maxDepth(0) { } + virtual ~TIntermTraverser() { } + + virtual void visitSymbol(TIntermSymbol*) { } + virtual void visitConstantUnion(TIntermConstantUnion*) { } + virtual bool visitBinary(TVisit, TIntermBinary*) { return true; } + virtual bool visitUnary(TVisit, TIntermUnary*) { return true; } + virtual bool visitSelection(TVisit, TIntermSelection*) { return true; } + virtual bool visitAggregate(TVisit, TIntermAggregate*) { return true; } + virtual bool visitLoop(TVisit, TIntermLoop*) { return true; } + virtual bool visitBranch(TVisit, TIntermBranch*) { return true; } + virtual bool visitSwitch(TVisit, TIntermSwitch*) { return true; } + + int getMaxDepth() const { return maxDepth; } + + void incrementDepth(TIntermNode *current) + { + depth++; + maxDepth = (std::max)(maxDepth, depth); + path.push_back(current); + } + + void decrementDepth() + { + depth--; + path.pop_back(); + } + + TIntermNode *getParentNode() + { + return path.size() == 0 ? NULL : path.back(); + } + + const bool preVisit; + const bool inVisit; + const bool postVisit; + const bool rightToLeft; + +protected: + TIntermTraverser& operator=(TIntermTraverser&); + + int depth; + int maxDepth; + + // All the nodes from root to the current node's parent during traversing. + TVector path; +}; + +// KHR_vulkan_glsl says "Two arrays sized with specialization constants are the same type only if +// sized with the same symbol, involving no operations" +inline bool SameSpecializationConstants(TIntermTyped* node1, TIntermTyped* node2) +{ + return node1->getAsSymbolNode() && node2->getAsSymbolNode() && + node1->getAsSymbolNode()->getId() == node2->getAsSymbolNode()->getId(); +} + +} // end namespace glslang + +#endif // __INTERMEDIATE_H diff --git a/mac/include/glslang/Include/revision.h b/mac/include/glslang/Include/revision.h new file mode 100644 index 00000000..744c2fb4 --- /dev/null +++ b/mac/include/glslang/Include/revision.h @@ -0,0 +1,3 @@ +// This header is generated by the make-revision script. + +#define GLSLANG_PATCH_LEVEL 3743 diff --git a/mac/include/glslang/MachineIndependent/Initialize.h b/mac/include/glslang/MachineIndependent/Initialize.h new file mode 100644 index 00000000..ac8ec33e --- /dev/null +++ b/mac/include/glslang/MachineIndependent/Initialize.h @@ -0,0 +1,112 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013-2016 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _INITIALIZE_INCLUDED_ +#define _INITIALIZE_INCLUDED_ + +#include "../Include/ResourceLimits.h" +#include "../Include/Common.h" +#include "../Include/ShHandle.h" +#include "SymbolTable.h" +#include "Versions.h" + +namespace glslang { + +// +// This is made to hold parseable strings for almost all the built-in +// functions and variables for one specific combination of version +// and profile. (Some still need to be added programmatically.) +// This is a base class for language-specific derivations, which +// can be used for language independent builtins. +// +// The strings are organized by +// commonBuiltins: intersection of all stages' built-ins, processed just once +// stageBuiltins[]: anything a stage needs that's not in commonBuiltins +// +class TBuiltInParseables { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + TBuiltInParseables(); + virtual ~TBuiltInParseables(); + virtual void initialize(int version, EProfile, const SpvVersion& spvVersion) = 0; + virtual void initialize(const TBuiltInResource& resources, int version, EProfile, const SpvVersion& spvVersion, EShLanguage) = 0; + virtual const TString& getCommonString() const { return commonBuiltins; } + virtual const TString& getStageString(EShLanguage language) const { return stageBuiltins[language]; } + + virtual void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable) = 0; + virtual void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources) = 0; + +protected: + TString commonBuiltins; + TString stageBuiltins[EShLangCount]; +}; + +// +// This is a GLSL specific derivation of TBuiltInParseables. To present a stable +// interface and match other similar code, it is called TBuiltIns, rather +// than TBuiltInParseablesGlsl. +// +class TBuiltIns : public TBuiltInParseables { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + TBuiltIns(); + virtual ~TBuiltIns(); + void initialize(int version, EProfile, const SpvVersion& spvVersion); + void initialize(const TBuiltInResource& resources, int version, EProfile, const SpvVersion& spvVersion, EShLanguage); + + void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable); + void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources); + +protected: + void addTabledBuiltins(int version, EProfile profile, const SpvVersion& spvVersion); + void relateTabledBuiltins(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage, TSymbolTable&); + void add2ndGenerationSamplingImaging(int version, EProfile profile, const SpvVersion& spvVersion); + void addSubpassSampling(TSampler, const TString& typeName, int version, EProfile profile); + void addQueryFunctions(TSampler, const TString& typeName, int version, EProfile profile); + void addImageFunctions(TSampler, const TString& typeName, int version, EProfile profile); + void addSamplingFunctions(TSampler, const TString& typeName, int version, EProfile profile); + void addGatherFunctions(TSampler, const TString& typeName, int version, EProfile profile); + + // Helpers for making textual representations of the permutations + // of texturing/imaging functions. + const char* postfixes[5]; + const char* prefixes[EbtNumTypes]; + int dimMap[EsdNumDims]; +}; + +} // end namespace glslang + +#endif // _INITIALIZE_INCLUDED_ diff --git a/mac/include/glslang/MachineIndependent/LiveTraverser.h b/mac/include/glslang/MachineIndependent/LiveTraverser.h new file mode 100644 index 00000000..7333bc96 --- /dev/null +++ b/mac/include/glslang/MachineIndependent/LiveTraverser.h @@ -0,0 +1,138 @@ +// +// Copyright (C) 2016 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#pragma once + +#include "../Include/Common.h" +#include "reflection.h" +#include "localintermediate.h" + +#include "gl_types.h" + +#include +#include + +namespace glslang { + +// +// The traverser: mostly pass through, except +// - processing function-call nodes to push live functions onto the stack of functions to process +// - processing selection nodes to trim semantically dead code +// +// This is in the glslang namespace directly so it can be a friend of TReflection. +// This can be derived from to implement reflection database traversers or +// binding mappers: anything that wants to traverse the live subset of the tree. +// + +class TLiveTraverser : public TIntermTraverser { +public: + TLiveTraverser(const TIntermediate& i, bool traverseAll = false, + bool preVisit = true, bool inVisit = false, bool postVisit = false) : + TIntermTraverser(preVisit, inVisit, postVisit), + intermediate(i), traverseAll(traverseAll) + { } + + // + // Given a function name, find its subroot in the tree, and push it onto the stack of + // functions left to process. + // + void pushFunction(const TString& name) + { + TIntermSequence& globals = intermediate.getTreeRoot()->getAsAggregate()->getSequence(); + for (unsigned int f = 0; f < globals.size(); ++f) { + TIntermAggregate* candidate = globals[f]->getAsAggregate(); + if (candidate && candidate->getOp() == EOpFunction && candidate->getName() == name) { + functions.push_back(candidate); + break; + } + } + } + + typedef std::list TFunctionStack; + TFunctionStack functions; + +protected: + // To catch which function calls are not dead, and hence which functions must be visited. + virtual bool visitAggregate(TVisit, TIntermAggregate* node) + { + if (!traverseAll) + if (node->getOp() == EOpFunctionCall) + addFunctionCall(node); + + return true; // traverse this subtree + } + + // To prune semantically dead paths. + virtual bool visitSelection(TVisit /* visit */, TIntermSelection* node) + { + if (traverseAll) + return true; // traverse all code + + TIntermConstantUnion* constant = node->getCondition()->getAsConstantUnion(); + if (constant) { + // cull the path that is dead + if (constant->getConstArray()[0].getBConst() == true && node->getTrueBlock()) + node->getTrueBlock()->traverse(this); + if (constant->getConstArray()[0].getBConst() == false && node->getFalseBlock()) + node->getFalseBlock()->traverse(this); + + return false; // don't traverse any more, we did it all above + } else + return true; // traverse the whole subtree + } + + // Track live functions as well as uniforms, so that we don't visit dead functions + // and only visit each function once. + void addFunctionCall(TIntermAggregate* call) + { + // // just use the map to ensure we process each function at most once + if (liveFunctions.find(call->getName()) == liveFunctions.end()) { + liveFunctions.insert(call->getName()); + pushFunction(call->getName()); + } + } + + const TIntermediate& intermediate; + typedef std::unordered_set TLiveFunctions; + TLiveFunctions liveFunctions; + bool traverseAll; + +private: + // prevent copy & copy construct + TLiveTraverser(TLiveTraverser&); + TLiveTraverser& operator=(TLiveTraverser&); +}; + +} // namespace glslang diff --git a/mac/include/glslang/MachineIndependent/ParseHelper.h b/mac/include/glslang/MachineIndependent/ParseHelper.h new file mode 100644 index 00000000..20df6405 --- /dev/null +++ b/mac/include/glslang/MachineIndependent/ParseHelper.h @@ -0,0 +1,525 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +// +// This header defines a two-level parse-helper hierarchy, derived from +// TParseVersions: +// - TParseContextBase: sharable across multiple parsers +// - TParseContext: GLSL specific helper +// + +#ifndef _PARSER_HELPER_INCLUDED_ +#define _PARSER_HELPER_INCLUDED_ + +#include +#include + +#include "parseVersions.h" +#include "../Include/ShHandle.h" +#include "SymbolTable.h" +#include "localintermediate.h" +#include "Scan.h" +#include "attribute.h" + +namespace glslang { + +struct TPragma { + TPragma(bool o, bool d) : optimize(o), debug(d) { } + bool optimize; + bool debug; + TPragmaTable pragmaTable; +}; + +class TScanContext; +class TPpContext; + +typedef std::set TIdSetType; + +// +// Sharable code (as well as what's in TParseVersions) across +// parse helpers. +// +class TParseContextBase : public TParseVersions { +public: + TParseContextBase(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins, int version, + EProfile profile, const SpvVersion& spvVersion, EShLanguage language, + TInfoSink& infoSink, bool forwardCompatible, EShMessages messages, + const TString* entryPoint = nullptr) + : TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages), + scopeMangler("::"), + symbolTable(symbolTable), + statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0), + postEntryPointReturn(false), + contextPragma(true, false), + beginInvocationInterlockCount(0), endInvocationInterlockCount(0), + parsingBuiltins(parsingBuiltins), scanContext(nullptr), ppContext(nullptr), + limits(resources.limits), + globalUniformBlock(nullptr), + globalUniformBinding(TQualifier::layoutBindingEnd), + globalUniformSet(TQualifier::layoutSetEnd) + { + if (entryPoint != nullptr) + sourceEntryPointName = *entryPoint; + } + virtual ~TParseContextBase() { } + +#if !defined(GLSLANG_WEB) || defined(GLSLANG_WEB_DEVEL) + virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...); + virtual void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...); + virtual void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...); + virtual void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...); +#endif + + virtual void setLimits(const TBuiltInResource&) = 0; + + void checkIndex(const TSourceLoc&, const TType&, int& index); + + EShLanguage getLanguage() const { return language; } + void setScanContext(TScanContext* c) { scanContext = c; } + TScanContext* getScanContext() const { return scanContext; } + void setPpContext(TPpContext* c) { ppContext = c; } + TPpContext* getPpContext() const { return ppContext; } + + virtual void setLineCallback(const std::function& func) { lineCallback = func; } + virtual void setExtensionCallback(const std::function& func) { extensionCallback = func; } + virtual void setVersionCallback(const std::function& func) { versionCallback = func; } + virtual void setPragmaCallback(const std::function&)>& func) { pragmaCallback = func; } + virtual void setErrorCallback(const std::function& func) { errorCallback = func; } + + virtual void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) = 0; + virtual bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) = 0; + virtual bool lineDirectiveShouldSetNextLine() const = 0; + virtual void handlePragma(const TSourceLoc&, const TVector&) = 0; + + virtual bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) = 0; + + virtual void notifyVersion(int line, int version, const char* type_string) + { + if (versionCallback) + versionCallback(line, version, type_string); + } + virtual void notifyErrorDirective(int line, const char* error_message) + { + if (errorCallback) + errorCallback(line, error_message); + } + virtual void notifyLineDirective(int curLineNo, int newLineNo, bool hasSource, int sourceNum, const char* sourceName) + { + if (lineCallback) + lineCallback(curLineNo, newLineNo, hasSource, sourceNum, sourceName); + } + virtual void notifyExtensionDirective(int line, const char* extension, const char* behavior) + { + if (extensionCallback) + extensionCallback(line, extension, behavior); + } + +#ifdef ENABLE_HLSL + // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL) + virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr); +#endif + + // Potentially rename shader entry point function + void renameShaderFunction(TString*& name) const + { + // Replace the entry point name given in the shader with the real entry point name, + // if there is a substitution. + if (name != nullptr && *name == sourceEntryPointName && intermediate.getEntryPointName().size() > 0) + name = NewPoolTString(intermediate.getEntryPointName().c_str()); + } + + virtual bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*); + virtual void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*); + + const char* const scopeMangler; + + // Basic parsing state, easily accessible to the grammar + + TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile + int statementNestingLevel; // 0 if outside all flow control or compound statements + int loopNestingLevel; // 0 if outside all loops + int structNestingLevel; // 0 if outside blocks and structures + int controlFlowNestingLevel; // 0 if outside all flow control + const TType* currentFunctionType; // the return type of the function that's currently being parsed + bool functionReturnsValue; // true if a non-void function has a return + // if inside a function, true if the function is the entry point and this is after a return statement + bool postEntryPointReturn; + // case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting + TList switchSequenceStack; + // the statementNestingLevel the current switch statement is at, which must match the level of its case statements + TList switchLevel; + struct TPragma contextPragma; + int beginInvocationInterlockCount; + int endInvocationInterlockCount; + +protected: + TParseContextBase(TParseContextBase&); + TParseContextBase& operator=(TParseContextBase&); + + const bool parsingBuiltins; // true if parsing built-in symbols/functions + TVector linkageSymbols; // will be transferred to 'linkage', after all editing is done, order preserving + TScanContext* scanContext; + TPpContext* ppContext; + TBuiltInResource resources; + TLimits& limits; + TString sourceEntryPointName; + + // These, if set, will be called when a line, pragma ... is preprocessed. + // They will be called with any parameters to the original directive. + std::function lineCallback; + std::function&)> pragmaCallback; + std::function versionCallback; + std::function extensionCallback; + std::function errorCallback; + + // see implementation for detail + const TFunction* selectFunction(const TVector, const TFunction&, + std::function, + std::function, + /* output */ bool& tie); + + virtual void parseSwizzleSelector(const TSourceLoc&, const TString&, int size, + TSwizzleSelectors&); + + // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL) + TVariable* globalUniformBlock; // the actual block, inserted into the symbol table + unsigned int globalUniformBinding; // the block's binding number + unsigned int globalUniformSet; // the block's set number + int firstNewMember; // the index of the first member not yet inserted into the symbol table + // override this to set the language-specific name + virtual const char* getGlobalUniformBlockName() const { return ""; } + virtual void setUniformBlockDefaults(TType&) const { } + virtual void finalizeGlobalUniformBlockLayout(TVariable&) { } + virtual void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, TPrefixType prefix, + va_list args); + virtual void trackLinkage(TSymbol& symbol); + virtual void makeEditable(TSymbol*&); + virtual TVariable* getEditableVariable(const char* name); + virtual void finish(); +}; + +// +// Manage the state for when to respect precision qualifiers and when to warn about +// the defaults being different than might be expected. +// +class TPrecisionManager { +public: + TPrecisionManager() : obey(false), warn(false), explicitIntDefault(false), explicitFloatDefault(false){ } + virtual ~TPrecisionManager() {} + + void respectPrecisionQualifiers() { obey = true; } + bool respectingPrecisionQualifiers() const { return obey; } + bool shouldWarnAboutDefaults() const { return warn; } + void defaultWarningGiven() { warn = false; } + void warnAboutDefaults() { warn = true; } + void explicitIntDefaultSeen() + { + explicitIntDefault = true; + if (explicitFloatDefault) + warn = false; + } + void explicitFloatDefaultSeen() + { + explicitFloatDefault = true; + if (explicitIntDefault) + warn = false; + } + +protected: + bool obey; // respect precision qualifiers + bool warn; // need to give a warning about the defaults + bool explicitIntDefault; // user set the default for int/uint + bool explicitFloatDefault; // user set the default for float +}; + +// +// GLSL-specific parse helper. Should have GLSL in the name, but that's +// too big of a change for comparing branches at the moment, and perhaps +// impacts downstream consumers as well. +// +class TParseContext : public TParseContextBase { +public: + TParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins, int version, EProfile, const SpvVersion& spvVersion, EShLanguage, TInfoSink&, + bool forwardCompatible = false, EShMessages messages = EShMsgDefault, + const TString* entryPoint = nullptr); + virtual ~TParseContext(); + + bool obeyPrecisionQualifiers() const { return precisionManager.respectingPrecisionQualifiers(); } + void setPrecisionDefaults(); + + void setLimits(const TBuiltInResource&) override; + bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) override; + void parserError(const char* s); // for bison's yyerror + + void reservedErrorCheck(const TSourceLoc&, const TString&); + void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) override; + bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) override; + bool lineDirectiveShouldSetNextLine() const override; + bool builtInName(const TString&); + + void handlePragma(const TSourceLoc&, const TVector&) override; + TIntermTyped* handleVariable(const TSourceLoc&, TSymbol* symbol, const TString* string); + TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index); + void handleIndexLimits(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index); + +#ifndef GLSLANG_WEB + void makeEditable(TSymbol*&) override; + void ioArrayCheck(const TSourceLoc&, const TType&, const TString& identifier); +#endif + bool isIoResizeArray(const TType&) const; + void fixIoArraySize(const TSourceLoc&, TType&); + void handleIoResizeArrayAccess(const TSourceLoc&, TIntermTyped* base); + void checkIoArraysConsistency(const TSourceLoc&, bool tailOnly = false); + int getIoArrayImplicitSize(const TQualifier&, TString* featureString = nullptr) const; + void checkIoArrayConsistency(const TSourceLoc&, int requiredSize, const char* feature, TType&, const TString&); + + TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right); + TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode); + TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field); + void blockMemberExtensionCheck(const TSourceLoc&, const TIntermTyped* base, int member, const TString& memberName); + TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype); + TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&); + TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*); + TIntermTyped* handleBuiltInFunctionCall(TSourceLoc, TIntermNode* arguments, const TFunction& function); + void computeBuiltinPrecisions(TIntermTyped&, const TFunction&); + TIntermNode* handleReturnValue(const TSourceLoc&, TIntermTyped*); + void checkLocation(const TSourceLoc&, TOperator); + TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*); + void addInputArgumentConversions(const TFunction&, TIntermNode*&) const; + TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const; + void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&); + void nonOpBuiltInCheck(const TSourceLoc&, const TFunction&, TIntermAggregate&); + void userFunctionCallCheck(const TSourceLoc&, TIntermAggregate&); + void samplerConstructorLocationCheck(const TSourceLoc&, const char* token, TIntermNode*); + TFunction* handleConstructorCall(const TSourceLoc&, const TPublicType&); + void handlePrecisionQualifier(const TSourceLoc&, TQualifier&, TPrecisionQualifier); + void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier); + void memorySemanticsCheck(const TSourceLoc&, const TFunction&, const TIntermOperator& callNode); + + void assignError(const TSourceLoc&, const char* op, TString left, TString right); + void unaryOpError(const TSourceLoc&, const char* op, TString operand); + void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right); + void variableCheck(TIntermTyped*& nodePtr); + bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override; + void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override; + void constantValueCheck(TIntermTyped* node, const char* token); + void integerCheck(const TIntermTyped* node, const char* token); + void globalCheck(const TSourceLoc&, const char* token); + bool constructorError(const TSourceLoc&, TIntermNode*, TFunction&, TOperator, TType&); + bool constructorTextureSamplerError(const TSourceLoc&, const TFunction&); + void arraySizeCheck(const TSourceLoc&, TIntermTyped* expr, TArraySize&, const char *sizeType); + bool arrayQualifierError(const TSourceLoc&, const TQualifier&); + bool arrayError(const TSourceLoc&, const TType&); + void arraySizeRequiredCheck(const TSourceLoc&, const TArraySizes&); + void structArrayCheck(const TSourceLoc&, const TType& structure); + void arraySizesCheck(const TSourceLoc&, const TQualifier&, TArraySizes*, const TIntermTyped* initializer, bool lastMember); + void arrayOfArrayVersionCheck(const TSourceLoc&, const TArraySizes*); + bool voidErrorCheck(const TSourceLoc&, const TString&, TBasicType); + void boolCheck(const TSourceLoc&, const TIntermTyped*); + void boolCheck(const TSourceLoc&, const TPublicType&); + void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer); + void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier); + void accStructCheck(const TSourceLoc & loc, const TType & type, const TString & identifier); + void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier); + void memberQualifierCheck(glslang::TPublicType&); + void globalQualifierFixCheck(const TSourceLoc&, TQualifier&); + void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&); + bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType); + void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force); + void setDefaultPrecision(const TSourceLoc&, TPublicType&, TPrecisionQualifier); + int computeSamplerTypeIndex(TSampler&); + TPrecisionQualifier getDefaultPrecision(TPublicType&); + void precisionQualifierCheck(const TSourceLoc&, TBasicType, TQualifier&); + void parameterTypeCheck(const TSourceLoc&, TStorageQualifier qualifier, const TType& type); + bool containsFieldWithBasicType(const TType& type ,TBasicType basicType); + TSymbol* redeclareBuiltinVariable(const TSourceLoc&, const TString&, const TQualifier&, const TShaderQualifiers&); + void redeclareBuiltinBlock(const TSourceLoc&, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes); + void paramCheckFixStorage(const TSourceLoc&, const TStorageQualifier&, TType& type); + void paramCheckFix(const TSourceLoc&, const TQualifier&, TType& type); + void nestedBlockCheck(const TSourceLoc&); + void nestedStructCheck(const TSourceLoc&); + void arrayObjectCheck(const TSourceLoc&, const TType&, const char* op); + void opaqueCheck(const TSourceLoc&, const TType&, const char* op); + void referenceCheck(const TSourceLoc&, const TType&, const char* op); + void storage16BitAssignmentCheck(const TSourceLoc&, const TType&, const char* op); + void specializationCheck(const TSourceLoc&, const TType&, const char* op); + void structTypeCheck(const TSourceLoc&, TPublicType&); + void inductiveLoopCheck(const TSourceLoc&, TIntermNode* init, TIntermLoop* loop); + void arrayLimitCheck(const TSourceLoc&, const TString&, int size); + void limitCheck(const TSourceLoc&, int value, const char* limit, const char* feature); + + void inductiveLoopBodyCheck(TIntermNode*, int loopIndexId, TSymbolTable&); + void constantIndexExpressionCheck(TIntermNode*); + + void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&); + void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&, const TIntermTyped*); + void mergeObjectLayoutQualifiers(TQualifier& dest, const TQualifier& src, bool inheritOnly); + void layoutObjectCheck(const TSourceLoc&, const TSymbol&); + void layoutMemberLocationArrayCheck(const TSourceLoc&, bool memberWithLocation, TArraySizes* arraySizes); + void layoutTypeCheck(const TSourceLoc&, const TType&); + void layoutQualifierCheck(const TSourceLoc&, const TQualifier&); + void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&); + void fixOffset(const TSourceLoc&, TSymbol&); + + const TFunction* findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn); + const TFunction* findFunctionExact(const TSourceLoc& loc, const TFunction& call, bool& builtIn); + const TFunction* findFunction120(const TSourceLoc& loc, const TFunction& call, bool& builtIn); + const TFunction* findFunction400(const TSourceLoc& loc, const TFunction& call, bool& builtIn); + const TFunction* findFunctionExplicitTypes(const TSourceLoc& loc, const TFunction& call, bool& builtIn); + void declareTypeDefaults(const TSourceLoc&, const TPublicType&); + TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, const TPublicType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0); + TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&); + TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&); + TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset); + void inheritMemoryQualifiers(const TQualifier& from, TQualifier& to); + void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0); + void blockStageIoCheck(const TSourceLoc&, const TQualifier&); + void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName); + void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation); + void fixXfbOffsets(TQualifier&, TTypeList&); + void fixBlockUniformOffsets(TQualifier&, TTypeList&); + void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier); + void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&); + void invariantCheck(const TSourceLoc&, const TQualifier&); + void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&); + void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode); + TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body); + +#ifndef GLSLANG_WEB + TAttributeType attributeFromName(const TString& name) const; + TAttributes* makeAttributes(const TString& identifier) const; + TAttributes* makeAttributes(const TString& identifier, TIntermNode* node) const; + TAttributes* mergeAttributes(TAttributes*, TAttributes*) const; + + // Determine selection control from attributes + void handleSelectionAttributes(const TAttributes& attributes, TIntermNode*); + void handleSwitchAttributes(const TAttributes& attributes, TIntermNode*); + // Determine loop control from attributes + void handleLoopAttributes(const TAttributes& attributes, TIntermNode*); +#endif + + void checkAndResizeMeshViewDim(const TSourceLoc&, TType&, bool isBlockMember); + +protected: + void nonInitConstCheck(const TSourceLoc&, TString& identifier, TType& type); + void inheritGlobalDefaults(TQualifier& dst) const; + TVariable* makeInternalVariable(const char* name, const TType&) const; + TVariable* declareNonArray(const TSourceLoc&, const TString& identifier, const TType&); + void declareArray(const TSourceLoc&, const TString& identifier, const TType&, TSymbol*&); + void checkRuntimeSizable(const TSourceLoc&, const TIntermTyped&); + bool isRuntimeLength(const TIntermTyped&) const; + TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable); + TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer); +#ifndef GLSLANG_WEB + void finish() override; +#endif + +public: + // + // Generally, bison productions, the scanner, and the PP need read/write access to these; just give them direct access + // + + // Current state of parsing + bool inMain; // if inside a function, true if the function is main + const TString* blockName; + TQualifier currentBlockQualifier; + TPrecisionQualifier defaultPrecision[EbtNumTypes]; + TBuiltInResource resources; + TLimits& limits; + +protected: + TParseContext(TParseContext&); + TParseContext& operator=(TParseContext&); + + static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2 * 2 * 2 * 2)); // see computeSamplerTypeIndex() + TPrecisionQualifier defaultSamplerPrecision[maxSamplerIndex]; + TPrecisionManager precisionManager; + TQualifier globalBufferDefaults; + TQualifier globalUniformDefaults; + TQualifier globalInputDefaults; + TQualifier globalOutputDefaults; + TString currentCaller; // name of last function body entered (not valid when at global scope) +#ifndef GLSLANG_WEB + int* atomicUintOffsets; // to become an array of the right size to hold an offset per binding point + bool anyIndexLimits; + TIdSetType inductiveLoopIds; + TVector needsIndexLimitationChecking; + + // + // Geometry shader input arrays: + // - array sizing is based on input primitive and/or explicit size + // + // Tessellation control output arrays: + // - array sizing is based on output layout(vertices=...) and/or explicit size + // + // Both: + // - array sizing is retroactive + // - built-in block redeclarations interact with this + // + // Design: + // - use a per-context "resize-list", a list of symbols whose array sizes + // can be fixed + // + // - the resize-list starts empty at beginning of user-shader compilation, it does + // not have built-ins in it + // + // - on built-in array use: copyUp() symbol and add it to the resize-list + // + // - on user array declaration: add it to the resize-list + // + // - on block redeclaration: copyUp() symbol and add it to the resize-list + // * note, that appropriately gives an error if redeclaring a block that + // was already used and hence already copied-up + // + // - on seeing a layout declaration that sizes the array, fix everything in the + // resize-list, giving errors for mismatch + // + // - on seeing an array size declaration, give errors on mismatch between it and previous + // array-sizing declarations + // + TVector ioArraySymbolResizeList; +#endif +}; + +} // end namespace glslang + +#endif // _PARSER_HELPER_INCLUDED_ diff --git a/mac/include/glslang/MachineIndependent/RemoveTree.h b/mac/include/glslang/MachineIndependent/RemoveTree.h new file mode 100644 index 00000000..1ed01562 --- /dev/null +++ b/mac/include/glslang/MachineIndependent/RemoveTree.h @@ -0,0 +1,41 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#pragma once + +namespace glslang { + +void RemoveAllTreeNodes(TIntermNode*); + +} // end namespace glslang diff --git a/mac/include/glslang/MachineIndependent/Scan.h b/mac/include/glslang/MachineIndependent/Scan.h new file mode 100644 index 00000000..24b75cf7 --- /dev/null +++ b/mac/include/glslang/MachineIndependent/Scan.h @@ -0,0 +1,276 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +#ifndef _GLSLANG_SCAN_INCLUDED_ +#define _GLSLANG_SCAN_INCLUDED_ + +#include "Versions.h" + +namespace glslang { + +// Use a global end-of-input character, so no translation is needed across +// layers of encapsulation. Characters are all 8 bit, and positive, so there is +// no aliasing of character 255 onto -1, for example. +const int EndOfInput = -1; + +// +// A character scanner that seamlessly, on read-only strings, reads across an +// array of strings without assuming null termination. +// +class TInputScanner { +public: + TInputScanner(int n, const char* const s[], size_t L[], const char* const* names = nullptr, + int b = 0, int f = 0, bool single = false) : + numSources(n), + // up to this point, common usage is "char*", but now we need positive 8-bit characters + sources(reinterpret_cast(s)), + lengths(L), currentSource(0), currentChar(0), stringBias(b), finale(f), singleLogical(single), + endOfFileReached(false) + { + loc = new TSourceLoc[numSources]; + for (int i = 0; i < numSources; ++i) { + loc[i].init(i - stringBias); + } + if (names != nullptr) { + for (int i = 0; i < numSources; ++i) + loc[i].name = names[i] != nullptr ? NewPoolTString(names[i]) : nullptr; + } + loc[currentSource].line = 1; + logicalSourceLoc.init(1); + logicalSourceLoc.name = loc[0].name; + } + + virtual ~TInputScanner() + { + delete [] loc; + } + + // retrieve the next character and advance one character + int get() + { + int ret = peek(); + if (ret == EndOfInput) + return ret; + ++loc[currentSource].column; + ++logicalSourceLoc.column; + if (ret == '\n') { + ++loc[currentSource].line; + ++logicalSourceLoc.line; + logicalSourceLoc.column = 0; + loc[currentSource].column = 0; + } + advance(); + + return ret; + } + + // retrieve the next character, no advance + int peek() + { + if (currentSource >= numSources) { + endOfFileReached = true; + return EndOfInput; + } + // Make sure we do not read off the end of a string. + // N.B. Sources can have a length of 0. + int sourceToRead = currentSource; + size_t charToRead = currentChar; + while(charToRead >= lengths[sourceToRead]) { + charToRead = 0; + sourceToRead += 1; + if (sourceToRead >= numSources) { + return EndOfInput; + } + } + + // Here, we care about making negative valued characters positive + return sources[sourceToRead][charToRead]; + } + + // go back one character + void unget() + { + // Do not roll back once we've reached the end of the file. + if (endOfFileReached) + return; + + if (currentChar > 0) { + --currentChar; + --loc[currentSource].column; + --logicalSourceLoc.column; + if (loc[currentSource].column < 0) { + // We've moved back past a new line. Find the + // previous newline (or start of the file) to compute + // the column count on the now current line. + size_t chIndex = currentChar; + while (chIndex > 0) { + if (sources[currentSource][chIndex] == '\n') { + break; + } + --chIndex; + } + logicalSourceLoc.column = (int)(currentChar - chIndex); + loc[currentSource].column = (int)(currentChar - chIndex); + } + } else { + do { + --currentSource; + } while (currentSource > 0 && lengths[currentSource] == 0); + if (lengths[currentSource] == 0) { + // set to 0 if we've backed up to the start of an empty string + currentChar = 0; + } else + currentChar = lengths[currentSource] - 1; + } + if (peek() == '\n') { + --loc[currentSource].line; + --logicalSourceLoc.line; + } + } + + // for #line override + void setLine(int newLine) + { + logicalSourceLoc.line = newLine; + loc[getLastValidSourceIndex()].line = newLine; + } + + // for #line override in filename based parsing + void setFile(const char* filename) + { + TString* fn_tstr = NewPoolTString(filename); + logicalSourceLoc.name = fn_tstr; + loc[getLastValidSourceIndex()].name = fn_tstr; + } + + void setFile(const char* filename, int i) + { + TString* fn_tstr = NewPoolTString(filename); + if (i == getLastValidSourceIndex()) { + logicalSourceLoc.name = fn_tstr; + } + loc[i].name = fn_tstr; + } + + void setString(int newString) + { + logicalSourceLoc.string = newString; + loc[getLastValidSourceIndex()].string = newString; + logicalSourceLoc.name = nullptr; + loc[getLastValidSourceIndex()].name = nullptr; + } + + // for #include content indentation + void setColumn(int col) + { + logicalSourceLoc.column = col; + loc[getLastValidSourceIndex()].column = col; + } + + void setEndOfInput() + { + endOfFileReached = true; + currentSource = numSources; + } + + bool atEndOfInput() const { return endOfFileReached; } + + const TSourceLoc& getSourceLoc() const + { + if (singleLogical) { + return logicalSourceLoc; + } else { + return loc[std::max(0, std::min(currentSource, numSources - finale - 1))]; + } + } + // Returns the index (starting from 0) of the most recent valid source string we are reading from. + int getLastValidSourceIndex() const { return std::min(currentSource, numSources - 1); } + + void consumeWhiteSpace(bool& foundNonSpaceTab); + bool consumeComment(); + void consumeWhitespaceComment(bool& foundNonSpaceTab); + bool scanVersion(int& version, EProfile& profile, bool& notFirstToken); + +protected: + + // advance one character + void advance() + { + ++currentChar; + if (currentChar >= lengths[currentSource]) { + ++currentSource; + if (currentSource < numSources) { + loc[currentSource].string = loc[currentSource - 1].string + 1; + loc[currentSource].line = 1; + loc[currentSource].column = 0; + } + while (currentSource < numSources && lengths[currentSource] == 0) { + ++currentSource; + if (currentSource < numSources) { + loc[currentSource].string = loc[currentSource - 1].string + 1; + loc[currentSource].line = 1; + loc[currentSource].column = 0; + } + } + currentChar = 0; + } + } + + int numSources; // number of strings in source + const unsigned char* const *sources; // array of strings; must be converted to positive values on use, to avoid aliasing with -1 as EndOfInput + const size_t *lengths; // length of each string + int currentSource; + size_t currentChar; + + // This is for reporting what string/line an error occurred on, and can be overridden by #line. + // It remembers the last state of each source string as it is left for the next one, so unget() + // can restore that state. + TSourceLoc* loc; // an array + + int stringBias; // the first string that is the user's string number 0 + int finale; // number of internal strings after user's last string + + TSourceLoc logicalSourceLoc; + bool singleLogical; // treats the strings as a single logical string. + // locations will be reported from the first string. + + // Set to true once peek() returns EndOfFile, so that we won't roll back + // once we've reached EndOfFile. + bool endOfFileReached; +}; + +} // end namespace glslang + +#endif // _GLSLANG_SCAN_INCLUDED_ diff --git a/mac/include/glslang/MachineIndependent/ScanContext.h b/mac/include/glslang/MachineIndependent/ScanContext.h new file mode 100644 index 00000000..74b2b3c7 --- /dev/null +++ b/mac/include/glslang/MachineIndependent/ScanContext.h @@ -0,0 +1,93 @@ +// +// Copyright (C) 2013 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +// +// This holds context specific to the GLSL scanner, which +// sits between the preprocessor scanner and parser. +// + +#pragma once + +#include "ParseHelper.h" + +namespace glslang { + +class TPpContext; +class TPpToken; +class TParserToken; + +class TScanContext { +public: + explicit TScanContext(TParseContextBase& pc) : + parseContext(pc), + afterType(false), afterStruct(false), + field(false), afterBuffer(false) { } + virtual ~TScanContext() { } + + static void fillInKeywordMap(); + static void deleteKeywordMap(); + + int tokenize(TPpContext*, TParserToken&); + +protected: + TScanContext(TScanContext&); + TScanContext& operator=(TScanContext&); + + int tokenizeIdentifier(); + int identifierOrType(); + int reservedWord(); + int identifierOrReserved(bool reserved); + int es30ReservedFromGLSL(int version); + int nonreservedKeyword(int esVersion, int nonEsVersion); + int precisionKeyword(); + int matNxM(); + int dMat(); + int firstGenerationImage(bool inEs310); + int secondGenerationImage(); + + TParseContextBase& parseContext; + bool afterType; // true if we've recognized a type, so can only be looking for an identifier + bool afterStruct; // true if we've recognized the STRUCT keyword, so can only be looking for an identifier + bool field; // true if we're on a field, right after a '.' + bool afterBuffer; // true if we've recognized the BUFFER keyword + TSourceLoc loc; + TParserToken* parserToken; + TPpToken* ppToken; + + const char* tokenText; + int keyword; +}; + +} // end namespace glslang diff --git a/mac/include/glslang/MachineIndependent/SymbolTable.h b/mac/include/glslang/MachineIndependent/SymbolTable.h new file mode 100644 index 00000000..40ca3da5 --- /dev/null +++ b/mac/include/glslang/MachineIndependent/SymbolTable.h @@ -0,0 +1,885 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _SYMBOL_TABLE_INCLUDED_ +#define _SYMBOL_TABLE_INCLUDED_ + +// +// Symbol table for parsing. Has these design characteristics: +// +// * Same symbol table can be used to compile many shaders, to preserve +// effort of creating and loading with the large numbers of built-in +// symbols. +// +// --> This requires a copy mechanism, so initial pools used to create +// the shared information can be popped. Done through "clone" +// methods. +// +// * Name mangling will be used to give each function a unique name +// so that symbol table lookups are never ambiguous. This allows +// a simpler symbol table structure. +// +// * Pushing and popping of scope, so symbol table will really be a stack +// of symbol tables. Searched from the top, with new inserts going into +// the top. +// +// * Constants: Compile time constant symbols will keep their values +// in the symbol table. The parser can substitute constants at parse +// time, including doing constant folding and constant propagation. +// +// * No temporaries: Temporaries made from operations (+, --, .xy, etc.) +// are tracked in the intermediate representation, not the symbol table. +// + +#include "../Include/Common.h" +#include "../Include/intermediate.h" +#include "../Include/InfoSink.h" + +namespace glslang { + +// +// Symbol base class. (Can build functions or variables out of these...) +// + +class TVariable; +class TFunction; +class TAnonMember; + +typedef TVector TExtensionList; + +class TSymbol { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + explicit TSymbol(const TString *n) : name(n), extensions(0), writable(true) { } + virtual TSymbol* clone() const = 0; + virtual ~TSymbol() { } // rely on all symbol owned memory coming from the pool + + virtual const TString& getName() const { return *name; } + virtual void changeName(const TString* newName) { name = newName; } + virtual void addPrefix(const char* prefix) + { + TString newName(prefix); + newName.append(*name); + changeName(NewPoolTString(newName.c_str())); + } + virtual const TString& getMangledName() const { return getName(); } + virtual TFunction* getAsFunction() { return 0; } + virtual const TFunction* getAsFunction() const { return 0; } + virtual TVariable* getAsVariable() { return 0; } + virtual const TVariable* getAsVariable() const { return 0; } + virtual const TAnonMember* getAsAnonMember() const { return 0; } + virtual const TType& getType() const = 0; + virtual TType& getWritableType() = 0; + virtual void setUniqueId(int id) { uniqueId = id; } + virtual int getUniqueId() const { return uniqueId; } + virtual void setExtensions(int numExts, const char* const exts[]) + { + assert(extensions == 0); + assert(numExts > 0); + extensions = NewPoolObject(extensions); + for (int e = 0; e < numExts; ++e) + extensions->push_back(exts[e]); + } + virtual int getNumExtensions() const { return extensions == nullptr ? 0 : (int)extensions->size(); } + virtual const char** getExtensions() const { return extensions->data(); } + +#ifndef GLSLANG_WEB + virtual void dump(TInfoSink& infoSink, bool complete = false) const = 0; + void dumpExtensions(TInfoSink& infoSink) const; +#endif + + virtual bool isReadOnly() const { return ! writable; } + virtual void makeReadOnly() { writable = false; } + +protected: + explicit TSymbol(const TSymbol&); + TSymbol& operator=(const TSymbol&); + + const TString *name; + unsigned int uniqueId; // For cross-scope comparing during code generation + + // For tracking what extensions must be present + // (don't use if correct version/profile is present). + TExtensionList* extensions; // an array of pointers to existing constant char strings + + // + // N.B.: Non-const functions that will be generally used should assert on this, + // to avoid overwriting shared symbol-table information. + // + bool writable; +}; + +// +// Variable class, meaning a symbol that's not a function. +// +// There could be a separate class hierarchy for Constant variables; +// Only one of int, bool, or float, (or none) is correct for +// any particular use, but it's easy to do this way, and doesn't +// seem worth having separate classes, and "getConst" can't simply return +// different values for different types polymorphically, so this is +// just simple and pragmatic. +// +class TVariable : public TSymbol { +public: + TVariable(const TString *name, const TType& t, bool uT = false ) + : TSymbol(name), + userType(uT), + constSubtree(nullptr), + memberExtensions(nullptr), + anonId(-1) + { type.shallowCopy(t); } + virtual TVariable* clone() const; + virtual ~TVariable() { } + + virtual TVariable* getAsVariable() { return this; } + virtual const TVariable* getAsVariable() const { return this; } + virtual const TType& getType() const { return type; } + virtual TType& getWritableType() { assert(writable); return type; } + virtual bool isUserType() const { return userType; } + virtual const TConstUnionArray& getConstArray() const { return constArray; } + virtual TConstUnionArray& getWritableConstArray() { assert(writable); return constArray; } + virtual void setConstArray(const TConstUnionArray& array) { constArray = array; } + virtual void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; } + virtual TIntermTyped* getConstSubtree() const { return constSubtree; } + virtual void setAnonId(int i) { anonId = i; } + virtual int getAnonId() const { return anonId; } + + virtual void setMemberExtensions(int member, int numExts, const char* const exts[]) + { + assert(type.isStruct()); + assert(numExts > 0); + if (memberExtensions == nullptr) { + memberExtensions = NewPoolObject(memberExtensions); + memberExtensions->resize(type.getStruct()->size()); + } + for (int e = 0; e < numExts; ++e) + (*memberExtensions)[member].push_back(exts[e]); + } + virtual bool hasMemberExtensions() const { return memberExtensions != nullptr; } + virtual int getNumMemberExtensions(int member) const + { + return memberExtensions == nullptr ? 0 : (int)(*memberExtensions)[member].size(); + } + virtual const char** getMemberExtensions(int member) const { return (*memberExtensions)[member].data(); } + +#ifndef GLSLANG_WEB + virtual void dump(TInfoSink& infoSink, bool complete = false) const; +#endif + +protected: + explicit TVariable(const TVariable&); + TVariable& operator=(const TVariable&); + + TType type; + bool userType; + + // we are assuming that Pool Allocator will free the memory allocated to unionArray + // when this object is destroyed + + TConstUnionArray constArray; // for compile-time constant value + TIntermTyped* constSubtree; // for specialization constant computation + TVector* memberExtensions; // per-member extension list, allocated only when needed + int anonId; // the ID used for anonymous blocks: TODO: see if uniqueId could serve a dual purpose +}; + +// +// The function sub-class of symbols and the parser will need to +// share this definition of a function parameter. +// +struct TParameter { + TString *name; + TType* type; + TIntermTyped* defaultValue; + void copyParam(const TParameter& param) + { + if (param.name) + name = NewPoolTString(param.name->c_str()); + else + name = 0; + type = param.type->clone(); + defaultValue = param.defaultValue; + } + TBuiltInVariable getDeclaredBuiltIn() const { return type->getQualifier().declaredBuiltIn; } +}; + +// +// The function sub-class of a symbol. +// +class TFunction : public TSymbol { +public: + explicit TFunction(TOperator o) : + TSymbol(0), + op(o), + defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0) { } + TFunction(const TString *name, const TType& retType, TOperator tOp = EOpNull) : + TSymbol(name), + mangledName(*name + '('), + op(tOp), + defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0) + { + returnType.shallowCopy(retType); + declaredBuiltIn = retType.getQualifier().builtIn; + } + virtual TFunction* clone() const override; + virtual ~TFunction(); + + virtual TFunction* getAsFunction() override { return this; } + virtual const TFunction* getAsFunction() const override { return this; } + + // Install 'p' as the (non-'this') last parameter. + // Non-'this' parameters are reflected in both the list of parameters and the + // mangled name. + virtual void addParameter(TParameter& p) + { + assert(writable); + parameters.push_back(p); + p.type->appendMangledName(mangledName); + + if (p.defaultValue != nullptr) + defaultParamCount++; + } + + // Install 'this' as the first parameter. + // 'this' is reflected in the list of parameters, but not the mangled name. + virtual void addThisParameter(TType& type, const char* name) + { + TParameter p = { NewPoolTString(name), new TType, nullptr }; + p.type->shallowCopy(type); + parameters.insert(parameters.begin(), p); + } + + virtual void addPrefix(const char* prefix) override + { + TSymbol::addPrefix(prefix); + mangledName.insert(0, prefix); + } + + virtual void removePrefix(const TString& prefix) + { + assert(mangledName.compare(0, prefix.size(), prefix) == 0); + mangledName.erase(0, prefix.size()); + } + + virtual const TString& getMangledName() const override { return mangledName; } + virtual const TType& getType() const override { return returnType; } + virtual TBuiltInVariable getDeclaredBuiltInType() const { return declaredBuiltIn; } + virtual TType& getWritableType() override { return returnType; } + virtual void relateToOperator(TOperator o) { assert(writable); op = o; } + virtual TOperator getBuiltInOp() const { return op; } + virtual void setDefined() { assert(writable); defined = true; } + virtual bool isDefined() const { return defined; } + virtual void setPrototyped() { assert(writable); prototyped = true; } + virtual bool isPrototyped() const { return prototyped; } + virtual void setImplicitThis() { assert(writable); implicitThis = true; } + virtual bool hasImplicitThis() const { return implicitThis; } + virtual void setIllegalImplicitThis() { assert(writable); illegalImplicitThis = true; } + virtual bool hasIllegalImplicitThis() const { return illegalImplicitThis; } + + // Return total number of parameters + virtual int getParamCount() const { return static_cast(parameters.size()); } + // Return number of parameters with default values. + virtual int getDefaultParamCount() const { return defaultParamCount; } + // Return number of fixed parameters (without default values) + virtual int getFixedParamCount() const { return getParamCount() - getDefaultParamCount(); } + + virtual TParameter& operator[](int i) { assert(writable); return parameters[i]; } + virtual const TParameter& operator[](int i) const { return parameters[i]; } + +#ifndef GLSLANG_WEB + virtual void dump(TInfoSink& infoSink, bool complete = false) const override; +#endif + +protected: + explicit TFunction(const TFunction&); + TFunction& operator=(const TFunction&); + + typedef TVector TParamList; + TParamList parameters; + TType returnType; + TBuiltInVariable declaredBuiltIn; + + TString mangledName; + TOperator op; + bool defined; + bool prototyped; + bool implicitThis; // True if this function is allowed to see all members of 'this' + bool illegalImplicitThis; // True if this function is not supposed to have access to dynamic members of 'this', + // even if it finds member variables in the symbol table. + // This is important for a static member function that has member variables in scope, + // but is not allowed to use them, or see hidden symbols instead. + int defaultParamCount; +}; + +// +// Members of anonymous blocks are a kind of TSymbol. They are not hidden in +// the symbol table behind a container; rather they are visible and point to +// their anonymous container. (The anonymous container is found through the +// member, not the other way around.) +// +class TAnonMember : public TSymbol { +public: + TAnonMember(const TString* n, unsigned int m, TVariable& a, int an) : TSymbol(n), anonContainer(a), memberNumber(m), anonId(an) { } + virtual TAnonMember* clone() const override; + virtual ~TAnonMember() { } + + virtual const TAnonMember* getAsAnonMember() const override { return this; } + virtual const TVariable& getAnonContainer() const { return anonContainer; } + virtual unsigned int getMemberNumber() const { return memberNumber; } + + virtual const TType& getType() const override + { + const TTypeList& types = *anonContainer.getType().getStruct(); + return *types[memberNumber].type; + } + + virtual TType& getWritableType() override + { + assert(writable); + const TTypeList& types = *anonContainer.getType().getStruct(); + return *types[memberNumber].type; + } + + virtual void setExtensions(int numExts, const char* const exts[]) override + { + anonContainer.setMemberExtensions(memberNumber, numExts, exts); + } + virtual int getNumExtensions() const override { return anonContainer.getNumMemberExtensions(memberNumber); } + virtual const char** getExtensions() const override { return anonContainer.getMemberExtensions(memberNumber); } + + virtual int getAnonId() const { return anonId; } +#ifndef GLSLANG_WEB + virtual void dump(TInfoSink& infoSink, bool complete = false) const override; +#endif + +protected: + explicit TAnonMember(const TAnonMember&); + TAnonMember& operator=(const TAnonMember&); + + TVariable& anonContainer; + unsigned int memberNumber; + int anonId; +}; + +class TSymbolTableLevel { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + TSymbolTableLevel() : defaultPrecision(0), anonId(0), thisLevel(false) { } + ~TSymbolTableLevel(); + + bool insert(TSymbol& symbol, bool separateNameSpaces) + { + // + // returning true means symbol was added to the table with no semantic errors + // + const TString& name = symbol.getName(); + if (name == "") { + symbol.getAsVariable()->setAnonId(anonId++); + // An empty name means an anonymous container, exposing its members to the external scope. + // Give it a name and insert its members in the symbol table, pointing to the container. + char buf[20]; + snprintf(buf, 20, "%s%d", AnonymousPrefix, symbol.getAsVariable()->getAnonId()); + symbol.changeName(NewPoolTString(buf)); + + return insertAnonymousMembers(symbol, 0); + } else { + // Check for redefinition errors: + // - STL itself will tell us if there is a direct name collision, with name mangling, at this level + // - additionally, check for function-redefining-variable name collisions + const TString& insertName = symbol.getMangledName(); + if (symbol.getAsFunction()) { + // make sure there isn't a variable of this name + if (! separateNameSpaces && level.find(name) != level.end()) + return false; + + // insert, and whatever happens is okay + level.insert(tLevelPair(insertName, &symbol)); + + return true; + } else + return level.insert(tLevelPair(insertName, &symbol)).second; + } + } + + // Add more members to an already inserted aggregate object + bool amend(TSymbol& symbol, int firstNewMember) + { + // See insert() for comments on basic explanation of insert. + // This operates similarly, but more simply. + // Only supporting amend of anonymous blocks so far. + if (IsAnonymous(symbol.getName())) + return insertAnonymousMembers(symbol, firstNewMember); + else + return false; + } + + bool insertAnonymousMembers(TSymbol& symbol, int firstMember) + { + const TTypeList& types = *symbol.getAsVariable()->getType().getStruct(); + for (unsigned int m = firstMember; m < types.size(); ++m) { + TAnonMember* member = new TAnonMember(&types[m].type->getFieldName(), m, *symbol.getAsVariable(), symbol.getAsVariable()->getAnonId()); + if (! level.insert(tLevelPair(member->getMangledName(), member)).second) + return false; + } + + return true; + } + + TSymbol* find(const TString& name) const + { + tLevel::const_iterator it = level.find(name); + if (it == level.end()) + return 0; + else + return (*it).second; + } + + void findFunctionNameList(const TString& name, TVector& list) + { + size_t parenAt = name.find_first_of('('); + TString base(name, 0, parenAt + 1); + + tLevel::const_iterator begin = level.lower_bound(base); + base[parenAt] = ')'; // assume ')' is lexically after '(' + tLevel::const_iterator end = level.upper_bound(base); + for (tLevel::const_iterator it = begin; it != end; ++it) + list.push_back(it->second->getAsFunction()); + } + + // See if there is already a function in the table having the given non-function-style name. + bool hasFunctionName(const TString& name) const + { + tLevel::const_iterator candidate = level.lower_bound(name); + if (candidate != level.end()) { + const TString& candidateName = (*candidate).first; + TString::size_type parenAt = candidateName.find_first_of('('); + if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0) + + return true; + } + + return false; + } + + // See if there is a variable at this level having the given non-function-style name. + // Return true if name is found, and set variable to true if the name was a variable. + bool findFunctionVariableName(const TString& name, bool& variable) const + { + tLevel::const_iterator candidate = level.lower_bound(name); + if (candidate != level.end()) { + const TString& candidateName = (*candidate).first; + TString::size_type parenAt = candidateName.find_first_of('('); + if (parenAt == candidateName.npos) { + // not a mangled name + if (candidateName == name) { + // found a variable name match + variable = true; + return true; + } + } else { + // a mangled name + if (candidateName.compare(0, parenAt, name) == 0) { + // found a function name match + variable = false; + return true; + } + } + } + + return false; + } + + // Use this to do a lazy 'push' of precision defaults the first time + // a precision statement is seen in a new scope. Leave it at 0 for + // when no push was needed. Thus, it is not the current defaults, + // it is what to restore the defaults to when popping a level. + void setPreviousDefaultPrecisions(const TPrecisionQualifier *p) + { + // can call multiple times at one scope, will only latch on first call, + // as we're tracking the previous scope's values, not the current values + if (defaultPrecision != 0) + return; + + defaultPrecision = new TPrecisionQualifier[EbtNumTypes]; + for (int t = 0; t < EbtNumTypes; ++t) + defaultPrecision[t] = p[t]; + } + + void getPreviousDefaultPrecisions(TPrecisionQualifier *p) + { + // can be called for table level pops that didn't set the + // defaults + if (defaultPrecision == 0 || p == 0) + return; + + for (int t = 0; t < EbtNumTypes; ++t) + p[t] = defaultPrecision[t]; + } + + void relateToOperator(const char* name, TOperator op); + void setFunctionExtensions(const char* name, int num, const char* const extensions[]); +#ifndef GLSLANG_WEB + void dump(TInfoSink& infoSink, bool complete = false) const; +#endif + TSymbolTableLevel* clone() const; + void readOnly(); + + void setThisLevel() { thisLevel = true; } + bool isThisLevel() const { return thisLevel; } + +protected: + explicit TSymbolTableLevel(TSymbolTableLevel&); + TSymbolTableLevel& operator=(TSymbolTableLevel&); + + typedef std::map, pool_allocator > > tLevel; + typedef const tLevel::value_type tLevelPair; + typedef std::pair tInsertResult; + + tLevel level; // named mappings + TPrecisionQualifier *defaultPrecision; + int anonId; + bool thisLevel; // True if this level of the symbol table is a structure scope containing member function + // that are supposed to see anonymous access to member variables. +}; + +class TSymbolTable { +public: + TSymbolTable() : uniqueId(0), noBuiltInRedeclarations(false), separateNameSpaces(false), adoptedLevels(0) + { + // + // This symbol table cannot be used until push() is called. + // + } + ~TSymbolTable() + { + // this can be called explicitly; safest to code it so it can be called multiple times + + // don't deallocate levels passed in from elsewhere + while (table.size() > adoptedLevels) + pop(0); + } + + void adoptLevels(TSymbolTable& symTable) + { + for (unsigned int level = 0; level < symTable.table.size(); ++level) { + table.push_back(symTable.table[level]); + ++adoptedLevels; + } + uniqueId = symTable.uniqueId; + noBuiltInRedeclarations = symTable.noBuiltInRedeclarations; + separateNameSpaces = symTable.separateNameSpaces; + } + + // + // While level adopting is generic, the methods below enact a the following + // convention for levels: + // 0: common built-ins shared across all stages, all compiles, only one copy for all symbol tables + // 1: per-stage built-ins, shared across all compiles, but a different copy per stage + // 2: built-ins specific to a compile, like resources that are context-dependent, or redeclared built-ins + // 3: user-shader globals + // +protected: + static const int globalLevel = 3; + bool isSharedLevel(int level) { return level <= 1; } // exclude all per-compile levels + bool isBuiltInLevel(int level) { return level <= 2; } // exclude user globals + bool isGlobalLevel(int level) { return level <= globalLevel; } // include user globals +public: + bool isEmpty() { return table.size() == 0; } + bool atBuiltInLevel() { return isBuiltInLevel(currentLevel()); } + bool atGlobalLevel() { return isGlobalLevel(currentLevel()); } + + void setNoBuiltInRedeclarations() { noBuiltInRedeclarations = true; } + void setSeparateNameSpaces() { separateNameSpaces = true; } + + void push() + { + table.push_back(new TSymbolTableLevel); + } + + // Make a new symbol-table level to represent the scope introduced by a structure + // containing member functions, such that the member functions can find anonymous + // references to member variables. + // + // 'thisSymbol' should have a name of "" to trigger anonymous structure-member + // symbol finds. + void pushThis(TSymbol& thisSymbol) + { + assert(thisSymbol.getName().size() == 0); + table.push_back(new TSymbolTableLevel); + table.back()->setThisLevel(); + insert(thisSymbol); + } + + void pop(TPrecisionQualifier *p) + { + table[currentLevel()]->getPreviousDefaultPrecisions(p); + delete table.back(); + table.pop_back(); + } + + // + // Insert a visible symbol into the symbol table so it can + // be found later by name. + // + // Returns false if the was a name collision. + // + bool insert(TSymbol& symbol) + { + symbol.setUniqueId(++uniqueId); + + // make sure there isn't a function of this variable name + if (! separateNameSpaces && ! symbol.getAsFunction() && table[currentLevel()]->hasFunctionName(symbol.getName())) + return false; + + // check for not overloading or redefining a built-in function + if (noBuiltInRedeclarations) { + if (atGlobalLevel() && currentLevel() > 0) { + if (table[0]->hasFunctionName(symbol.getName())) + return false; + if (currentLevel() > 1 && table[1]->hasFunctionName(symbol.getName())) + return false; + } + } + + return table[currentLevel()]->insert(symbol, separateNameSpaces); + } + + // Add more members to an already inserted aggregate object + bool amend(TSymbol& symbol, int firstNewMember) + { + // See insert() for comments on basic explanation of insert. + // This operates similarly, but more simply. + return table[currentLevel()]->amend(symbol, firstNewMember); + } + + // + // To allocate an internal temporary, which will need to be uniquely + // identified by the consumer of the AST, but never need to + // found by doing a symbol table search by name, hence allowed an + // arbitrary name in the symbol with no worry of collision. + // + void makeInternalVariable(TSymbol& symbol) + { + symbol.setUniqueId(++uniqueId); + } + + // + // Copy a variable or anonymous member's structure from a shared level so that + // it can be added (soon after return) to the symbol table where it can be + // modified without impacting other users of the shared table. + // + TSymbol* copyUpDeferredInsert(TSymbol* shared) + { + if (shared->getAsVariable()) { + TSymbol* copy = shared->clone(); + copy->setUniqueId(shared->getUniqueId()); + return copy; + } else { + const TAnonMember* anon = shared->getAsAnonMember(); + assert(anon); + TVariable* container = anon->getAnonContainer().clone(); + container->changeName(NewPoolTString("")); + container->setUniqueId(anon->getAnonContainer().getUniqueId()); + return container; + } + } + + TSymbol* copyUp(TSymbol* shared) + { + TSymbol* copy = copyUpDeferredInsert(shared); + table[globalLevel]->insert(*copy, separateNameSpaces); + if (shared->getAsVariable()) + return copy; + else { + // return the copy of the anonymous member + return table[globalLevel]->find(shared->getName()); + } + } + + // Normal find of a symbol, that can optionally say whether the symbol was found + // at a built-in level or the current top-scope level. + TSymbol* find(const TString& name, bool* builtIn = 0, bool* currentScope = 0, int* thisDepthP = 0) + { + int level = currentLevel(); + TSymbol* symbol; + int thisDepth = 0; + do { + if (table[level]->isThisLevel()) + ++thisDepth; + symbol = table[level]->find(name); + --level; + } while (symbol == nullptr && level >= 0); + level++; + if (builtIn) + *builtIn = isBuiltInLevel(level); + if (currentScope) + *currentScope = isGlobalLevel(currentLevel()) || level == currentLevel(); // consider shared levels as "current scope" WRT user globals + if (thisDepthP != nullptr) { + if (! table[level]->isThisLevel()) + thisDepth = 0; + *thisDepthP = thisDepth; + } + + return symbol; + } + + // Find of a symbol that returns how many layers deep of nested + // structures-with-member-functions ('this' scopes) deep the symbol was + // found in. + TSymbol* find(const TString& name, int& thisDepth) + { + int level = currentLevel(); + TSymbol* symbol; + thisDepth = 0; + do { + if (table[level]->isThisLevel()) + ++thisDepth; + symbol = table[level]->find(name); + --level; + } while (symbol == 0 && level >= 0); + + if (! table[level + 1]->isThisLevel()) + thisDepth = 0; + + return symbol; + } + + bool isFunctionNameVariable(const TString& name) const + { + if (separateNameSpaces) + return false; + + int level = currentLevel(); + do { + bool variable; + bool found = table[level]->findFunctionVariableName(name, variable); + if (found) + return variable; + --level; + } while (level >= 0); + + return false; + } + + void findFunctionNameList(const TString& name, TVector& list, bool& builtIn) + { + // For user levels, return the set found in the first scope with a match + builtIn = false; + int level = currentLevel(); + do { + table[level]->findFunctionNameList(name, list); + --level; + } while (list.empty() && level >= globalLevel); + + if (! list.empty()) + return; + + // Gather across all built-in levels; they don't hide each other + builtIn = true; + do { + table[level]->findFunctionNameList(name, list); + --level; + } while (level >= 0); + } + + void relateToOperator(const char* name, TOperator op) + { + for (unsigned int level = 0; level < table.size(); ++level) + table[level]->relateToOperator(name, op); + } + + void setFunctionExtensions(const char* name, int num, const char* const extensions[]) + { + for (unsigned int level = 0; level < table.size(); ++level) + table[level]->setFunctionExtensions(name, num, extensions); + } + + void setVariableExtensions(const char* name, int numExts, const char* const extensions[]) + { + TSymbol* symbol = find(TString(name)); + if (symbol == nullptr) + return; + + symbol->setExtensions(numExts, extensions); + } + + void setVariableExtensions(const char* blockName, const char* name, int numExts, const char* const extensions[]) + { + TSymbol* symbol = find(TString(blockName)); + if (symbol == nullptr) + return; + TVariable* variable = symbol->getAsVariable(); + assert(variable != nullptr); + + const TTypeList& structure = *variable->getAsVariable()->getType().getStruct(); + for (int member = 0; member < (int)structure.size(); ++member) { + if (structure[member].type->getFieldName().compare(name) == 0) { + variable->setMemberExtensions(member, numExts, extensions); + return; + } + } + } + + int getMaxSymbolId() { return uniqueId; } +#ifndef GLSLANG_WEB + void dump(TInfoSink& infoSink, bool complete = false) const; +#endif + void copyTable(const TSymbolTable& copyOf); + + void setPreviousDefaultPrecisions(TPrecisionQualifier *p) { table[currentLevel()]->setPreviousDefaultPrecisions(p); } + + void readOnly() + { + for (unsigned int level = 0; level < table.size(); ++level) + table[level]->readOnly(); + } + +protected: + TSymbolTable(TSymbolTable&); + TSymbolTable& operator=(TSymbolTableLevel&); + + int currentLevel() const { return static_cast(table.size()) - 1; } + + std::vector table; + int uniqueId; // for unique identification in code generation + bool noBuiltInRedeclarations; + bool separateNameSpaces; + unsigned int adoptedLevels; +}; + +} // end namespace glslang + +#endif // _SYMBOL_TABLE_INCLUDED_ diff --git a/mac/include/glslang/MachineIndependent/Versions.h b/mac/include/glslang/MachineIndependent/Versions.h new file mode 100644 index 00000000..98a88e1d --- /dev/null +++ b/mac/include/glslang/MachineIndependent/Versions.h @@ -0,0 +1,327 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 LunarG, Inc. +// Copyright (C) 2017 ARM Limited. +// Copyright (C) 2015-2018 Google, Inc. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +#ifndef _VERSIONS_INCLUDED_ +#define _VERSIONS_INCLUDED_ + +#define LAST_ELEMENT_MARKER(x) x + +// +// Help manage multiple profiles, versions, extensions etc. +// + +// +// Profiles are set up for masking operations, so queries can be done on multiple +// profiles at the same time. +// +// Don't maintain an ordinal set of enums (0,1,2,3...) to avoid all possible +// defects from mixing the two different forms. +// +typedef enum { + EBadProfile = 0, + ENoProfile = (1 << 0), // only for desktop, before profiles showed up + ECoreProfile = (1 << 1), + ECompatibilityProfile = (1 << 2), + EEsProfile = (1 << 3), + LAST_ELEMENT_MARKER(EProfileCount), +} EProfile; + +namespace glslang { + +// +// Map from profile enum to externally readable text name. +// +inline const char* ProfileName(EProfile profile) +{ + switch (profile) { + case ENoProfile: return "none"; + case ECoreProfile: return "core"; + case ECompatibilityProfile: return "compatibility"; + case EEsProfile: return "es"; + default: return "unknown profile"; + } +} + +// +// What source rules, validation rules, target language, etc. are needed or +// desired for SPIR-V? +// +// 0 means a target or rule set is not enabled (ignore rules from that entity). +// Non-0 means to apply semantic rules arising from that version of its rule set. +// The union of all requested rule sets will be applied. +// +struct SpvVersion { + SpvVersion() : spv(0), vulkanGlsl(0), vulkan(0), openGl(0) {} + unsigned int spv; // the version of SPIR-V to target, as defined by "word 1" of the SPIR-V binary header + int vulkanGlsl; // the version of GLSL semantics for Vulkan, from GL_KHR_vulkan_glsl, for "#define VULKAN XXX" + int vulkan; // the version of Vulkan, for which SPIR-V execution environment rules to use + int openGl; // the version of GLSL semantics for OpenGL, from GL_ARB_gl_spirv, for "#define GL_SPIRV XXX" +}; + +// +// The behaviors from the GLSL "#extension extension_name : behavior" +// +typedef enum { + EBhMissing = 0, + EBhRequire, + EBhEnable, + EBhWarn, + EBhDisable, + EBhDisablePartial // use as initial state of an extension that is only partially implemented +} TExtensionBehavior; + +// +// Symbolic names for extensions. Strings may be directly used when calling the +// functions, but better to have the compiler do spelling checks. +// +const char* const E_GL_OES_texture_3D = "GL_OES_texture_3D"; +const char* const E_GL_OES_standard_derivatives = "GL_OES_standard_derivatives"; +const char* const E_GL_EXT_frag_depth = "GL_EXT_frag_depth"; +const char* const E_GL_OES_EGL_image_external = "GL_OES_EGL_image_external"; +const char* const E_GL_OES_EGL_image_external_essl3 = "GL_OES_EGL_image_external_essl3"; +const char* const E_GL_EXT_YUV_target = "GL_EXT_YUV_target"; +const char* const E_GL_EXT_shader_texture_lod = "GL_EXT_shader_texture_lod"; +const char* const E_GL_EXT_shadow_samplers = "GL_EXT_shadow_samplers"; + +const char* const E_GL_ARB_texture_rectangle = "GL_ARB_texture_rectangle"; +const char* const E_GL_3DL_array_objects = "GL_3DL_array_objects"; +const char* const E_GL_ARB_shading_language_420pack = "GL_ARB_shading_language_420pack"; +const char* const E_GL_ARB_texture_gather = "GL_ARB_texture_gather"; +const char* const E_GL_ARB_gpu_shader5 = "GL_ARB_gpu_shader5"; +const char* const E_GL_ARB_separate_shader_objects = "GL_ARB_separate_shader_objects"; +const char* const E_GL_ARB_compute_shader = "GL_ARB_compute_shader"; +const char* const E_GL_ARB_tessellation_shader = "GL_ARB_tessellation_shader"; +const char* const E_GL_ARB_enhanced_layouts = "GL_ARB_enhanced_layouts"; +const char* const E_GL_ARB_texture_cube_map_array = "GL_ARB_texture_cube_map_array"; +const char* const E_GL_ARB_texture_multisample = "GL_ARB_texture_multisample"; +const char* const E_GL_ARB_shader_texture_lod = "GL_ARB_shader_texture_lod"; +const char* const E_GL_ARB_explicit_attrib_location = "GL_ARB_explicit_attrib_location"; +const char* const E_GL_ARB_explicit_uniform_location = "GL_ARB_explicit_uniform_location"; +const char* const E_GL_ARB_shader_image_load_store = "GL_ARB_shader_image_load_store"; +const char* const E_GL_ARB_shader_atomic_counters = "GL_ARB_shader_atomic_counters"; +const char* const E_GL_ARB_shader_draw_parameters = "GL_ARB_shader_draw_parameters"; +const char* const E_GL_ARB_shader_group_vote = "GL_ARB_shader_group_vote"; +const char* const E_GL_ARB_derivative_control = "GL_ARB_derivative_control"; +const char* const E_GL_ARB_shader_texture_image_samples = "GL_ARB_shader_texture_image_samples"; +const char* const E_GL_ARB_viewport_array = "GL_ARB_viewport_array"; +const char* const E_GL_ARB_gpu_shader_int64 = "GL_ARB_gpu_shader_int64"; +const char* const E_GL_ARB_gpu_shader_fp64 = "GL_ARB_gpu_shader_fp64"; +const char* const E_GL_ARB_shader_ballot = "GL_ARB_shader_ballot"; +const char* const E_GL_ARB_sparse_texture2 = "GL_ARB_sparse_texture2"; +const char* const E_GL_ARB_sparse_texture_clamp = "GL_ARB_sparse_texture_clamp"; +const char* const E_GL_ARB_shader_stencil_export = "GL_ARB_shader_stencil_export"; +// const char* const E_GL_ARB_cull_distance = "GL_ARB_cull_distance"; // present for 4.5, but need extension control over block members +const char* const E_GL_ARB_post_depth_coverage = "GL_ARB_post_depth_coverage"; +const char* const E_GL_ARB_shader_viewport_layer_array = "GL_ARB_shader_viewport_layer_array"; +const char* const E_GL_ARB_fragment_shader_interlock = "GL_ARB_fragment_shader_interlock"; +const char* const E_GL_ARB_shader_clock = "GL_ARB_shader_clock"; +const char* const E_GL_ARB_uniform_buffer_object = "GL_ARB_uniform_buffer_object"; +const char* const E_GL_ARB_sample_shading = "GL_ARB_sample_shading"; +const char* const E_GL_ARB_shader_bit_encoding = "GL_ARB_shader_bit_encoding"; +const char* const E_GL_ARB_shader_image_size = "GL_ARB_shader_image_size"; +const char* const E_GL_ARB_shader_storage_buffer_object = "GL_ARB_shader_storage_buffer_object"; +const char* const E_GL_ARB_shading_language_packing = "GL_ARB_shading_language_packing"; +const char* const E_GL_ARB_texture_query_lod = "GL_ARB_texture_query_lod"; + +const char* const E_GL_KHR_shader_subgroup_basic = "GL_KHR_shader_subgroup_basic"; +const char* const E_GL_KHR_shader_subgroup_vote = "GL_KHR_shader_subgroup_vote"; +const char* const E_GL_KHR_shader_subgroup_arithmetic = "GL_KHR_shader_subgroup_arithmetic"; +const char* const E_GL_KHR_shader_subgroup_ballot = "GL_KHR_shader_subgroup_ballot"; +const char* const E_GL_KHR_shader_subgroup_shuffle = "GL_KHR_shader_subgroup_shuffle"; +const char* const E_GL_KHR_shader_subgroup_shuffle_relative = "GL_KHR_shader_subgroup_shuffle_relative"; +const char* const E_GL_KHR_shader_subgroup_clustered = "GL_KHR_shader_subgroup_clustered"; +const char* const E_GL_KHR_shader_subgroup_quad = "GL_KHR_shader_subgroup_quad"; +const char* const E_GL_KHR_memory_scope_semantics = "GL_KHR_memory_scope_semantics"; + +const char* const E_GL_EXT_shader_atomic_int64 = "GL_EXT_shader_atomic_int64"; + +const char* const E_GL_EXT_shader_non_constant_global_initializers = "GL_EXT_shader_non_constant_global_initializers"; +const char* const E_GL_EXT_shader_image_load_formatted = "GL_EXT_shader_image_load_formatted"; + +const char* const E_GL_EXT_shader_16bit_storage = "GL_EXT_shader_16bit_storage"; +const char* const E_GL_EXT_shader_8bit_storage = "GL_EXT_shader_8bit_storage"; + + +// EXT extensions +const char* const E_GL_EXT_device_group = "GL_EXT_device_group"; +const char* const E_GL_EXT_multiview = "GL_EXT_multiview"; +const char* const E_GL_EXT_post_depth_coverage = "GL_EXT_post_depth_coverage"; +const char* const E_GL_EXT_control_flow_attributes = "GL_EXT_control_flow_attributes"; +const char* const E_GL_EXT_nonuniform_qualifier = "GL_EXT_nonuniform_qualifier"; +const char* const E_GL_EXT_samplerless_texture_functions = "GL_EXT_samplerless_texture_functions"; +const char* const E_GL_EXT_scalar_block_layout = "GL_EXT_scalar_block_layout"; +const char* const E_GL_EXT_fragment_invocation_density = "GL_EXT_fragment_invocation_density"; +const char* const E_GL_EXT_buffer_reference = "GL_EXT_buffer_reference"; +const char* const E_GL_EXT_buffer_reference2 = "GL_EXT_buffer_reference2"; +const char* const E_GL_EXT_buffer_reference_uvec2 = "GL_EXT_buffer_reference_uvec2"; +const char* const E_GL_EXT_demote_to_helper_invocation = "GL_EXT_demote_to_helper_invocation"; +const char* const E_GL_EXT_shader_realtime_clock = "GL_EXT_shader_realtime_clock"; +const char* const E_GL_EXT_debug_printf = "GL_EXT_debug_printf"; +const char* const E_GL_EXT_ray_tracing = "GL_EXT_ray_tracing"; +const char* const E_GL_EXT_ray_query = "GL_EXT_ray_query"; +const char* const E_GL_EXT_ray_flags_primitive_culling = "GL_EXT_ray_flags_primitive_culling"; + +// Arrays of extensions for the above viewportEXTs duplications + +const char* const post_depth_coverageEXTs[] = { E_GL_ARB_post_depth_coverage, E_GL_EXT_post_depth_coverage }; +const int Num_post_depth_coverageEXTs = sizeof(post_depth_coverageEXTs) / sizeof(post_depth_coverageEXTs[0]); + +// OVR extensions +const char* const E_GL_OVR_multiview = "GL_OVR_multiview"; +const char* const E_GL_OVR_multiview2 = "GL_OVR_multiview2"; + +const char* const OVR_multiview_EXTs[] = { E_GL_OVR_multiview, E_GL_OVR_multiview2 }; +const int Num_OVR_multiview_EXTs = sizeof(OVR_multiview_EXTs) / sizeof(OVR_multiview_EXTs[0]); + +// #line and #include +const char* const E_GL_GOOGLE_cpp_style_line_directive = "GL_GOOGLE_cpp_style_line_directive"; +const char* const E_GL_GOOGLE_include_directive = "GL_GOOGLE_include_directive"; + +const char* const E_GL_AMD_shader_ballot = "GL_AMD_shader_ballot"; +const char* const E_GL_AMD_shader_trinary_minmax = "GL_AMD_shader_trinary_minmax"; +const char* const E_GL_AMD_shader_explicit_vertex_parameter = "GL_AMD_shader_explicit_vertex_parameter"; +const char* const E_GL_AMD_gcn_shader = "GL_AMD_gcn_shader"; +const char* const E_GL_AMD_gpu_shader_half_float = "GL_AMD_gpu_shader_half_float"; +const char* const E_GL_AMD_texture_gather_bias_lod = "GL_AMD_texture_gather_bias_lod"; +const char* const E_GL_AMD_gpu_shader_int16 = "GL_AMD_gpu_shader_int16"; +const char* const E_GL_AMD_shader_image_load_store_lod = "GL_AMD_shader_image_load_store_lod"; +const char* const E_GL_AMD_shader_fragment_mask = "GL_AMD_shader_fragment_mask"; +const char* const E_GL_AMD_gpu_shader_half_float_fetch = "GL_AMD_gpu_shader_half_float_fetch"; + +const char* const E_GL_INTEL_shader_integer_functions2 = "GL_INTEL_shader_integer_functions2"; + +const char* const E_GL_NV_sample_mask_override_coverage = "GL_NV_sample_mask_override_coverage"; +const char* const E_SPV_NV_geometry_shader_passthrough = "GL_NV_geometry_shader_passthrough"; +const char* const E_GL_NV_viewport_array2 = "GL_NV_viewport_array2"; +const char* const E_GL_NV_stereo_view_rendering = "GL_NV_stereo_view_rendering"; +const char* const E_GL_NVX_multiview_per_view_attributes = "GL_NVX_multiview_per_view_attributes"; +const char* const E_GL_NV_shader_atomic_int64 = "GL_NV_shader_atomic_int64"; +const char* const E_GL_NV_conservative_raster_underestimation = "GL_NV_conservative_raster_underestimation"; +const char* const E_GL_NV_shader_noperspective_interpolation = "GL_NV_shader_noperspective_interpolation"; +const char* const E_GL_NV_shader_subgroup_partitioned = "GL_NV_shader_subgroup_partitioned"; +const char* const E_GL_NV_shading_rate_image = "GL_NV_shading_rate_image"; +const char* const E_GL_NV_ray_tracing = "GL_NV_ray_tracing"; +const char* const E_GL_NV_fragment_shader_barycentric = "GL_NV_fragment_shader_barycentric"; +const char* const E_GL_NV_compute_shader_derivatives = "GL_NV_compute_shader_derivatives"; +const char* const E_GL_NV_shader_texture_footprint = "GL_NV_shader_texture_footprint"; +const char* const E_GL_NV_mesh_shader = "GL_NV_mesh_shader"; + +// Arrays of extensions for the above viewportEXTs duplications + +const char* const viewportEXTs[] = { E_GL_ARB_shader_viewport_layer_array, E_GL_NV_viewport_array2 }; +const int Num_viewportEXTs = sizeof(viewportEXTs) / sizeof(viewportEXTs[0]); + +const char* const E_GL_NV_cooperative_matrix = "GL_NV_cooperative_matrix"; +const char* const E_GL_NV_shader_sm_builtins = "GL_NV_shader_sm_builtins"; +const char* const E_GL_NV_integer_cooperative_matrix = "GL_NV_integer_cooperative_matrix"; + +// AEP +const char* const E_GL_ANDROID_extension_pack_es31a = "GL_ANDROID_extension_pack_es31a"; +const char* const E_GL_KHR_blend_equation_advanced = "GL_KHR_blend_equation_advanced"; +const char* const E_GL_OES_sample_variables = "GL_OES_sample_variables"; +const char* const E_GL_OES_shader_image_atomic = "GL_OES_shader_image_atomic"; +const char* const E_GL_OES_shader_multisample_interpolation = "GL_OES_shader_multisample_interpolation"; +const char* const E_GL_OES_texture_storage_multisample_2d_array = "GL_OES_texture_storage_multisample_2d_array"; +const char* const E_GL_EXT_geometry_shader = "GL_EXT_geometry_shader"; +const char* const E_GL_EXT_geometry_point_size = "GL_EXT_geometry_point_size"; +const char* const E_GL_EXT_gpu_shader5 = "GL_EXT_gpu_shader5"; +const char* const E_GL_EXT_primitive_bounding_box = "GL_EXT_primitive_bounding_box"; +const char* const E_GL_EXT_shader_io_blocks = "GL_EXT_shader_io_blocks"; +const char* const E_GL_EXT_tessellation_shader = "GL_EXT_tessellation_shader"; +const char* const E_GL_EXT_tessellation_point_size = "GL_EXT_tessellation_point_size"; +const char* const E_GL_EXT_texture_buffer = "GL_EXT_texture_buffer"; +const char* const E_GL_EXT_texture_cube_map_array = "GL_EXT_texture_cube_map_array"; + +// OES matching AEP +const char* const E_GL_OES_geometry_shader = "GL_OES_geometry_shader"; +const char* const E_GL_OES_geometry_point_size = "GL_OES_geometry_point_size"; +const char* const E_GL_OES_gpu_shader5 = "GL_OES_gpu_shader5"; +const char* const E_GL_OES_primitive_bounding_box = "GL_OES_primitive_bounding_box"; +const char* const E_GL_OES_shader_io_blocks = "GL_OES_shader_io_blocks"; +const char* const E_GL_OES_tessellation_shader = "GL_OES_tessellation_shader"; +const char* const E_GL_OES_tessellation_point_size = "GL_OES_tessellation_point_size"; +const char* const E_GL_OES_texture_buffer = "GL_OES_texture_buffer"; +const char* const E_GL_OES_texture_cube_map_array = "GL_OES_texture_cube_map_array"; + +// EXT +const char* const E_GL_EXT_shader_explicit_arithmetic_types = "GL_EXT_shader_explicit_arithmetic_types"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_int8 = "GL_EXT_shader_explicit_arithmetic_types_int8"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_int16 = "GL_EXT_shader_explicit_arithmetic_types_int16"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_int32 = "GL_EXT_shader_explicit_arithmetic_types_int32"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_int64 = "GL_EXT_shader_explicit_arithmetic_types_int64"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_float16 = "GL_EXT_shader_explicit_arithmetic_types_float16"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_float32 = "GL_EXT_shader_explicit_arithmetic_types_float32"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_float64 = "GL_EXT_shader_explicit_arithmetic_types_float64"; + +const char* const E_GL_EXT_shader_subgroup_extended_types_int8 = "GL_EXT_shader_subgroup_extended_types_int8"; +const char* const E_GL_EXT_shader_subgroup_extended_types_int16 = "GL_EXT_shader_subgroup_extended_types_int16"; +const char* const E_GL_EXT_shader_subgroup_extended_types_int64 = "GL_EXT_shader_subgroup_extended_types_int64"; +const char* const E_GL_EXT_shader_subgroup_extended_types_float16 = "GL_EXT_shader_subgroup_extended_types_float16"; + +// Arrays of extensions for the above AEP duplications + +const char* const AEP_geometry_shader[] = { E_GL_EXT_geometry_shader, E_GL_OES_geometry_shader }; +const int Num_AEP_geometry_shader = sizeof(AEP_geometry_shader)/sizeof(AEP_geometry_shader[0]); + +const char* const AEP_geometry_point_size[] = { E_GL_EXT_geometry_point_size, E_GL_OES_geometry_point_size }; +const int Num_AEP_geometry_point_size = sizeof(AEP_geometry_point_size)/sizeof(AEP_geometry_point_size[0]); + +const char* const AEP_gpu_shader5[] = { E_GL_EXT_gpu_shader5, E_GL_OES_gpu_shader5 }; +const int Num_AEP_gpu_shader5 = sizeof(AEP_gpu_shader5)/sizeof(AEP_gpu_shader5[0]); + +const char* const AEP_primitive_bounding_box[] = { E_GL_EXT_primitive_bounding_box, E_GL_OES_primitive_bounding_box }; +const int Num_AEP_primitive_bounding_box = sizeof(AEP_primitive_bounding_box)/sizeof(AEP_primitive_bounding_box[0]); + +const char* const AEP_shader_io_blocks[] = { E_GL_EXT_shader_io_blocks, E_GL_OES_shader_io_blocks }; +const int Num_AEP_shader_io_blocks = sizeof(AEP_shader_io_blocks)/sizeof(AEP_shader_io_blocks[0]); + +const char* const AEP_tessellation_shader[] = { E_GL_EXT_tessellation_shader, E_GL_OES_tessellation_shader }; +const int Num_AEP_tessellation_shader = sizeof(AEP_tessellation_shader)/sizeof(AEP_tessellation_shader[0]); + +const char* const AEP_tessellation_point_size[] = { E_GL_EXT_tessellation_point_size, E_GL_OES_tessellation_point_size }; +const int Num_AEP_tessellation_point_size = sizeof(AEP_tessellation_point_size)/sizeof(AEP_tessellation_point_size[0]); + +const char* const AEP_texture_buffer[] = { E_GL_EXT_texture_buffer, E_GL_OES_texture_buffer }; +const int Num_AEP_texture_buffer = sizeof(AEP_texture_buffer)/sizeof(AEP_texture_buffer[0]); + +const char* const AEP_texture_cube_map_array[] = { E_GL_EXT_texture_cube_map_array, E_GL_OES_texture_cube_map_array }; +const int Num_AEP_texture_cube_map_array = sizeof(AEP_texture_cube_map_array)/sizeof(AEP_texture_cube_map_array[0]); + +} // end namespace glslang + +#endif // _VERSIONS_INCLUDED_ diff --git a/mac/include/glslang/MachineIndependent/attribute.h b/mac/include/glslang/MachineIndependent/attribute.h new file mode 100644 index 00000000..38a943d2 --- /dev/null +++ b/mac/include/glslang/MachineIndependent/attribute.h @@ -0,0 +1,149 @@ +// +// Copyright (C) 2017 LunarG, Inc. +// Copyright (C) 2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _ATTRIBUTE_INCLUDED_ +#define _ATTRIBUTE_INCLUDED_ + +#include "../Include/Common.h" +#include "../Include/ConstantUnion.h" + +namespace glslang { + + enum TAttributeType { + EatNone, + EatAllow_uav_condition, + EatBranch, + EatCall, + EatDomain, + EatEarlyDepthStencil, + EatFastOpt, + EatFlatten, + EatForceCase, + EatInstance, + EatMaxTessFactor, + EatNumThreads, + EatMaxVertexCount, + EatOutputControlPoints, + EatOutputTopology, + EatPartitioning, + EatPatchConstantFunc, + EatPatchSize, + EatUnroll, + EatLoop, + EatBinding, + EatGlobalBinding, + EatLocation, + EatInputAttachment, + EatBuiltIn, + EatPushConstant, + EatConstantId, + EatDependencyInfinite, + EatDependencyLength, + EatMinIterations, + EatMaxIterations, + EatIterationMultiple, + EatPeelCount, + EatPartialCount, + EatFormatRgba32f, + EatFormatRgba16f, + EatFormatR32f, + EatFormatRgba8, + EatFormatRgba8Snorm, + EatFormatRg32f, + EatFormatRg16f, + EatFormatR11fG11fB10f, + EatFormatR16f, + EatFormatRgba16, + EatFormatRgb10A2, + EatFormatRg16, + EatFormatRg8, + EatFormatR16, + EatFormatR8, + EatFormatRgba16Snorm, + EatFormatRg16Snorm, + EatFormatRg8Snorm, + EatFormatR16Snorm, + EatFormatR8Snorm, + EatFormatRgba32i, + EatFormatRgba16i, + EatFormatRgba8i, + EatFormatR32i, + EatFormatRg32i, + EatFormatRg16i, + EatFormatRg8i, + EatFormatR16i, + EatFormatR8i, + EatFormatRgba32ui, + EatFormatRgba16ui, + EatFormatRgba8ui, + EatFormatR32ui, + EatFormatRgb10a2ui, + EatFormatRg32ui, + EatFormatRg16ui, + EatFormatRg8ui, + EatFormatR16ui, + EatFormatR8ui, + EatFormatUnknown, + EatNonWritable, + EatNonReadable + }; + + class TIntermAggregate; + + struct TAttributeArgs { + TAttributeType name; + const TIntermAggregate* args; + + // Obtain attribute as integer + // Return false if it cannot be obtained + bool getInt(int& value, int argNum = 0) const; + + // Obtain attribute as string, with optional to-lower transform + // Return false if it cannot be obtained + bool getString(TString& value, int argNum = 0, bool convertToLower = true) const; + + // How many arguments were provided to the attribute? + int size() const; + + protected: + const TConstUnion* getConstUnion(TBasicType basicType, int argNum) const; + }; + + typedef TList TAttributes; + +} // end namespace glslang + +#endif // _ATTRIBUTE_INCLUDED_ diff --git a/mac/include/glslang/MachineIndependent/gl_types.h b/mac/include/glslang/MachineIndependent/gl_types.h new file mode 100644 index 00000000..b6f613bc --- /dev/null +++ b/mac/include/glslang/MachineIndependent/gl_types.h @@ -0,0 +1,210 @@ +/* +** Copyright (c) 2013 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +#pragma once + +#define GL_FLOAT 0x1406 +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 + +#define GL_DOUBLE 0x140A +#define GL_DOUBLE_VEC2 0x8FFC +#define GL_DOUBLE_VEC3 0x8FFD +#define GL_DOUBLE_VEC4 0x8FFE + +#define GL_INT 0x1404 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 + +#define GL_UNSIGNED_INT 0x1405 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 + +#define GL_INT64_ARB 0x140E +#define GL_INT64_VEC2_ARB 0x8FE9 +#define GL_INT64_VEC3_ARB 0x8FEA +#define GL_INT64_VEC4_ARB 0x8FEB + +#define GL_UNSIGNED_INT64_ARB 0x140F +#define GL_UNSIGNED_INT64_VEC2_ARB 0x8FE5 +#define GL_UNSIGNED_INT64_VEC3_ARB 0x8FE6 +#define GL_UNSIGNED_INT64_VEC4_ARB 0x8FE7 + +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 + +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A + +#define GL_DOUBLE_MAT2 0x8F46 +#define GL_DOUBLE_MAT3 0x8F47 +#define GL_DOUBLE_MAT4 0x8F48 +#define GL_DOUBLE_MAT2x3 0x8F49 +#define GL_DOUBLE_MAT2x4 0x8F4A +#define GL_DOUBLE_MAT3x2 0x8F4B +#define GL_DOUBLE_MAT3x4 0x8F4C +#define GL_DOUBLE_MAT4x2 0x8F4D +#define GL_DOUBLE_MAT4x3 0x8F4E + +// Those constants are borrowed from extension NV_gpu_shader5 +#define GL_FLOAT16_NV 0x8FF8 +#define GL_FLOAT16_VEC2_NV 0x8FF9 +#define GL_FLOAT16_VEC3_NV 0x8FFA +#define GL_FLOAT16_VEC4_NV 0x8FFB + +#define GL_FLOAT16_MAT2_AMD 0x91C5 +#define GL_FLOAT16_MAT3_AMD 0x91C6 +#define GL_FLOAT16_MAT4_AMD 0x91C7 +#define GL_FLOAT16_MAT2x3_AMD 0x91C8 +#define GL_FLOAT16_MAT2x4_AMD 0x91C9 +#define GL_FLOAT16_MAT3x2_AMD 0x91CA +#define GL_FLOAT16_MAT3x4_AMD 0x91CB +#define GL_FLOAT16_MAT4x2_AMD 0x91CC +#define GL_FLOAT16_MAT4x3_AMD 0x91CD + +#define GL_SAMPLER_1D 0x8B5D +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_SAMPLER_BUFFER 0x8DC2 +#define GL_SAMPLER_1D_ARRAY 0x8DC0 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_SAMPLER_1D_SHADOW 0x8B61 +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_SAMPLER_2D_RECT 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64 +#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 +#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B +#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D +#define GL_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D + +#define GL_FLOAT16_SAMPLER_1D_AMD 0x91CE +#define GL_FLOAT16_SAMPLER_2D_AMD 0x91CF +#define GL_FLOAT16_SAMPLER_3D_AMD 0x91D0 +#define GL_FLOAT16_SAMPLER_CUBE_AMD 0x91D1 +#define GL_FLOAT16_SAMPLER_2D_RECT_AMD 0x91D2 +#define GL_FLOAT16_SAMPLER_1D_ARRAY_AMD 0x91D3 +#define GL_FLOAT16_SAMPLER_2D_ARRAY_AMD 0x91D4 +#define GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_AMD 0x91D5 +#define GL_FLOAT16_SAMPLER_BUFFER_AMD 0x91D6 +#define GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_AMD 0x91D7 +#define GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_ARRAY_AMD 0x91D8 + +#define GL_FLOAT16_SAMPLER_1D_SHADOW_AMD 0x91D9 +#define GL_FLOAT16_SAMPLER_2D_SHADOW_AMD 0x91DA +#define GL_FLOAT16_SAMPLER_2D_RECT_SHADOW_AMD 0x91DB +#define GL_FLOAT16_SAMPLER_1D_ARRAY_SHADOW_AMD 0x91DC +#define GL_FLOAT16_SAMPLER_2D_ARRAY_SHADOW_AMD 0x91DD +#define GL_FLOAT16_SAMPLER_CUBE_SHADOW_AMD 0x91DE +#define GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_SHADOW_AMD 0x91DF + +#define GL_FLOAT16_IMAGE_1D_AMD 0x91E0 +#define GL_FLOAT16_IMAGE_2D_AMD 0x91E1 +#define GL_FLOAT16_IMAGE_3D_AMD 0x91E2 +#define GL_FLOAT16_IMAGE_2D_RECT_AMD 0x91E3 +#define GL_FLOAT16_IMAGE_CUBE_AMD 0x91E4 +#define GL_FLOAT16_IMAGE_1D_ARRAY_AMD 0x91E5 +#define GL_FLOAT16_IMAGE_2D_ARRAY_AMD 0x91E6 +#define GL_FLOAT16_IMAGE_CUBE_MAP_ARRAY_AMD 0x91E7 +#define GL_FLOAT16_IMAGE_BUFFER_AMD 0x91E8 +#define GL_FLOAT16_IMAGE_2D_MULTISAMPLE_AMD 0x91E9 +#define GL_FLOAT16_IMAGE_2D_MULTISAMPLE_ARRAY_AMD 0x91EA + +#define GL_INT_SAMPLER_1D 0x8DC9 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_INT_SAMPLER_2D_RECT 0x8DCD +#define GL_INT_SAMPLER_BUFFER 0x8DD0 +#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 +#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900E + +#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8 +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900F +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A + +#define GL_IMAGE_1D 0x904C +#define GL_IMAGE_2D 0x904D +#define GL_IMAGE_3D 0x904E +#define GL_IMAGE_2D_RECT 0x904F +#define GL_IMAGE_CUBE 0x9050 +#define GL_IMAGE_BUFFER 0x9051 +#define GL_IMAGE_1D_ARRAY 0x9052 +#define GL_IMAGE_2D_ARRAY 0x9053 +#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054 +#define GL_IMAGE_2D_MULTISAMPLE 0x9055 +#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056 +#define GL_INT_IMAGE_1D 0x9057 +#define GL_INT_IMAGE_2D 0x9058 +#define GL_INT_IMAGE_3D 0x9059 +#define GL_INT_IMAGE_2D_RECT 0x905A +#define GL_INT_IMAGE_CUBE 0x905B +#define GL_INT_IMAGE_BUFFER 0x905C +#define GL_INT_IMAGE_1D_ARRAY 0x905D +#define GL_INT_IMAGE_2D_ARRAY 0x905E +#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F +#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060 +#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061 +#define GL_UNSIGNED_INT_IMAGE_1D 0x9062 +#define GL_UNSIGNED_INT_IMAGE_2D 0x9063 +#define GL_UNSIGNED_INT_IMAGE_3D 0x9064 +#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065 +#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066 +#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067 +#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068 +#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069 +#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C + +#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB diff --git a/mac/include/glslang/MachineIndependent/glslang_tab.cpp.h b/mac/include/glslang/MachineIndependent/glslang_tab.cpp.h new file mode 100644 index 00000000..31c8f902 --- /dev/null +++ b/mac/include/glslang/MachineIndependent/glslang_tab.cpp.h @@ -0,0 +1,521 @@ +/* A Bison parser, made by GNU Bison 3.0.4. */ + +/* Bison interface for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +#ifndef YY_YY_GLSLANG_TAB_CPP_H_INCLUDED +# define YY_YY_GLSLANG_TAB_CPP_H_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 1 +#endif +#if YYDEBUG +extern int yydebug; +#endif + +/* Token type. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + enum yytokentype + { + CONST = 258, + BOOL = 259, + INT = 260, + UINT = 261, + FLOAT = 262, + BVEC2 = 263, + BVEC3 = 264, + BVEC4 = 265, + IVEC2 = 266, + IVEC3 = 267, + IVEC4 = 268, + UVEC2 = 269, + UVEC3 = 270, + UVEC4 = 271, + VEC2 = 272, + VEC3 = 273, + VEC4 = 274, + MAT2 = 275, + MAT3 = 276, + MAT4 = 277, + MAT2X2 = 278, + MAT2X3 = 279, + MAT2X4 = 280, + MAT3X2 = 281, + MAT3X3 = 282, + MAT3X4 = 283, + MAT4X2 = 284, + MAT4X3 = 285, + MAT4X4 = 286, + SAMPLER2D = 287, + SAMPLER3D = 288, + SAMPLERCUBE = 289, + SAMPLER2DSHADOW = 290, + SAMPLERCUBESHADOW = 291, + SAMPLER2DARRAY = 292, + SAMPLER2DARRAYSHADOW = 293, + ISAMPLER2D = 294, + ISAMPLER3D = 295, + ISAMPLERCUBE = 296, + ISAMPLER2DARRAY = 297, + USAMPLER2D = 298, + USAMPLER3D = 299, + USAMPLERCUBE = 300, + USAMPLER2DARRAY = 301, + SAMPLER = 302, + SAMPLERSHADOW = 303, + TEXTURE2D = 304, + TEXTURE3D = 305, + TEXTURECUBE = 306, + TEXTURE2DARRAY = 307, + ITEXTURE2D = 308, + ITEXTURE3D = 309, + ITEXTURECUBE = 310, + ITEXTURE2DARRAY = 311, + UTEXTURE2D = 312, + UTEXTURE3D = 313, + UTEXTURECUBE = 314, + UTEXTURE2DARRAY = 315, + ATTRIBUTE = 316, + VARYING = 317, + FLOAT16_T = 318, + FLOAT32_T = 319, + DOUBLE = 320, + FLOAT64_T = 321, + INT64_T = 322, + UINT64_T = 323, + INT32_T = 324, + UINT32_T = 325, + INT16_T = 326, + UINT16_T = 327, + INT8_T = 328, + UINT8_T = 329, + I64VEC2 = 330, + I64VEC3 = 331, + I64VEC4 = 332, + U64VEC2 = 333, + U64VEC3 = 334, + U64VEC4 = 335, + I32VEC2 = 336, + I32VEC3 = 337, + I32VEC4 = 338, + U32VEC2 = 339, + U32VEC3 = 340, + U32VEC4 = 341, + I16VEC2 = 342, + I16VEC3 = 343, + I16VEC4 = 344, + U16VEC2 = 345, + U16VEC3 = 346, + U16VEC4 = 347, + I8VEC2 = 348, + I8VEC3 = 349, + I8VEC4 = 350, + U8VEC2 = 351, + U8VEC3 = 352, + U8VEC4 = 353, + DVEC2 = 354, + DVEC3 = 355, + DVEC4 = 356, + DMAT2 = 357, + DMAT3 = 358, + DMAT4 = 359, + F16VEC2 = 360, + F16VEC3 = 361, + F16VEC4 = 362, + F16MAT2 = 363, + F16MAT3 = 364, + F16MAT4 = 365, + F32VEC2 = 366, + F32VEC3 = 367, + F32VEC4 = 368, + F32MAT2 = 369, + F32MAT3 = 370, + F32MAT4 = 371, + F64VEC2 = 372, + F64VEC3 = 373, + F64VEC4 = 374, + F64MAT2 = 375, + F64MAT3 = 376, + F64MAT4 = 377, + DMAT2X2 = 378, + DMAT2X3 = 379, + DMAT2X4 = 380, + DMAT3X2 = 381, + DMAT3X3 = 382, + DMAT3X4 = 383, + DMAT4X2 = 384, + DMAT4X3 = 385, + DMAT4X4 = 386, + F16MAT2X2 = 387, + F16MAT2X3 = 388, + F16MAT2X4 = 389, + F16MAT3X2 = 390, + F16MAT3X3 = 391, + F16MAT3X4 = 392, + F16MAT4X2 = 393, + F16MAT4X3 = 394, + F16MAT4X4 = 395, + F32MAT2X2 = 396, + F32MAT2X3 = 397, + F32MAT2X4 = 398, + F32MAT3X2 = 399, + F32MAT3X3 = 400, + F32MAT3X4 = 401, + F32MAT4X2 = 402, + F32MAT4X3 = 403, + F32MAT4X4 = 404, + F64MAT2X2 = 405, + F64MAT2X3 = 406, + F64MAT2X4 = 407, + F64MAT3X2 = 408, + F64MAT3X3 = 409, + F64MAT3X4 = 410, + F64MAT4X2 = 411, + F64MAT4X3 = 412, + F64MAT4X4 = 413, + ATOMIC_UINT = 414, + ACCSTRUCTNV = 415, + ACCSTRUCTEXT = 416, + RAYQUERYEXT = 417, + FCOOPMATNV = 418, + ICOOPMATNV = 419, + UCOOPMATNV = 420, + SAMPLERCUBEARRAY = 421, + SAMPLERCUBEARRAYSHADOW = 422, + ISAMPLERCUBEARRAY = 423, + USAMPLERCUBEARRAY = 424, + SAMPLER1D = 425, + SAMPLER1DARRAY = 426, + SAMPLER1DARRAYSHADOW = 427, + ISAMPLER1D = 428, + SAMPLER1DSHADOW = 429, + SAMPLER2DRECT = 430, + SAMPLER2DRECTSHADOW = 431, + ISAMPLER2DRECT = 432, + USAMPLER2DRECT = 433, + SAMPLERBUFFER = 434, + ISAMPLERBUFFER = 435, + USAMPLERBUFFER = 436, + SAMPLER2DMS = 437, + ISAMPLER2DMS = 438, + USAMPLER2DMS = 439, + SAMPLER2DMSARRAY = 440, + ISAMPLER2DMSARRAY = 441, + USAMPLER2DMSARRAY = 442, + SAMPLEREXTERNALOES = 443, + SAMPLEREXTERNAL2DY2YEXT = 444, + ISAMPLER1DARRAY = 445, + USAMPLER1D = 446, + USAMPLER1DARRAY = 447, + F16SAMPLER1D = 448, + F16SAMPLER2D = 449, + F16SAMPLER3D = 450, + F16SAMPLER2DRECT = 451, + F16SAMPLERCUBE = 452, + F16SAMPLER1DARRAY = 453, + F16SAMPLER2DARRAY = 454, + F16SAMPLERCUBEARRAY = 455, + F16SAMPLERBUFFER = 456, + F16SAMPLER2DMS = 457, + F16SAMPLER2DMSARRAY = 458, + F16SAMPLER1DSHADOW = 459, + F16SAMPLER2DSHADOW = 460, + F16SAMPLER1DARRAYSHADOW = 461, + F16SAMPLER2DARRAYSHADOW = 462, + F16SAMPLER2DRECTSHADOW = 463, + F16SAMPLERCUBESHADOW = 464, + F16SAMPLERCUBEARRAYSHADOW = 465, + IMAGE1D = 466, + IIMAGE1D = 467, + UIMAGE1D = 468, + IMAGE2D = 469, + IIMAGE2D = 470, + UIMAGE2D = 471, + IMAGE3D = 472, + IIMAGE3D = 473, + UIMAGE3D = 474, + IMAGE2DRECT = 475, + IIMAGE2DRECT = 476, + UIMAGE2DRECT = 477, + IMAGECUBE = 478, + IIMAGECUBE = 479, + UIMAGECUBE = 480, + IMAGEBUFFER = 481, + IIMAGEBUFFER = 482, + UIMAGEBUFFER = 483, + IMAGE1DARRAY = 484, + IIMAGE1DARRAY = 485, + UIMAGE1DARRAY = 486, + IMAGE2DARRAY = 487, + IIMAGE2DARRAY = 488, + UIMAGE2DARRAY = 489, + IMAGECUBEARRAY = 490, + IIMAGECUBEARRAY = 491, + UIMAGECUBEARRAY = 492, + IMAGE2DMS = 493, + IIMAGE2DMS = 494, + UIMAGE2DMS = 495, + IMAGE2DMSARRAY = 496, + IIMAGE2DMSARRAY = 497, + UIMAGE2DMSARRAY = 498, + F16IMAGE1D = 499, + F16IMAGE2D = 500, + F16IMAGE3D = 501, + F16IMAGE2DRECT = 502, + F16IMAGECUBE = 503, + F16IMAGE1DARRAY = 504, + F16IMAGE2DARRAY = 505, + F16IMAGECUBEARRAY = 506, + F16IMAGEBUFFER = 507, + F16IMAGE2DMS = 508, + F16IMAGE2DMSARRAY = 509, + TEXTURECUBEARRAY = 510, + ITEXTURECUBEARRAY = 511, + UTEXTURECUBEARRAY = 512, + TEXTURE1D = 513, + ITEXTURE1D = 514, + UTEXTURE1D = 515, + TEXTURE1DARRAY = 516, + ITEXTURE1DARRAY = 517, + UTEXTURE1DARRAY = 518, + TEXTURE2DRECT = 519, + ITEXTURE2DRECT = 520, + UTEXTURE2DRECT = 521, + TEXTUREBUFFER = 522, + ITEXTUREBUFFER = 523, + UTEXTUREBUFFER = 524, + TEXTURE2DMS = 525, + ITEXTURE2DMS = 526, + UTEXTURE2DMS = 527, + TEXTURE2DMSARRAY = 528, + ITEXTURE2DMSARRAY = 529, + UTEXTURE2DMSARRAY = 530, + F16TEXTURE1D = 531, + F16TEXTURE2D = 532, + F16TEXTURE3D = 533, + F16TEXTURE2DRECT = 534, + F16TEXTURECUBE = 535, + F16TEXTURE1DARRAY = 536, + F16TEXTURE2DARRAY = 537, + F16TEXTURECUBEARRAY = 538, + F16TEXTUREBUFFER = 539, + F16TEXTURE2DMS = 540, + F16TEXTURE2DMSARRAY = 541, + SUBPASSINPUT = 542, + SUBPASSINPUTMS = 543, + ISUBPASSINPUT = 544, + ISUBPASSINPUTMS = 545, + USUBPASSINPUT = 546, + USUBPASSINPUTMS = 547, + F16SUBPASSINPUT = 548, + F16SUBPASSINPUTMS = 549, + LEFT_OP = 550, + RIGHT_OP = 551, + INC_OP = 552, + DEC_OP = 553, + LE_OP = 554, + GE_OP = 555, + EQ_OP = 556, + NE_OP = 557, + AND_OP = 558, + OR_OP = 559, + XOR_OP = 560, + MUL_ASSIGN = 561, + DIV_ASSIGN = 562, + ADD_ASSIGN = 563, + MOD_ASSIGN = 564, + LEFT_ASSIGN = 565, + RIGHT_ASSIGN = 566, + AND_ASSIGN = 567, + XOR_ASSIGN = 568, + OR_ASSIGN = 569, + SUB_ASSIGN = 570, + STRING_LITERAL = 571, + LEFT_PAREN = 572, + RIGHT_PAREN = 573, + LEFT_BRACKET = 574, + RIGHT_BRACKET = 575, + LEFT_BRACE = 576, + RIGHT_BRACE = 577, + DOT = 578, + COMMA = 579, + COLON = 580, + EQUAL = 581, + SEMICOLON = 582, + BANG = 583, + DASH = 584, + TILDE = 585, + PLUS = 586, + STAR = 587, + SLASH = 588, + PERCENT = 589, + LEFT_ANGLE = 590, + RIGHT_ANGLE = 591, + VERTICAL_BAR = 592, + CARET = 593, + AMPERSAND = 594, + QUESTION = 595, + INVARIANT = 596, + HIGH_PRECISION = 597, + MEDIUM_PRECISION = 598, + LOW_PRECISION = 599, + PRECISION = 600, + PACKED = 601, + RESOURCE = 602, + SUPERP = 603, + FLOATCONSTANT = 604, + INTCONSTANT = 605, + UINTCONSTANT = 606, + BOOLCONSTANT = 607, + IDENTIFIER = 608, + TYPE_NAME = 609, + CENTROID = 610, + IN = 611, + OUT = 612, + INOUT = 613, + STRUCT = 614, + VOID = 615, + WHILE = 616, + BREAK = 617, + CONTINUE = 618, + DO = 619, + ELSE = 620, + FOR = 621, + IF = 622, + DISCARD = 623, + RETURN = 624, + SWITCH = 625, + CASE = 626, + DEFAULT = 627, + UNIFORM = 628, + SHARED = 629, + BUFFER = 630, + FLAT = 631, + SMOOTH = 632, + LAYOUT = 633, + DOUBLECONSTANT = 634, + INT16CONSTANT = 635, + UINT16CONSTANT = 636, + FLOAT16CONSTANT = 637, + INT32CONSTANT = 638, + UINT32CONSTANT = 639, + INT64CONSTANT = 640, + UINT64CONSTANT = 641, + SUBROUTINE = 642, + DEMOTE = 643, + PAYLOADNV = 644, + PAYLOADINNV = 645, + HITATTRNV = 646, + CALLDATANV = 647, + CALLDATAINNV = 648, + PAYLOADEXT = 649, + PAYLOADINEXT = 650, + HITATTREXT = 651, + CALLDATAEXT = 652, + CALLDATAINEXT = 653, + PATCH = 654, + SAMPLE = 655, + NONUNIFORM = 656, + COHERENT = 657, + VOLATILE = 658, + RESTRICT = 659, + READONLY = 660, + WRITEONLY = 661, + DEVICECOHERENT = 662, + QUEUEFAMILYCOHERENT = 663, + WORKGROUPCOHERENT = 664, + SUBGROUPCOHERENT = 665, + NONPRIVATE = 666, + SHADERCALLCOHERENT = 667, + NOPERSPECTIVE = 668, + EXPLICITINTERPAMD = 669, + PERVERTEXNV = 670, + PERPRIMITIVENV = 671, + PERVIEWNV = 672, + PERTASKNV = 673, + PRECISE = 674 + }; +#endif + +/* Value type. */ +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED + +union YYSTYPE +{ +#line 97 "glslang.y" /* yacc.c:1909 */ + + struct { + glslang::TSourceLoc loc; + union { + glslang::TString *string; + int i; + unsigned int u; + long long i64; + unsigned long long u64; + bool b; + double d; + }; + glslang::TSymbol* symbol; + } lex; + struct { + glslang::TSourceLoc loc; + glslang::TOperator op; + union { + TIntermNode* intermNode; + glslang::TIntermNodePair nodePair; + glslang::TIntermTyped* intermTypedNode; + glslang::TAttributes* attributes; + }; + union { + glslang::TPublicType type; + glslang::TFunction* function; + glslang::TParameter param; + glslang::TTypeLoc typeLine; + glslang::TTypeList* typeList; + glslang::TArraySizes* arraySizes; + glslang::TIdentifierList* identifierList; + }; + glslang::TArraySizes* typeParameters; + } interm; + +#line 510 "glslang_tab.cpp.h" /* yacc.c:1909 */ +}; + +typedef union YYSTYPE YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif + + + +int yyparse (glslang::TParseContext* pParseContext); + +#endif /* !YY_YY_GLSLANG_TAB_CPP_H_INCLUDED */ diff --git a/mac/include/glslang/MachineIndependent/iomapper.h b/mac/include/glslang/MachineIndependent/iomapper.h new file mode 100644 index 00000000..13a8932b --- /dev/null +++ b/mac/include/glslang/MachineIndependent/iomapper.h @@ -0,0 +1,300 @@ +// +// Copyright (C) 2016 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef GLSLANG_WEB + +#ifndef _IOMAPPER_INCLUDED +#define _IOMAPPER_INCLUDED + +#include +#include "LiveTraverser.h" +#include +#include +// +// A reflection database and its interface, consistent with the OpenGL API reflection queries. +// + +class TInfoSink; + +namespace glslang { + +class TIntermediate; +struct TVarEntryInfo { + int id; + TIntermSymbol* symbol; + bool live; + int newBinding; + int newSet; + int newLocation; + int newComponent; + int newIndex; + EShLanguage stage; + struct TOrderById { + inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) { return l.id < r.id; } + }; + + struct TOrderByPriority { + // ordering: + // 1) has both binding and set + // 2) has binding but no set + // 3) has no binding but set + // 4) has no binding and no set + inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) { + const TQualifier& lq = l.symbol->getQualifier(); + const TQualifier& rq = r.symbol->getQualifier(); + + // simple rules: + // has binding gives 2 points + // has set gives 1 point + // who has the most points is more important. + int lPoints = (lq.hasBinding() ? 2 : 0) + (lq.hasSet() ? 1 : 0); + int rPoints = (rq.hasBinding() ? 2 : 0) + (rq.hasSet() ? 1 : 0); + + if (lPoints == rPoints) + return l.id < r.id; + return lPoints > rPoints; + } + }; +}; + +// Base class for shared TIoMapResolver services, used by several derivations. +struct TDefaultIoResolverBase : public glslang::TIoMapResolver { +public: + TDefaultIoResolverBase(const TIntermediate& intermediate); + typedef std::vector TSlotSet; + typedef std::unordered_map TSlotSetMap; + + // grow the reflection stage by stage + void notifyBinding(EShLanguage, TVarEntryInfo& /*ent*/) override {} + void notifyInOut(EShLanguage, TVarEntryInfo& /*ent*/) override {} + void beginNotifications(EShLanguage) override {} + void endNotifications(EShLanguage) override {} + void beginResolve(EShLanguage) override {} + void endResolve(EShLanguage) override {} + void beginCollect(EShLanguage) override {} + void endCollect(EShLanguage) override {} + void reserverResourceSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {} + void reserverStorageSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {} + int getBaseBinding(TResourceType res, unsigned int set) const; + const std::vector& getResourceSetBinding() const; + virtual TResourceType getResourceType(const glslang::TType& type) = 0; + bool doAutoBindingMapping() const; + bool doAutoLocationMapping() const; + TSlotSet::iterator findSlot(int set, int slot); + bool checkEmpty(int set, int slot); + bool validateInOut(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; } + int reserveSlot(int set, int slot, int size = 1); + int getFreeSlot(int set, int base, int size = 1); + int resolveSet(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + int resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override; + int resolveInOutComponent(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + int resolveInOutIndex(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + void addStage(EShLanguage stage) override { + if (stage < EShLangCount) + stageMask[stage] = true; + } + uint32_t computeTypeLocationSize(const TType& type, EShLanguage stage); + + TSlotSetMap slots; + bool hasError = false; + +protected: + TDefaultIoResolverBase(TDefaultIoResolverBase&); + TDefaultIoResolverBase& operator=(TDefaultIoResolverBase&); + const TIntermediate& intermediate; + int nextUniformLocation; + int nextInputLocation; + int nextOutputLocation; + bool stageMask[EShLangCount + 1]; + // Return descriptor set specific base if there is one, and the generic base otherwise. + int selectBaseBinding(int base, int descriptorSetBase) const { + return descriptorSetBase != -1 ? descriptorSetBase : base; + } + + static int getLayoutSet(const glslang::TType& type) { + if (type.getQualifier().hasSet()) + return type.getQualifier().layoutSet; + else + return 0; + } + + static bool isSamplerType(const glslang::TType& type) { + return type.getBasicType() == glslang::EbtSampler && type.getSampler().isPureSampler(); + } + + static bool isTextureType(const glslang::TType& type) { + return (type.getBasicType() == glslang::EbtSampler && + (type.getSampler().isTexture() || type.getSampler().isSubpass())); + } + + static bool isUboType(const glslang::TType& type) { + return type.getQualifier().storage == EvqUniform; + } + + static bool isImageType(const glslang::TType& type) { + return type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage(); + } + + static bool isSsboType(const glslang::TType& type) { + return type.getQualifier().storage == EvqBuffer; + } + + // Return true if this is a SRV (shader resource view) type: + static bool isSrvType(const glslang::TType& type) { + return isTextureType(type) || type.getQualifier().storage == EvqBuffer; + } + + // Return true if this is a UAV (unordered access view) type: + static bool isUavType(const glslang::TType& type) { + if (type.getQualifier().isReadOnly()) + return false; + return (type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage()) || + (type.getQualifier().storage == EvqBuffer); + } +}; + +// Defaulf I/O resolver for OpenGL +struct TDefaultGlslIoResolver : public TDefaultIoResolverBase { +public: + typedef std::map TVarSlotMap; // + typedef std::map TSlotMap; // + TDefaultGlslIoResolver(const TIntermediate& intermediate); + bool validateBinding(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; } + TResourceType getResourceType(const glslang::TType& type) override; + int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override; + int resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + int resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + void beginResolve(EShLanguage /*stage*/) override; + void endResolve(EShLanguage stage) override; + void beginCollect(EShLanguage) override; + void endCollect(EShLanguage) override; + void reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override; + void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override; + // in/out symbol and uniform symbol are stored in the same resourceSlotMap, the storage key is used to identify each type of symbol. + // We use stage and storage qualifier to construct a storage key. it can help us identify the same storage resource used in different stage. + // if a resource is a program resource and we don't need know it usage stage, we can use same stage to build storage key. + // Note: both stage and type must less then 0xffff. + int buildStorageKey(EShLanguage stage, TStorageQualifier type) { + assert(static_cast(stage) <= 0x0000ffff && static_cast(type) <= 0x0000ffff); + return (stage << 16) | type; + } + +protected: + // Use for mark pre stage, to get more interface symbol information. + EShLanguage preStage; + // Use for mark current shader stage for resolver + EShLanguage currentStage; + // Slot map for storage resource(location of uniform and interface symbol) It's a program share slot + TSlotMap resourceSlotMap; + // Slot map for other resource(image, ubo, ssbo), It's a program share slot. + TSlotMap storageSlotMap; +}; + +typedef std::map TVarLiveMap; + +// override function "operator=", if a vector being sort, +// when use vc++, the sort function will call : +// pair& operator=(const pair<_Other1, _Other2>& _Right) +// { +// first = _Right.first; +// second = _Right.second; +// return (*this); +// } +// that will make a const type handing on left. +// override this function can avoid a compiler error. +// In the future, if the vc++ compiler can handle such a situation, +// this part of the code will be removed. +struct TVarLivePair : std::pair { + TVarLivePair(std::pair& _Right) : pair(_Right.first, _Right.second) {} + TVarLivePair& operator=(const TVarLivePair& _Right) { + const_cast(first) = _Right.first; + second = _Right.second; + return (*this); + } +}; +typedef std::vector TVarLiveVector; + +// I/O mapper +class TIoMapper { +public: + TIoMapper() {} + virtual ~TIoMapper() {} + // grow the reflection stage by stage + bool virtual addStage(EShLanguage, TIntermediate&, TInfoSink&, TIoMapResolver*); + bool virtual doMap(TIoMapResolver*, TInfoSink&) { return true; } +}; + +// I/O mapper for OpenGL +class TGlslIoMapper : public TIoMapper { +public: + TGlslIoMapper() { + memset(inVarMaps, 0, sizeof(TVarLiveMap*) * EShLangCount); + memset(outVarMaps, 0, sizeof(TVarLiveMap*) * EShLangCount); + memset(uniformVarMap, 0, sizeof(TVarLiveMap*) * EShLangCount); + memset(intermediates, 0, sizeof(TIntermediate*) * EShLangCount); + } + virtual ~TGlslIoMapper() { + for (size_t stage = 0; stage < EShLangCount; stage++) { + if (inVarMaps[stage] != nullptr) { + delete inVarMaps[stage]; + inVarMaps[stage] = nullptr; + } + if (outVarMaps[stage] != nullptr) { + delete outVarMaps[stage]; + outVarMaps[stage] = nullptr; + } + if (uniformVarMap[stage] != nullptr) { + delete uniformVarMap[stage]; + uniformVarMap[stage] = nullptr; + } + if (intermediates[stage] != nullptr) + intermediates[stage] = nullptr; + } + } + // grow the reflection stage by stage + bool addStage(EShLanguage, TIntermediate&, TInfoSink&, TIoMapResolver*) override; + bool doMap(TIoMapResolver*, TInfoSink&) override; + TVarLiveMap *inVarMaps[EShLangCount], *outVarMaps[EShLangCount], + *uniformVarMap[EShLangCount]; + TIntermediate* intermediates[EShLangCount]; + bool hadError = false; +}; + +} // end namespace glslang + +#endif // _IOMAPPER_INCLUDED + +#endif // GLSLANG_WEB diff --git a/mac/include/glslang/MachineIndependent/localintermediate.h b/mac/include/glslang/MachineIndependent/localintermediate.h new file mode 100644 index 00000000..66f5a88a --- /dev/null +++ b/mac/include/glslang/MachineIndependent/localintermediate.h @@ -0,0 +1,1013 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2016 LunarG, Inc. +// Copyright (C) 2017 ARM Limited. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef _LOCAL_INTERMEDIATE_INCLUDED_ +#define _LOCAL_INTERMEDIATE_INCLUDED_ + +#include "../Include/intermediate.h" +#include "../Public/ShaderLang.h" +#include "Versions.h" + +#include +#include +#include +#include +#include + +class TInfoSink; + +namespace glslang { + +struct TMatrixSelector { + int coord1; // stay agnostic about column/row; this is parse order + int coord2; +}; + +typedef int TVectorSelector; + +const int MaxSwizzleSelectors = 4; + +template +class TSwizzleSelectors { +public: + TSwizzleSelectors() : size_(0) { } + + void push_back(selectorType comp) + { + if (size_ < MaxSwizzleSelectors) + components[size_++] = comp; + } + void resize(int s) + { + assert(s <= size_); + size_ = s; + } + int size() const { return size_; } + selectorType operator[](int i) const + { + assert(i < MaxSwizzleSelectors); + return components[i]; + } + +private: + int size_; + selectorType components[MaxSwizzleSelectors]; +}; + +// +// Some helper structures for TIntermediate. Their contents are encapsulated +// by TIntermediate. +// + +// Used for call-graph algorithms for detecting recursion, missing bodies, and dead bodies. +// A "call" is a pair: . +// There can be duplicates. General assumption is the list is small. +struct TCall { + TCall(const TString& pCaller, const TString& pCallee) : caller(pCaller), callee(pCallee) { } + TString caller; + TString callee; + bool visited; + bool currentPath; + bool errorGiven; + int calleeBodyPosition; +}; + +// A generic 1-D range. +struct TRange { + TRange(int start, int last) : start(start), last(last) { } + bool overlap(const TRange& rhs) const + { + return last >= rhs.start && start <= rhs.last; + } + int start; + int last; +}; + +// An IO range is a 3-D rectangle; the set of (location, component, index) triples all lying +// within the same location range, component range, and index value. Locations don't alias unless +// all other dimensions of their range overlap. +struct TIoRange { + TIoRange(TRange location, TRange component, TBasicType basicType, int index) + : location(location), component(component), basicType(basicType), index(index) { } + bool overlap(const TIoRange& rhs) const + { + return location.overlap(rhs.location) && component.overlap(rhs.component) && index == rhs.index; + } + TRange location; + TRange component; + TBasicType basicType; + int index; +}; + +// An offset range is a 2-D rectangle; the set of (binding, offset) pairs all lying +// within the same binding and offset range. +struct TOffsetRange { + TOffsetRange(TRange binding, TRange offset) + : binding(binding), offset(offset) { } + bool overlap(const TOffsetRange& rhs) const + { + return binding.overlap(rhs.binding) && offset.overlap(rhs.offset); + } + TRange binding; + TRange offset; +}; + +#ifndef GLSLANG_WEB +// Things that need to be tracked per xfb buffer. +struct TXfbBuffer { + TXfbBuffer() : stride(TQualifier::layoutXfbStrideEnd), implicitStride(0), contains64BitType(false), + contains32BitType(false), contains16BitType(false) { } + std::vector ranges; // byte offsets that have already been assigned + unsigned int stride; + unsigned int implicitStride; + bool contains64BitType; + bool contains32BitType; + bool contains16BitType; +}; +#endif + +// Track a set of strings describing how the module was processed. +// This includes command line options, transforms, etc., ideally inclusive enough +// to reproduce the steps used to transform the input source to the output. +// E.g., see SPIR-V OpModuleProcessed. +// Each "process" or "transform" uses is expressed in the form: +// process arg0 arg1 arg2 ... +// process arg0 arg1 arg2 ... +// where everything is textual, and there can be zero or more arguments +class TProcesses { +public: + TProcesses() {} + ~TProcesses() {} + + void addProcess(const char* process) + { + processes.push_back(process); + } + void addProcess(const std::string& process) + { + processes.push_back(process); + } + void addArgument(int arg) + { + processes.back().append(" "); + std::string argString = std::to_string(arg); + processes.back().append(argString); + } + void addArgument(const char* arg) + { + processes.back().append(" "); + processes.back().append(arg); + } + void addArgument(const std::string& arg) + { + processes.back().append(" "); + processes.back().append(arg); + } + void addIfNonZero(const char* process, int value) + { + if (value != 0) { + addProcess(process); + addArgument(value); + } + } + + const std::vector& getProcesses() const { return processes; } + +private: + std::vector processes; +}; + +class TSymbolTable; +class TSymbol; +class TVariable; + +// +// Texture and Sampler transformation mode. +// +enum ComputeDerivativeMode { + LayoutDerivativeNone, // default layout as SPV_NV_compute_shader_derivatives not enabled + LayoutDerivativeGroupQuads, // derivative_group_quadsNV + LayoutDerivativeGroupLinear, // derivative_group_linearNV +}; + +class TIdMaps { +public: + TMap& operator[](int i) { return maps[i]; } + const TMap& operator[](int i) const { return maps[i]; } +private: + TMap maps[EsiCount]; +}; + + +// +// Set of helper functions to help parse and build the tree. +// +class TIntermediate { +public: + explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) : + language(l), + profile(p), version(v), treeRoot(0), + numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false), + invertY(false), + useStorageBuffer(false), + nanMinMaxClamp(false), + depthReplacing(false) +#ifndef GLSLANG_WEB + , + implicitThisName("@this"), implicitCounterName("@count"), + source(EShSourceNone), + useVulkanMemoryModel(false), + invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet), + inputPrimitive(ElgNone), outputPrimitive(ElgNone), + pixelCenterInteger(false), originUpperLeft(false), + vertexSpacing(EvsNone), vertexOrder(EvoNone), interlockOrdering(EioNone), pointMode(false), earlyFragmentTests(false), + postDepthCoverage(false), depthLayout(EldNone), + hlslFunctionality1(false), + blendEquations(0), xfbMode(false), multiStream(false), + layoutOverrideCoverage(false), + geoPassthroughEXT(false), + numShaderRecordBlocks(0), + computeDerivativeMode(LayoutDerivativeNone), + primitives(TQualifier::layoutNotSet), + numTaskNVBlocks(0), + autoMapBindings(false), + autoMapLocations(false), + flattenUniformArrays(false), + useUnknownFormat(false), + hlslOffsets(false), + hlslIoMapping(false), + useVariablePointers(false), + textureSamplerTransformMode(EShTexSampTransKeep), + needToLegalize(false), + binaryDoubleOutput(false), + usePhysicalStorageBuffer(false), + uniformLocationBase(0) +#endif + { + localSize[0] = 1; + localSize[1] = 1; + localSize[2] = 1; + localSizeNotDefault[0] = false; + localSizeNotDefault[1] = false; + localSizeNotDefault[2] = false; + localSizeSpecId[0] = TQualifier::layoutNotSet; + localSizeSpecId[1] = TQualifier::layoutNotSet; + localSizeSpecId[2] = TQualifier::layoutNotSet; +#ifndef GLSLANG_WEB + xfbBuffers.resize(TQualifier::layoutXfbBufferEnd); + shiftBinding.fill(0); +#endif + } + + void setVersion(int v) { version = v; } + int getVersion() const { return version; } + void setProfile(EProfile p) { profile = p; } + EProfile getProfile() const { return profile; } + void setSpv(const SpvVersion& s) + { + spvVersion = s; + + // client processes + if (spvVersion.vulkan > 0) + processes.addProcess("client vulkan100"); + if (spvVersion.openGl > 0) + processes.addProcess("client opengl100"); + + // target SPV + switch (spvVersion.spv) { + case 0: + break; + case EShTargetSpv_1_0: + break; + case EShTargetSpv_1_1: + processes.addProcess("target-env spirv1.1"); + break; + case EShTargetSpv_1_2: + processes.addProcess("target-env spirv1.2"); + break; + case EShTargetSpv_1_3: + processes.addProcess("target-env spirv1.3"); + break; + case EShTargetSpv_1_4: + processes.addProcess("target-env spirv1.4"); + break; + case EShTargetSpv_1_5: + processes.addProcess("target-env spirv1.5"); + break; + default: + processes.addProcess("target-env spirvUnknown"); + break; + } + + // target-environment processes + switch (spvVersion.vulkan) { + case 0: + break; + case EShTargetVulkan_1_0: + processes.addProcess("target-env vulkan1.0"); + break; + case EShTargetVulkan_1_1: + processes.addProcess("target-env vulkan1.1"); + break; + case EShTargetVulkan_1_2: + processes.addProcess("target-env vulkan1.2"); + break; + default: + processes.addProcess("target-env vulkanUnknown"); + break; + } + if (spvVersion.openGl > 0) + processes.addProcess("target-env opengl"); + } + const SpvVersion& getSpv() const { return spvVersion; } + EShLanguage getStage() const { return language; } + void addRequestedExtension(const char* extension) { requestedExtensions.insert(extension); } + const std::set& getRequestedExtensions() const { return requestedExtensions; } + + void setTreeRoot(TIntermNode* r) { treeRoot = r; } + TIntermNode* getTreeRoot() const { return treeRoot; } + void incrementEntryPointCount() { ++numEntryPoints; } + int getNumEntryPoints() const { return numEntryPoints; } + int getNumErrors() const { return numErrors; } + void addPushConstantCount() { ++numPushConstants; } + void setLimits(const TBuiltInResource& r) { resources = r; } + + bool postProcess(TIntermNode*, EShLanguage); + void removeTree(); + + void setEntryPointName(const char* ep) + { + entryPointName = ep; + processes.addProcess("entry-point"); + processes.addArgument(entryPointName); + } + void setEntryPointMangledName(const char* ep) { entryPointMangledName = ep; } + const std::string& getEntryPointName() const { return entryPointName; } + const std::string& getEntryPointMangledName() const { return entryPointMangledName; } + + void setInvertY(bool invert) + { + invertY = invert; + if (invertY) + processes.addProcess("invert-y"); + } + bool getInvertY() const { return invertY; } + +#ifdef ENABLE_HLSL + void setSource(EShSource s) { source = s; } + EShSource getSource() const { return source; } +#else + void setSource(EShSource s) { assert(s == EShSourceGlsl); } + EShSource getSource() const { return EShSourceGlsl; } +#endif + + bool isRecursive() const { return recursive; } + + TIntermSymbol* addSymbol(const TVariable&); + TIntermSymbol* addSymbol(const TVariable&, const TSourceLoc&); + TIntermSymbol* addSymbol(const TType&, const TSourceLoc&); + TIntermSymbol* addSymbol(const TIntermSymbol&); + TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*); + std::tuple addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1); + TIntermTyped* addUniShapeConversion(TOperator, const TType&, TIntermTyped*); + TIntermTyped* addConversion(TBasicType convertTo, TIntermTyped* node) const; + void addBiShapeConversion(TOperator, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode); + TIntermTyped* addShapeConversion(const TType&, TIntermTyped*); + TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc); + TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc); + TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc); + TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, TSourceLoc); + TIntermTyped* addBuiltInFunctionCall(const TSourceLoc& line, TOperator, bool unary, TIntermNode*, const TType& returnType); + bool canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op = EOpNull) const; + bool isIntegralPromotion(TBasicType from, TBasicType to) const; + bool isFPPromotion(TBasicType from, TBasicType to) const; + bool isIntegralConversion(TBasicType from, TBasicType to) const; + bool isFPConversion(TBasicType from, TBasicType to) const; + bool isFPIntegralConversion(TBasicType from, TBasicType to) const; + TOperator mapTypeToConstructorOp(const TType&) const; + TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right); + TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&); + TIntermAggregate* makeAggregate(TIntermNode* node); + TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&); + TIntermAggregate* makeAggregate(const TSourceLoc&); + TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, TSourceLoc); + bool areAllChildConst(TIntermAggregate* aggrNode); + TIntermSelection* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&); + TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&); + TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); + TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, const TSourceLoc&); + TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(signed char, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(unsigned char, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(signed short, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(unsigned short, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(int, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(unsigned int, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(long long, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(unsigned long long, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(bool, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(double, TBasicType, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(const TString*, const TSourceLoc&, bool literal = false) const; + TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const; + bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false); + TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&); + TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, + const TSourceLoc&, TIntermLoop*&); + TIntermBranch* addBranch(TOperator, const TSourceLoc&); + TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&); + template TIntermTyped* addSwizzle(TSwizzleSelectors&, const TSourceLoc&); + + // Low level functions to add nodes (no conversions or other higher level transformations) + // If a type is provided, the node's type will be set to it. + TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc) const; + TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, const TType&) const; + TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc) const; + TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc, const TType&) const; + + // Constant folding (in Constant.cpp) + TIntermTyped* fold(TIntermAggregate* aggrNode); + TIntermTyped* foldConstructor(TIntermAggregate* aggrNode); + TIntermTyped* foldDereference(TIntermTyped* node, int index, const TSourceLoc&); + TIntermTyped* foldSwizzle(TIntermTyped* node, TSwizzleSelectors& fields, const TSourceLoc&); + + // Tree ops + static const TIntermTyped* findLValueBase(const TIntermTyped*, bool swizzleOkay); + + // Linkage related + void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&); + void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&); + + void setUseStorageBuffer() + { + useStorageBuffer = true; + processes.addProcess("use-storage-buffer"); + } + bool usingStorageBuffer() const { return useStorageBuffer; } + void setDepthReplacing() { depthReplacing = true; } + bool isDepthReplacing() const { return depthReplacing; } + bool setLocalSize(int dim, int size) + { + if (localSizeNotDefault[dim]) + return size == localSize[dim]; + localSizeNotDefault[dim] = true; + localSize[dim] = size; + return true; + } + unsigned int getLocalSize(int dim) const { return localSize[dim]; } + bool setLocalSizeSpecId(int dim, int id) + { + if (localSizeSpecId[dim] != TQualifier::layoutNotSet) + return id == localSizeSpecId[dim]; + localSizeSpecId[dim] = id; + return true; + } + int getLocalSizeSpecId(int dim) const { return localSizeSpecId[dim]; } +#ifdef GLSLANG_WEB + void output(TInfoSink&, bool tree) { } + + bool isEsProfile() const { return false; } + bool getXfbMode() const { return false; } + bool isMultiStream() const { return false; } + TLayoutGeometry getOutputPrimitive() const { return ElgNone; } + bool getPostDepthCoverage() const { return false; } + bool getEarlyFragmentTests() const { return false; } + TLayoutDepth getDepth() const { return EldNone; } + bool getPixelCenterInteger() const { return false; } + void setOriginUpperLeft() { } + bool getOriginUpperLeft() const { return true; } + TInterlockOrdering getInterlockOrdering() const { return EioNone; } + + bool getAutoMapBindings() const { return false; } + bool getAutoMapLocations() const { return false; } + int getNumPushConstants() const { return 0; } + void addShaderRecordCount() { } + void addTaskNVCount() { } + void setUseVulkanMemoryModel() { } + bool usingVulkanMemoryModel() const { return false; } + bool usingPhysicalStorageBuffer() const { return false; } + bool usingVariablePointers() const { return false; } + unsigned getXfbStride(int buffer) const { return 0; } + bool hasLayoutDerivativeModeNone() const { return false; } + ComputeDerivativeMode getLayoutDerivativeModeNone() const { return LayoutDerivativeNone; } +#else + void output(TInfoSink&, bool tree); + + bool isEsProfile() const { return profile == EEsProfile; } + + void setShiftBinding(TResourceType res, unsigned int shift) + { + shiftBinding[res] = shift; + + const char* name = getResourceName(res); + if (name != nullptr) + processes.addIfNonZero(name, shift); + } + + unsigned int getShiftBinding(TResourceType res) const { return shiftBinding[res]; } + + void setShiftBindingForSet(TResourceType res, unsigned int shift, unsigned int set) + { + if (shift == 0) // ignore if there's no shift: it's a no-op. + return; + + shiftBindingForSet[res][set] = shift; + + const char* name = getResourceName(res); + if (name != nullptr) { + processes.addProcess(name); + processes.addArgument(shift); + processes.addArgument(set); + } + } + + int getShiftBindingForSet(TResourceType res, unsigned int set) const + { + const auto shift = shiftBindingForSet[res].find(set); + return shift == shiftBindingForSet[res].end() ? -1 : shift->second; + } + bool hasShiftBindingForSet(TResourceType res) const { return !shiftBindingForSet[res].empty(); } + + void setResourceSetBinding(const std::vector& shift) + { + resourceSetBinding = shift; + if (shift.size() > 0) { + processes.addProcess("resource-set-binding"); + for (int s = 0; s < (int)shift.size(); ++s) + processes.addArgument(shift[s]); + } + } + const std::vector& getResourceSetBinding() const { return resourceSetBinding; } + void setAutoMapBindings(bool map) + { + autoMapBindings = map; + if (autoMapBindings) + processes.addProcess("auto-map-bindings"); + } + bool getAutoMapBindings() const { return autoMapBindings; } + void setAutoMapLocations(bool map) + { + autoMapLocations = map; + if (autoMapLocations) + processes.addProcess("auto-map-locations"); + } + bool getAutoMapLocations() const { return autoMapLocations; } + +#ifdef ENABLE_HLSL + void setFlattenUniformArrays(bool flatten) + { + flattenUniformArrays = flatten; + if (flattenUniformArrays) + processes.addProcess("flatten-uniform-arrays"); + } + bool getFlattenUniformArrays() const { return flattenUniformArrays; } +#endif + void setNoStorageFormat(bool b) + { + useUnknownFormat = b; + if (useUnknownFormat) + processes.addProcess("no-storage-format"); + } + bool getNoStorageFormat() const { return useUnknownFormat; } + void setUseVulkanMemoryModel() + { + useVulkanMemoryModel = true; + processes.addProcess("use-vulkan-memory-model"); + } + bool usingVulkanMemoryModel() const { return useVulkanMemoryModel; } + void setUsePhysicalStorageBuffer() + { + usePhysicalStorageBuffer = true; + } + bool usingPhysicalStorageBuffer() const { return usePhysicalStorageBuffer; } + void setUseVariablePointers() + { + useVariablePointers = true; + processes.addProcess("use-variable-pointers"); + } + bool usingVariablePointers() const { return useVariablePointers; } + +#ifdef ENABLE_HLSL + template T addCounterBufferName(const T& name) const { return name + implicitCounterName; } + bool hasCounterBufferName(const TString& name) const { + size_t len = strlen(implicitCounterName); + return name.size() > len && + name.compare(name.size() - len, len, implicitCounterName) == 0; + } +#endif + + void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; } + int getNumPushConstants() const { return numPushConstants; } + void addShaderRecordCount() { ++numShaderRecordBlocks; } + void addTaskNVCount() { ++numTaskNVBlocks; } + + bool setInvocations(int i) + { + if (invocations != TQualifier::layoutNotSet) + return invocations == i; + invocations = i; + return true; + } + int getInvocations() const { return invocations; } + bool setVertices(int m) + { + if (vertices != TQualifier::layoutNotSet) + return vertices == m; + vertices = m; + return true; + } + int getVertices() const { return vertices; } + bool setInputPrimitive(TLayoutGeometry p) + { + if (inputPrimitive != ElgNone) + return inputPrimitive == p; + inputPrimitive = p; + return true; + } + TLayoutGeometry getInputPrimitive() const { return inputPrimitive; } + bool setVertexSpacing(TVertexSpacing s) + { + if (vertexSpacing != EvsNone) + return vertexSpacing == s; + vertexSpacing = s; + return true; + } + TVertexSpacing getVertexSpacing() const { return vertexSpacing; } + bool setVertexOrder(TVertexOrder o) + { + if (vertexOrder != EvoNone) + return vertexOrder == o; + vertexOrder = o; + return true; + } + TVertexOrder getVertexOrder() const { return vertexOrder; } + void setPointMode() { pointMode = true; } + bool getPointMode() const { return pointMode; } + + bool setInterlockOrdering(TInterlockOrdering o) + { + if (interlockOrdering != EioNone) + return interlockOrdering == o; + interlockOrdering = o; + return true; + } + TInterlockOrdering getInterlockOrdering() const { return interlockOrdering; } + + void setXfbMode() { xfbMode = true; } + bool getXfbMode() const { return xfbMode; } + void setMultiStream() { multiStream = true; } + bool isMultiStream() const { return multiStream; } + bool setOutputPrimitive(TLayoutGeometry p) + { + if (outputPrimitive != ElgNone) + return outputPrimitive == p; + outputPrimitive = p; + return true; + } + TLayoutGeometry getOutputPrimitive() const { return outputPrimitive; } + void setPostDepthCoverage() { postDepthCoverage = true; } + bool getPostDepthCoverage() const { return postDepthCoverage; } + void setEarlyFragmentTests() { earlyFragmentTests = true; } + bool getEarlyFragmentTests() const { return earlyFragmentTests; } + bool setDepth(TLayoutDepth d) + { + if (depthLayout != EldNone) + return depthLayout == d; + depthLayout = d; + return true; + } + TLayoutDepth getDepth() const { return depthLayout; } + void setOriginUpperLeft() { originUpperLeft = true; } + bool getOriginUpperLeft() const { return originUpperLeft; } + void setPixelCenterInteger() { pixelCenterInteger = true; } + bool getPixelCenterInteger() const { return pixelCenterInteger; } + void addBlendEquation(TBlendEquationShift b) { blendEquations |= (1 << b); } + unsigned int getBlendEquations() const { return blendEquations; } + bool setXfbBufferStride(int buffer, unsigned stride) + { + if (xfbBuffers[buffer].stride != TQualifier::layoutXfbStrideEnd) + return xfbBuffers[buffer].stride == stride; + xfbBuffers[buffer].stride = stride; + return true; + } + unsigned getXfbStride(int buffer) const { return xfbBuffers[buffer].stride; } + int addXfbBufferOffset(const TType&); + unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType, bool& contains32BitType, bool& contains16BitType) const; + unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType) const; + void setLayoutOverrideCoverage() { layoutOverrideCoverage = true; } + bool getLayoutOverrideCoverage() const { return layoutOverrideCoverage; } + void setGeoPassthroughEXT() { geoPassthroughEXT = true; } + bool getGeoPassthroughEXT() const { return geoPassthroughEXT; } + void setLayoutDerivativeMode(ComputeDerivativeMode mode) { computeDerivativeMode = mode; } + bool hasLayoutDerivativeModeNone() const { return computeDerivativeMode != LayoutDerivativeNone; } + ComputeDerivativeMode getLayoutDerivativeModeNone() const { return computeDerivativeMode; } + bool setPrimitives(int m) + { + if (primitives != TQualifier::layoutNotSet) + return primitives == m; + primitives = m; + return true; + } + int getPrimitives() const { return primitives; } + const char* addSemanticName(const TString& name) + { + return semanticNameSet.insert(name).first->c_str(); + } + void addUniformLocationOverride(const char* nameStr, int location) + { + std::string name = nameStr; + uniformLocationOverrides[name] = location; + } + + int getUniformLocationOverride(const char* nameStr) const + { + std::string name = nameStr; + auto pos = uniformLocationOverrides.find(name); + if (pos == uniformLocationOverrides.end()) + return -1; + else + return pos->second; + } + + void setUniformLocationBase(int base) { uniformLocationBase = base; } + int getUniformLocationBase() const { return uniformLocationBase; } + + void setNeedsLegalization() { needToLegalize = true; } + bool needsLegalization() const { return needToLegalize; } + + void setBinaryDoubleOutput() { binaryDoubleOutput = true; } + bool getBinaryDoubleOutput() { return binaryDoubleOutput; } +#endif // GLSLANG_WEB + +#ifdef ENABLE_HLSL + void setHlslFunctionality1() { hlslFunctionality1 = true; } + bool getHlslFunctionality1() const { return hlslFunctionality1; } + void setHlslOffsets() + { + hlslOffsets = true; + if (hlslOffsets) + processes.addProcess("hlsl-offsets"); + } + bool usingHlslOffsets() const { return hlslOffsets; } + void setHlslIoMapping(bool b) + { + hlslIoMapping = b; + if (hlslIoMapping) + processes.addProcess("hlsl-iomap"); + } + bool usingHlslIoMapping() { return hlslIoMapping; } +#else + bool getHlslFunctionality1() const { return false; } + bool usingHlslOffsets() const { return false; } + bool usingHlslIoMapping() { return false; } +#endif + + void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee); + void merge(TInfoSink&, TIntermediate&); + void finalCheck(TInfoSink&, bool keepUncalled); + + bool buildConvertOp(TBasicType dst, TBasicType src, TOperator& convertOp) const; + TIntermTyped* createConversion(TBasicType convertTo, TIntermTyped* node) const; + + void addIoAccessed(const TString& name) { ioAccessed.insert(name); } + bool inIoAccessed(const TString& name) const { return ioAccessed.find(name) != ioAccessed.end(); } + + int addUsedLocation(const TQualifier&, const TType&, bool& typeCollision); + int checkLocationRange(int set, const TIoRange& range, const TType&, bool& typeCollision); + int addUsedOffsets(int binding, int offset, int numOffsets); + bool addUsedConstantId(int id); + static int computeTypeLocationSize(const TType&, EShLanguage); + static int computeTypeUniformLocationSize(const TType&); + + static int getBaseAlignmentScalar(const TType&, int& size); + static int getBaseAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor); + static int getScalarAlignment(const TType&, int& size, int& stride, bool rowMajor); + static int getMemberAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor); + static bool improperStraddle(const TType& type, int size, int offset); + static void updateOffset(const TType& parentType, const TType& memberType, int& offset, int& memberSize); + static int getOffset(const TType& type, int index); + static int getBlockSize(const TType& blockType); + static int computeBufferReferenceTypeSize(const TType&); + bool promote(TIntermOperator*); + void setNanMinMaxClamp(bool setting) { nanMinMaxClamp = setting; } + bool getNanMinMaxClamp() const { return nanMinMaxClamp; } + + void setSourceFile(const char* file) { if (file != nullptr) sourceFile = file; } + const std::string& getSourceFile() const { return sourceFile; } + void addSourceText(const char* text, size_t len) { sourceText.append(text, len); } + const std::string& getSourceText() const { return sourceText; } + const std::map& getIncludeText() const { return includeText; } + void addIncludeText(const char* name, const char* text, size_t len) { includeText[name].assign(text,len); } + void addProcesses(const std::vector& p) + { + for (int i = 0; i < (int)p.size(); ++i) + processes.addProcess(p[i]); + } + void addProcess(const std::string& process) { processes.addProcess(process); } + void addProcessArgument(const std::string& arg) { processes.addArgument(arg); } + const std::vector& getProcesses() const { return processes.getProcesses(); } + + // Certain explicit conversions are allowed conditionally +#ifdef GLSLANG_WEB + bool getArithemeticInt8Enabled() const { return false; } + bool getArithemeticInt16Enabled() const { return false; } + bool getArithemeticFloat16Enabled() const { return false; } +#else + bool getArithemeticInt8Enabled() const { + return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || + extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8); + } + bool getArithemeticInt16Enabled() const { + return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || + extensionRequested(E_GL_AMD_gpu_shader_int16) || + extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16); + } + + bool getArithemeticFloat16Enabled() const { + return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || + extensionRequested(E_GL_AMD_gpu_shader_half_float) || + extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16); + } +#endif + +protected: + TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&); + void error(TInfoSink& infoSink, const char*); + void warn(TInfoSink& infoSink, const char*); + void mergeCallGraphs(TInfoSink&, TIntermediate&); + void mergeModes(TInfoSink&, TIntermediate&); + void mergeTrees(TInfoSink&, TIntermediate&); + void seedIdMap(TIdMaps& idMaps, int& maxId); + void remapIds(const TIdMaps& idMaps, int idShift, TIntermediate&); + void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals); + void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects); + void mergeImplicitArraySizes(TType&, const TType&); + void mergeErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, bool crossStage); + void checkCallGraphCycles(TInfoSink&); + void checkCallGraphBodies(TInfoSink&, bool keepUncalled); + void inOutLocationCheck(TInfoSink&); + TIntermAggregate* findLinkerObjects() const; + bool userOutputUsed() const; + bool isSpecializationOperation(const TIntermOperator&) const; + bool isNonuniformPropagating(TOperator) const; + bool promoteUnary(TIntermUnary&); + bool promoteBinary(TIntermBinary&); + void addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable&, const TString&); + bool promoteAggregate(TIntermAggregate&); + void pushSelector(TIntermSequence&, const TVectorSelector&, const TSourceLoc&); + void pushSelector(TIntermSequence&, const TMatrixSelector&, const TSourceLoc&); + bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&); + void performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root); + bool isConversionAllowed(TOperator op, TIntermTyped* node) const; + std::tuple getConversionDestinatonType(TBasicType type0, TBasicType type1, TOperator op) const; + + // JohnK: I think this function should go away. + // This data structure is just a log to pass on to back ends. + // Versioning and extensions are handled in Version.cpp, with a rich + // set of functions for querying stages, versions, extension enable/disabled, etc. +#ifdef GLSLANG_WEB + bool extensionRequested(const char *extension) const { return false; } +#else + bool extensionRequested(const char *extension) const {return requestedExtensions.find(extension) != requestedExtensions.end();} +#endif + + static const char* getResourceName(TResourceType); + + const EShLanguage language; // stage, known at construction time + std::string entryPointName; + std::string entryPointMangledName; + typedef std::list TGraph; + TGraph callGraph; + + EProfile profile; // source profile + int version; // source version + SpvVersion spvVersion; + TIntermNode* treeRoot; + std::set requestedExtensions; // cumulation of all enabled or required extensions; not connected to what subset of the shader used them + TBuiltInResource resources; + int numEntryPoints; + int numErrors; + int numPushConstants; + bool recursive; + bool invertY; + bool useStorageBuffer; + bool nanMinMaxClamp; // true if desiring min/max/clamp to favor non-NaN over NaN + bool depthReplacing; + int localSize[3]; + bool localSizeNotDefault[3]; + int localSizeSpecId[3]; +#ifndef GLSLANG_WEB +public: + const char* const implicitThisName; + const char* const implicitCounterName; +protected: + EShSource source; // source language, known a bit later + bool useVulkanMemoryModel; + int invocations; + int vertices; + TLayoutGeometry inputPrimitive; + TLayoutGeometry outputPrimitive; + bool pixelCenterInteger; + bool originUpperLeft; + TVertexSpacing vertexSpacing; + TVertexOrder vertexOrder; + TInterlockOrdering interlockOrdering; + bool pointMode; + bool earlyFragmentTests; + bool postDepthCoverage; + TLayoutDepth depthLayout; + bool hlslFunctionality1; + int blendEquations; // an 'or'ing of masks of shifts of TBlendEquationShift + bool xfbMode; + std::vector xfbBuffers; // all the data we need to track per xfb buffer + bool multiStream; + bool layoutOverrideCoverage; + bool geoPassthroughEXT; + int numShaderRecordBlocks; + ComputeDerivativeMode computeDerivativeMode; + int primitives; + int numTaskNVBlocks; + + // Base shift values + std::array shiftBinding; + + // Per-descriptor-set shift values + std::array, EResCount> shiftBindingForSet; + + std::vector resourceSetBinding; + bool autoMapBindings; + bool autoMapLocations; + bool flattenUniformArrays; + bool useUnknownFormat; + bool hlslOffsets; + bool hlslIoMapping; + bool useVariablePointers; + + std::set semanticNameSet; + + EShTextureSamplerTransformMode textureSamplerTransformMode; + + bool needToLegalize; + bool binaryDoubleOutput; + bool usePhysicalStorageBuffer; + + std::unordered_map uniformLocationOverrides; + int uniformLocationBase; +#endif + + std::unordered_set usedConstantId; // specialization constant ids used + std::vector usedAtomics; // sets of bindings used by atomic counters + std::vector usedIo[4]; // sets of used locations, one for each of in, out, uniform, and buffers + // set of names of statically read/written I/O that might need extra checking + std::set ioAccessed; + // source code of shader, useful as part of debug information + std::string sourceFile; + std::string sourceText; + + // Included text. First string is a name, second is the included text + std::map includeText; + + // for OpModuleProcessed, or equivalent + TProcesses processes; + +private: + void operator=(TIntermediate&); // prevent assignments +}; + +} // end namespace glslang + +#endif // _LOCAL_INTERMEDIATE_INCLUDED_ diff --git a/mac/include/glslang/MachineIndependent/parseVersions.h b/mac/include/glslang/MachineIndependent/parseVersions.h new file mode 100644 index 00000000..aa1964fc --- /dev/null +++ b/mac/include/glslang/MachineIndependent/parseVersions.h @@ -0,0 +1,236 @@ +// +// Copyright (C) 2015-2018 Google, Inc. +// Copyright (C) 2017 ARM Limited. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +// This is implemented in Versions.cpp + +#ifndef _PARSE_VERSIONS_INCLUDED_ +#define _PARSE_VERSIONS_INCLUDED_ + +#include "../Public/ShaderLang.h" +#include "../Include/InfoSink.h" +#include "Scan.h" + +#include + +namespace glslang { + +// +// Base class for parse helpers. +// This just has version-related information and checking. +// This class should be sufficient for preprocessing. +// +class TParseVersions { +public: + TParseVersions(TIntermediate& interm, int version, EProfile profile, + const SpvVersion& spvVersion, EShLanguage language, TInfoSink& infoSink, + bool forwardCompatible, EShMessages messages) + : +#ifndef GLSLANG_WEB + forwardCompatible(forwardCompatible), + profile(profile), +#endif + infoSink(infoSink), version(version), + language(language), + spvVersion(spvVersion), + intermediate(interm), messages(messages), numErrors(0), currentScanner(0) { } + virtual ~TParseVersions() { } + void requireStage(const TSourceLoc&, EShLanguageMask, const char* featureDesc); + void requireStage(const TSourceLoc&, EShLanguage, const char* featureDesc); +#ifdef GLSLANG_WEB + const EProfile profile = EEsProfile; + bool isEsProfile() const { return true; } + void requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc) + { + if (! (EEsProfile & profileMask)) + error(loc, "not supported with this profile:", featureDesc, ProfileName(profile)); + } + void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions, + const char* const extensions[], const char* featureDesc) + { + if ((EEsProfile & profileMask) && (minVersion == 0 || version < minVersion)) + error(loc, "not supported for this version or the enabled extensions", featureDesc, ""); + } + void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, const char* extension, + const char* featureDesc) + { + profileRequires(loc, profileMask, minVersion, extension ? 1 : 0, &extension, featureDesc); + } + void initializeExtensionBehavior() { } + void checkDeprecated(const TSourceLoc&, int queryProfiles, int depVersion, const char* featureDesc) { } + void requireNotRemoved(const TSourceLoc&, int queryProfiles, int removedVersion, const char* featureDesc) { } + void requireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], + const char* featureDesc) { } + void ppRequireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], + const char* featureDesc) { } + TExtensionBehavior getExtensionBehavior(const char*) { return EBhMissing; } + bool extensionTurnedOn(const char* const extension) { return false; } + bool extensionsTurnedOn(int numExtensions, const char* const extensions[]) { return false; } + void updateExtensionBehavior(int line, const char* const extension, const char* behavior) { } + void updateExtensionBehavior(const char* const extension, TExtensionBehavior) { } + void checkExtensionStage(const TSourceLoc&, const char* const extension) { } + void fullIntegerCheck(const TSourceLoc&, const char* op) { } + void doubleCheck(const TSourceLoc&, const char* op) { } + bool float16Arithmetic() { return false; } + void requireFloat16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc) { } + bool int16Arithmetic() { return false; } + void requireInt16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc) { } + bool int8Arithmetic() { return false; } + void requireInt8Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc) { } + void int64Check(const TSourceLoc&, const char* op, bool builtIn = false) { } + void explicitFloat32Check(const TSourceLoc&, const char* op, bool builtIn = false) { } + void explicitFloat64Check(const TSourceLoc&, const char* op, bool builtIn = false) { } + bool relaxedErrors() const { return false; } + bool suppressWarnings() const { return true; } + bool isForwardCompatible() const { return false; } +#else + bool forwardCompatible; // true if errors are to be given for use of deprecated features + EProfile profile; // the declared profile in the shader (core by default) + bool isEsProfile() const { return profile == EEsProfile; } + void requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc); + void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions, + const char* const extensions[], const char* featureDesc); + void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, const char* extension, + const char* featureDesc); + virtual void initializeExtensionBehavior(); + virtual void checkDeprecated(const TSourceLoc&, int queryProfiles, int depVersion, const char* featureDesc); + virtual void requireNotRemoved(const TSourceLoc&, int queryProfiles, int removedVersion, const char* featureDesc); + virtual void requireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], + const char* featureDesc); + virtual void ppRequireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], + const char* featureDesc); + virtual TExtensionBehavior getExtensionBehavior(const char*); + virtual bool extensionTurnedOn(const char* const extension); + virtual bool extensionsTurnedOn(int numExtensions, const char* const extensions[]); + virtual void updateExtensionBehavior(int line, const char* const extension, const char* behavior); + virtual void updateExtensionBehavior(const char* const extension, TExtensionBehavior); + virtual bool checkExtensionsRequested(const TSourceLoc&, int numExtensions, const char* const extensions[], + const char* featureDesc); + virtual void checkExtensionStage(const TSourceLoc&, const char* const extension); + virtual void fullIntegerCheck(const TSourceLoc&, const char* op); + + virtual void unimplemented(const TSourceLoc&, const char* featureDesc); + virtual void doubleCheck(const TSourceLoc&, const char* op); + virtual void float16Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void float16ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false); + virtual bool float16Arithmetic(); + virtual void requireFloat16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc); + virtual void int16ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false); + virtual bool int16Arithmetic(); + virtual void requireInt16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc); + virtual void int8ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false); + virtual bool int8Arithmetic(); + virtual void requireInt8Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc); + virtual void float16OpaqueCheck(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void int64Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void explicitInt8Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void explicitInt16Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void explicitInt32Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void explicitFloat32Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void explicitFloat64Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void fcoopmatCheck(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void intcoopmatCheck(const TSourceLoc&, const char *op, bool builtIn = false); + bool relaxedErrors() const { return (messages & EShMsgRelaxedErrors) != 0; } + bool suppressWarnings() const { return (messages & EShMsgSuppressWarnings) != 0; } + bool isForwardCompatible() const { return forwardCompatible; } +#endif // GLSLANG_WEB + virtual void spvRemoved(const TSourceLoc&, const char* op); + virtual void vulkanRemoved(const TSourceLoc&, const char* op); + virtual void requireVulkan(const TSourceLoc&, const char* op); + virtual void requireSpv(const TSourceLoc&, const char* op); + + +#if defined(GLSLANG_WEB) && !defined(GLSLANG_WEB_DEVEL) + void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) { addError(); } + void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) { } + void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) { addError(); } + void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) { } +#else + virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) = 0; + virtual void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) = 0; + virtual void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) = 0; + virtual void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) = 0; +#endif + + void addError() { ++numErrors; } + int getNumErrors() const { return numErrors; } + + void setScanner(TInputScanner* scanner) { currentScanner = scanner; } + TInputScanner* getScanner() const { return currentScanner; } + const TSourceLoc& getCurrentLoc() const { return currentScanner->getSourceLoc(); } + void setCurrentLine(int line) { currentScanner->setLine(line); } + void setCurrentColumn(int col) { currentScanner->setColumn(col); } + void setCurrentSourceName(const char* name) { currentScanner->setFile(name); } + void setCurrentString(int string) { currentScanner->setString(string); } + + void getPreamble(std::string&); +#ifdef ENABLE_HLSL + bool isReadingHLSL() const { return (messages & EShMsgReadHlsl) == EShMsgReadHlsl; } + bool hlslEnable16BitTypes() const { return (messages & EShMsgHlslEnable16BitTypes) != 0; } + bool hlslDX9Compatible() const { return (messages & EShMsgHlslDX9Compatible) != 0; } +#else + bool isReadingHLSL() const { return false; } +#endif + + TInfoSink& infoSink; + + // compilation mode + int version; // version, updated by #version in the shader + EShLanguage language; // really the stage + SpvVersion spvVersion; + TIntermediate& intermediate; // helper for making and hooking up pieces of the parse tree + +protected: + TMap extensionBehavior; // for each extension string, what its current behavior is set to + EShMessages messages; // errors/warnings/rule-sets + int numErrors; // number of compile-time errors encountered + TInputScanner* currentScanner; + +private: + explicit TParseVersions(const TParseVersions&); + TParseVersions& operator=(const TParseVersions&); +}; + +} // end namespace glslang + +#endif // _PARSE_VERSIONS_INCLUDED_ diff --git a/mac/include/glslang/MachineIndependent/preprocessor/PpContext.h b/mac/include/glslang/MachineIndependent/preprocessor/PpContext.h new file mode 100644 index 00000000..714b5ead --- /dev/null +++ b/mac/include/glslang/MachineIndependent/preprocessor/PpContext.h @@ -0,0 +1,703 @@ +// +// Copyright (C) 2013 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ + +#ifndef PPCONTEXT_H +#define PPCONTEXT_H + +#include +#include +#include + +#include "../ParseHelper.h" +#include "PpTokens.h" + +/* windows only pragma */ +#ifdef _MSC_VER + #pragma warning(disable : 4127) +#endif + +namespace glslang { + +class TPpToken { +public: + TPpToken() { clear(); } + void clear() + { + space = false; + i64val = 0; + loc.init(); + name[0] = 0; + } + + // Used for comparing macro definitions, so checks what is relevant for that. + bool operator==(const TPpToken& right) const + { + return space == right.space && + ival == right.ival && dval == right.dval && i64val == right.i64val && + strncmp(name, right.name, MaxTokenLength) == 0; + } + bool operator!=(const TPpToken& right) const { return ! operator==(right); } + + TSourceLoc loc; + // True if a space (for white space or a removed comment) should also be + // recognized, in front of the token returned: + bool space; + // Numeric value of the token: + union { + int ival; + double dval; + long long i64val; + }; + // Text string of the token: + char name[MaxTokenLength + 1]; +}; + +class TStringAtomMap { +// +// Implementation is in PpAtom.cpp +// +// Maintain a bi-directional mapping between relevant preprocessor strings and +// "atoms" which a unique integers (small, contiguous, not hash-like) per string. +// +public: + TStringAtomMap(); + + // Map string -> atom. + // Return 0 if no existing string. + int getAtom(const char* s) const + { + auto it = atomMap.find(s); + return it == atomMap.end() ? 0 : it->second; + } + + // Map a new or existing string -> atom, inventing a new atom if necessary. + int getAddAtom(const char* s) + { + int atom = getAtom(s); + if (atom == 0) { + atom = nextAtom++; + addAtomFixed(s, atom); + } + return atom; + } + + // Map atom -> string. + const char* getString(int atom) const { return stringMap[atom]->c_str(); } + +protected: + TStringAtomMap(TStringAtomMap&); + TStringAtomMap& operator=(TStringAtomMap&); + + TUnorderedMap atomMap; + TVector stringMap; // these point into the TString in atomMap + int nextAtom; + + // Bad source characters can lead to bad atoms, so gracefully handle those by + // pre-filling the table with them (to avoid if tests later). + TString badToken; + + // Add bi-directional mappings: + // - string -> atom + // - atom -> string + void addAtomFixed(const char* s, int atom) + { + auto it = atomMap.insert(std::pair(s, atom)).first; + if (stringMap.size() < (size_t)atom + 1) + stringMap.resize(atom + 100, &badToken); + stringMap[atom] = &it->first; + } +}; + +class TInputScanner; + +enum MacroExpandResult { + MacroExpandNotStarted, // macro not expanded, which might not be an error + MacroExpandError, // a clear error occurred while expanding, no expansion + MacroExpandStarted, // macro expansion process has started + MacroExpandUndef // macro is undefined and will be expanded +}; + +// This class is the result of turning a huge pile of C code communicating through globals +// into a class. This was done to allowing instancing to attain thread safety. +// Don't expect too much in terms of OO design. +class TPpContext { +public: + TPpContext(TParseContextBase&, const std::string& rootFileName, TShader::Includer&); + virtual ~TPpContext(); + + void setPreamble(const char* preamble, size_t length); + + int tokenize(TPpToken& ppToken); + int tokenPaste(int token, TPpToken&); + + class tInput { + public: + tInput(TPpContext* p) : done(false), pp(p) { } + virtual ~tInput() { } + + virtual int scan(TPpToken*) = 0; + virtual int getch() = 0; + virtual void ungetch() = 0; + virtual bool peekPasting() { return false; } // true when about to see ## + virtual bool peekContinuedPasting(int) { return false; } // true when non-spaced tokens can paste + virtual bool endOfReplacementList() { return false; } // true when at the end of a macro replacement list (RHS of #define) + virtual bool isMacroInput() { return false; } + + // Will be called when we start reading tokens from this instance + virtual void notifyActivated() {} + // Will be called when we do not read tokens from this instance anymore + virtual void notifyDeleted() {} + protected: + bool done; + TPpContext* pp; + }; + + void setInput(TInputScanner& input, bool versionWillBeError); + + void pushInput(tInput* in) + { + inputStack.push_back(in); + in->notifyActivated(); + } + void popInput() + { + inputStack.back()->notifyDeleted(); + delete inputStack.back(); + inputStack.pop_back(); + } + + // + // From PpTokens.cpp + // + + // Capture the needed parts of a token stream for macro recording/playback. + class TokenStream { + public: + // Manage a stream of these 'Token', which capture the relevant parts + // of a TPpToken, plus its atom. + class Token { + public: + Token(int atom, const TPpToken& ppToken) : + atom(atom), + space(ppToken.space), + i64val(ppToken.i64val), + name(ppToken.name) { } + int get(TPpToken& ppToken) + { + ppToken.clear(); + ppToken.space = space; + ppToken.i64val = i64val; + snprintf(ppToken.name, sizeof(ppToken.name), "%s", name.c_str()); + return atom; + } + bool isAtom(int a) const { return atom == a; } + int getAtom() const { return atom; } + bool nonSpaced() const { return !space; } + protected: + Token() {} + int atom; + bool space; // did a space precede the token? + long long i64val; + TString name; + }; + + TokenStream() : currentPos(0) { } + + void putToken(int token, TPpToken* ppToken); + bool peekToken(int atom) { return !atEnd() && stream[currentPos].isAtom(atom); } + bool peekContinuedPasting(int atom) + { + // This is basically necessary because, for example, the PP + // tokenizer only accepts valid numeric-literals plus suffixes, so + // separates numeric-literals plus bad suffix into two tokens, which + // should get both pasted together as one token when token pasting. + // + // The following code is a bit more generalized than the above example. + if (!atEnd() && atom == PpAtomIdentifier && stream[currentPos].nonSpaced()) { + switch(stream[currentPos].getAtom()) { + case PpAtomConstInt: + case PpAtomConstUint: + case PpAtomConstInt64: + case PpAtomConstUint64: + case PpAtomConstInt16: + case PpAtomConstUint16: + case PpAtomConstFloat: + case PpAtomConstDouble: + case PpAtomConstFloat16: + case PpAtomConstString: + case PpAtomIdentifier: + return true; + default: + break; + } + } + + return false; + } + int getToken(TParseContextBase&, TPpToken*); + bool atEnd() { return currentPos >= stream.size(); } + bool peekTokenizedPasting(bool lastTokenPastes); + bool peekUntokenizedPasting(); + void reset() { currentPos = 0; } + + protected: + TVector stream; + size_t currentPos; + }; + + // + // From Pp.cpp + // + + struct MacroSymbol { + MacroSymbol() : functionLike(0), busy(0), undef(0) { } + TVector args; + TokenStream body; + unsigned functionLike : 1; // 0 means object-like, 1 means function-like + unsigned busy : 1; + unsigned undef : 1; + }; + + typedef TMap TSymbolMap; + TSymbolMap macroDefs; // map atoms to macro definitions + MacroSymbol* lookupMacroDef(int atom) + { + auto existingMacroIt = macroDefs.find(atom); + return (existingMacroIt == macroDefs.end()) ? nullptr : &(existingMacroIt->second); + } + void addMacroDef(int atom, MacroSymbol& macroDef) { macroDefs[atom] = macroDef; } + +protected: + TPpContext(TPpContext&); + TPpContext& operator=(TPpContext&); + + TStringAtomMap atomStrings; + char* preamble; // string to parse, all before line 1 of string 0, it is 0 if no preamble + int preambleLength; + char** strings; // official strings of shader, starting a string 0 line 1 + size_t* lengths; + int numStrings; // how many official strings there are + int currentString; // which string we're currently parsing (-1 for preamble) + + // Scanner data: + int previous_token; + TParseContextBase& parseContext; + + // Get the next token from *stack* of input sources, popping input sources + // that are out of tokens, down until an input source is found that has a token. + // Return EndOfInput when there are no more tokens to be found by doing this. + int scanToken(TPpToken* ppToken) + { + int token = EndOfInput; + + while (! inputStack.empty()) { + token = inputStack.back()->scan(ppToken); + if (token != EndOfInput || inputStack.empty()) + break; + popInput(); + } + + return token; + } + int getChar() { return inputStack.back()->getch(); } + void ungetChar() { inputStack.back()->ungetch(); } + bool peekPasting() { return !inputStack.empty() && inputStack.back()->peekPasting(); } + bool peekContinuedPasting(int a) + { + return !inputStack.empty() && inputStack.back()->peekContinuedPasting(a); + } + bool endOfReplacementList() { return inputStack.empty() || inputStack.back()->endOfReplacementList(); } + bool isMacroInput() { return inputStack.size() > 0 && inputStack.back()->isMacroInput(); } + + static const int maxIfNesting = 65; + + int ifdepth; // current #if-#else-#endif nesting in the cpp.c file (pre-processor) + bool elseSeen[maxIfNesting]; // Keep a track of whether an else has been seen at a particular depth + int elsetracker; // #if-#else and #endif constructs...Counter. + + class tMacroInput : public tInput { + public: + tMacroInput(TPpContext* pp) : tInput(pp), prepaste(false), postpaste(false) { } + virtual ~tMacroInput() + { + for (size_t i = 0; i < args.size(); ++i) + delete args[i]; + for (size_t i = 0; i < expandedArgs.size(); ++i) + delete expandedArgs[i]; + } + + virtual int scan(TPpToken*) override; + virtual int getch() override { assert(0); return EndOfInput; } + virtual void ungetch() override { assert(0); } + bool peekPasting() override { return prepaste; } + bool peekContinuedPasting(int a) override { return mac->body.peekContinuedPasting(a); } + bool endOfReplacementList() override { return mac->body.atEnd(); } + bool isMacroInput() override { return true; } + + MacroSymbol *mac; + TVector args; + TVector expandedArgs; + + protected: + bool prepaste; // true if we are just before ## + bool postpaste; // true if we are right after ## + }; + + class tMarkerInput : public tInput { + public: + tMarkerInput(TPpContext* pp) : tInput(pp) { } + virtual int scan(TPpToken*) override + { + if (done) + return EndOfInput; + done = true; + + return marker; + } + virtual int getch() override { assert(0); return EndOfInput; } + virtual void ungetch() override { assert(0); } + static const int marker = -3; + }; + + class tZeroInput : public tInput { + public: + tZeroInput(TPpContext* pp) : tInput(pp) { } + virtual int scan(TPpToken*) override; + virtual int getch() override { assert(0); return EndOfInput; } + virtual void ungetch() override { assert(0); } + }; + + std::vector inputStack; + bool errorOnVersion; + bool versionSeen; + + // + // from Pp.cpp + // + + // Used to obtain #include content. + TShader::Includer& includer; + + int CPPdefine(TPpToken * ppToken); + int CPPundef(TPpToken * ppToken); + int CPPelse(int matchelse, TPpToken * ppToken); + int extraTokenCheck(int atom, TPpToken* ppToken, int token); + int eval(int token, int precedence, bool shortCircuit, int& res, bool& err, TPpToken * ppToken); + int evalToToken(int token, bool shortCircuit, int& res, bool& err, TPpToken * ppToken); + int CPPif (TPpToken * ppToken); + int CPPifdef(int defined, TPpToken * ppToken); + int CPPinclude(TPpToken * ppToken); + int CPPline(TPpToken * ppToken); + int CPPerror(TPpToken * ppToken); + int CPPpragma(TPpToken * ppToken); + int CPPversion(TPpToken * ppToken); + int CPPextension(TPpToken * ppToken); + int readCPPline(TPpToken * ppToken); + int scanHeaderName(TPpToken* ppToken, char delimit); + TokenStream* PrescanMacroArg(TokenStream&, TPpToken*, bool newLineOkay); + MacroExpandResult MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay); + + // + // From PpTokens.cpp + // + void pushTokenStreamInput(TokenStream&, bool pasting = false); + void UngetToken(int token, TPpToken*); + + class tTokenInput : public tInput { + public: + tTokenInput(TPpContext* pp, TokenStream* t, bool prepasting) : + tInput(pp), + tokens(t), + lastTokenPastes(prepasting) { } + virtual int scan(TPpToken *ppToken) override { return tokens->getToken(pp->parseContext, ppToken); } + virtual int getch() override { assert(0); return EndOfInput; } + virtual void ungetch() override { assert(0); } + virtual bool peekPasting() override { return tokens->peekTokenizedPasting(lastTokenPastes); } + bool peekContinuedPasting(int a) override { return tokens->peekContinuedPasting(a); } + protected: + TokenStream* tokens; + bool lastTokenPastes; // true if the last token in the input is to be pasted, rather than consumed as a token + }; + + class tUngotTokenInput : public tInput { + public: + tUngotTokenInput(TPpContext* pp, int t, TPpToken* p) : tInput(pp), token(t), lval(*p) { } + virtual int scan(TPpToken *) override; + virtual int getch() override { assert(0); return EndOfInput; } + virtual void ungetch() override { assert(0); } + protected: + int token; + TPpToken lval; + }; + + // + // From PpScanner.cpp + // + class tStringInput : public tInput { + public: + tStringInput(TPpContext* pp, TInputScanner& i) : tInput(pp), input(&i) { } + virtual int scan(TPpToken*) override; + + // Scanner used to get source stream characters. + // - Escaped newlines are handled here, invisibly to the caller. + // - All forms of newline are handled, and turned into just a '\n'. + int getch() override + { + int ch = input->get(); + + if (ch == '\\') { + // Move past escaped newlines, as many as sequentially exist + do { + if (input->peek() == '\r' || input->peek() == '\n') { + bool allowed = pp->parseContext.lineContinuationCheck(input->getSourceLoc(), pp->inComment); + if (! allowed && pp->inComment) + return '\\'; + + // escape one newline now + ch = input->get(); + int nextch = input->get(); + if (ch == '\r' && nextch == '\n') + ch = input->get(); + else + ch = nextch; + } else + return '\\'; + } while (ch == '\\'); + } + + // handle any non-escaped newline + if (ch == '\r' || ch == '\n') { + if (ch == '\r' && input->peek() == '\n') + input->get(); + return '\n'; + } + + return ch; + } + + // Scanner used to backup the source stream characters. Newlines are + // handled here, invisibly to the caller, meaning have to undo exactly + // what getch() above does (e.g., don't leave things in the middle of a + // sequence of escaped newlines). + void ungetch() override + { + input->unget(); + + do { + int ch = input->peek(); + if (ch == '\r' || ch == '\n') { + if (ch == '\n') { + // correct for two-character newline + input->unget(); + if (input->peek() != '\r') + input->get(); + } + // now in front of a complete newline, move past an escape character + input->unget(); + if (input->peek() == '\\') + input->unget(); + else { + input->get(); + break; + } + } else + break; + } while (true); + } + + protected: + TInputScanner* input; + }; + + // Holds a reference to included file data, as well as a + // prologue and an epilogue string. This can be scanned using the tInput + // interface and acts as a single source string. + class TokenizableIncludeFile : public tInput { + public: + // Copies prologue and epilogue. The includedFile must remain valid + // until this TokenizableIncludeFile is no longer used. + TokenizableIncludeFile(const TSourceLoc& startLoc, + const std::string& prologue, + TShader::Includer::IncludeResult* includedFile, + const std::string& epilogue, + TPpContext* pp) + : tInput(pp), + prologue_(prologue), + epilogue_(epilogue), + includedFile_(includedFile), + scanner(3, strings, lengths, nullptr, 0, 0, true), + prevScanner(nullptr), + stringInput(pp, scanner) + { + strings[0] = prologue_.data(); + strings[1] = includedFile_->headerData; + strings[2] = epilogue_.data(); + + lengths[0] = prologue_.size(); + lengths[1] = includedFile_->headerLength; + lengths[2] = epilogue_.size(); + + scanner.setLine(startLoc.line); + scanner.setString(startLoc.string); + + scanner.setFile(startLoc.getFilenameStr(), 0); + scanner.setFile(startLoc.getFilenameStr(), 1); + scanner.setFile(startLoc.getFilenameStr(), 2); + } + + // tInput methods: + int scan(TPpToken* t) override { return stringInput.scan(t); } + int getch() override { return stringInput.getch(); } + void ungetch() override { stringInput.ungetch(); } + + void notifyActivated() override + { + prevScanner = pp->parseContext.getScanner(); + pp->parseContext.setScanner(&scanner); + pp->push_include(includedFile_); + } + + void notifyDeleted() override + { + pp->parseContext.setScanner(prevScanner); + pp->pop_include(); + } + + private: + TokenizableIncludeFile& operator=(const TokenizableIncludeFile&); + + // Stores the prologue for this string. + const std::string prologue_; + + // Stores the epilogue for this string. + const std::string epilogue_; + + // Points to the IncludeResult that this TokenizableIncludeFile represents. + TShader::Includer::IncludeResult* includedFile_; + + // Will point to prologue_, includedFile_->headerData and epilogue_ + // This is passed to scanner constructor. + // These do not own the storage and it must remain valid until this + // object has been destroyed. + const char* strings[3]; + // Length of str_, passed to scanner constructor. + size_t lengths[3]; + // Scans over str_. + TInputScanner scanner; + // The previous effective scanner before the scanner in this instance + // has been activated. + TInputScanner* prevScanner; + // Delegate object implementing the tInput interface. + tStringInput stringInput; + }; + + int ScanFromString(char* s); + void missingEndifCheck(); + int lFloatConst(int len, int ch, TPpToken* ppToken); + int characterLiteral(TPpToken* ppToken); + + void push_include(TShader::Includer::IncludeResult* result) + { + currentSourceFile = result->headerName; + includeStack.push(result); + } + + void pop_include() + { + TShader::Includer::IncludeResult* include = includeStack.top(); + includeStack.pop(); + includer.releaseInclude(include); + if (includeStack.empty()) { + currentSourceFile = rootFileName; + } else { + currentSourceFile = includeStack.top()->headerName; + } + } + + bool inComment; + std::string rootFileName; + std::stack includeStack; + std::string currentSourceFile; + + std::istringstream strtodStream; + bool disableEscapeSequences; +}; + +} // end namespace glslang + +#endif // PPCONTEXT_H diff --git a/mac/include/glslang/MachineIndependent/preprocessor/PpTokens.h b/mac/include/glslang/MachineIndependent/preprocessor/PpTokens.h new file mode 100644 index 00000000..7b0f8155 --- /dev/null +++ b/mac/include/glslang/MachineIndependent/preprocessor/PpTokens.h @@ -0,0 +1,179 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ + +#ifndef PARSER_H +#define PARSER_H + +namespace glslang { + +// Multi-character tokens +enum EFixedAtoms { + // single character tokens get their own char value as their token; start here for multi-character tokens + PpAtomMaxSingle = 127, + + // replace bad character tokens with this, to avoid accidental aliasing with the below + PpAtomBadToken, + + // Operators + + PPAtomAddAssign, + PPAtomSubAssign, + PPAtomMulAssign, + PPAtomDivAssign, + PPAtomModAssign, + + PpAtomRight, + PpAtomLeft, + + PpAtomRightAssign, + PpAtomLeftAssign, + PpAtomAndAssign, + PpAtomOrAssign, + PpAtomXorAssign, + + PpAtomAnd, + PpAtomOr, + PpAtomXor, + + PpAtomEQ, + PpAtomNE, + PpAtomGE, + PpAtomLE, + + PpAtomDecrement, + PpAtomIncrement, + + PpAtomColonColon, + + PpAtomPaste, + + // Constants + + PpAtomConstInt, + PpAtomConstUint, + PpAtomConstInt64, + PpAtomConstUint64, + PpAtomConstInt16, + PpAtomConstUint16, + PpAtomConstFloat, + PpAtomConstDouble, + PpAtomConstFloat16, + PpAtomConstString, + + // Identifiers + PpAtomIdentifier, + + // preprocessor "keywords" + + PpAtomDefine, + PpAtomUndef, + + PpAtomIf, + PpAtomIfdef, + PpAtomIfndef, + PpAtomElse, + PpAtomElif, + PpAtomEndif, + + PpAtomLine, + PpAtomPragma, + PpAtomError, + + // #version ... + PpAtomVersion, + PpAtomCore, + PpAtomCompatibility, + PpAtomEs, + + // #extension + PpAtomExtension, + + // __LINE__, __FILE__, __VERSION__ + + PpAtomLineMacro, + PpAtomFileMacro, + PpAtomVersionMacro, + + // #include + PpAtomInclude, + + PpAtomLast, +}; + +} // end namespace glslang + +#endif /* not PARSER_H */ diff --git a/mac/include/glslang/MachineIndependent/propagateNoContraction.h b/mac/include/glslang/MachineIndependent/propagateNoContraction.h new file mode 100644 index 00000000..8521ad7d --- /dev/null +++ b/mac/include/glslang/MachineIndependent/propagateNoContraction.h @@ -0,0 +1,55 @@ +// +// Copyright (C) 2015-2016 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Visit the nodes in the glslang intermediate tree representation to +// propagate 'noContraction' qualifier. +// + +#pragma once + +#include "../Include/intermediate.h" + +namespace glslang { + +// Propagates the 'precise' qualifier for objects (objects marked with +// 'noContraction' qualifier) from the shader source specified 'precise' +// variables to all the involved objects, and add 'noContraction' qualifier for +// the involved arithmetic operations. +// Note that the same qualifier: 'noContraction' is used in both object nodes +// and arithmetic operation nodes, but has different meaning. For object nodes, +// 'noContraction' means the object is 'precise'; and for arithmetic operation +// nodes, it means the operation should not be contracted. +void PropagateNoContraction(const glslang::TIntermediate& intermediate); +}; diff --git a/mac/include/glslang/MachineIndependent/reflection.h b/mac/include/glslang/MachineIndependent/reflection.h new file mode 100644 index 00000000..0c33de45 --- /dev/null +++ b/mac/include/glslang/MachineIndependent/reflection.h @@ -0,0 +1,223 @@ +// +// Copyright (C) 2013-2016 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef GLSLANG_WEB + +#ifndef _REFLECTION_INCLUDED +#define _REFLECTION_INCLUDED + +#include "../Public/ShaderLang.h" +#include "../Include/Types.h" + +#include +#include + +// +// A reflection database and its interface, consistent with the OpenGL API reflection queries. +// + +namespace glslang { + +class TIntermediate; +class TIntermAggregate; +class TReflectionTraverser; + +// The full reflection database +class TReflection { +public: + TReflection(EShReflectionOptions opts, EShLanguage first, EShLanguage last) + : options(opts), firstStage(first), lastStage(last), badReflection(TObjectReflection::badReflection()) + { + for (int dim=0; dim<3; ++dim) + localSize[dim] = 0; + } + + virtual ~TReflection() {} + + // grow the reflection stage by stage + bool addStage(EShLanguage, const TIntermediate&); + + // for mapping a uniform index to a uniform object's description + int getNumUniforms() { return (int)indexToUniform.size(); } + const TObjectReflection& getUniform(int i) const + { + if (i >= 0 && i < (int)indexToUniform.size()) + return indexToUniform[i]; + else + return badReflection; + } + + // for mapping a block index to the block's description + int getNumUniformBlocks() const { return (int)indexToUniformBlock.size(); } + const TObjectReflection& getUniformBlock(int i) const + { + if (i >= 0 && i < (int)indexToUniformBlock.size()) + return indexToUniformBlock[i]; + else + return badReflection; + } + + // for mapping an pipeline input index to the input's description + int getNumPipeInputs() { return (int)indexToPipeInput.size(); } + const TObjectReflection& getPipeInput(int i) const + { + if (i >= 0 && i < (int)indexToPipeInput.size()) + return indexToPipeInput[i]; + else + return badReflection; + } + + // for mapping an pipeline output index to the output's description + int getNumPipeOutputs() { return (int)indexToPipeOutput.size(); } + const TObjectReflection& getPipeOutput(int i) const + { + if (i >= 0 && i < (int)indexToPipeOutput.size()) + return indexToPipeOutput[i]; + else + return badReflection; + } + + // for mapping from an atomic counter to the uniform index + int getNumAtomicCounters() const { return (int)atomicCounterUniformIndices.size(); } + const TObjectReflection& getAtomicCounter(int i) const + { + if (i >= 0 && i < (int)atomicCounterUniformIndices.size()) + return getUniform(atomicCounterUniformIndices[i]); + else + return badReflection; + } + + // for mapping a buffer variable index to a buffer variable object's description + int getNumBufferVariables() { return (int)indexToBufferVariable.size(); } + const TObjectReflection& getBufferVariable(int i) const + { + if (i >= 0 && i < (int)indexToBufferVariable.size()) + return indexToBufferVariable[i]; + else + return badReflection; + } + + // for mapping a storage block index to the storage block's description + int getNumStorageBuffers() const { return (int)indexToBufferBlock.size(); } + const TObjectReflection& getStorageBufferBlock(int i) const + { + if (i >= 0 && i < (int)indexToBufferBlock.size()) + return indexToBufferBlock[i]; + else + return badReflection; + } + + // for mapping any name to its index (block names, uniform names and input/output names) + int getIndex(const char* name) const + { + TNameToIndex::const_iterator it = nameToIndex.find(name); + if (it == nameToIndex.end()) + return -1; + else + return it->second; + } + + // see getIndex(const char*) + int getIndex(const TString& name) const { return getIndex(name.c_str()); } + + + // for mapping any name to its index (only pipe input/output names) + int getPipeIOIndex(const char* name, const bool inOrOut) const + { + TNameToIndex::const_iterator it = inOrOut ? pipeInNameToIndex.find(name) : pipeOutNameToIndex.find(name); + if (it == (inOrOut ? pipeInNameToIndex.end() : pipeOutNameToIndex.end())) + return -1; + else + return it->second; + } + + // see gePipeIOIndex(const char*, const bool) + int getPipeIOIndex(const TString& name, const bool inOrOut) const { return getPipeIOIndex(name.c_str(), inOrOut); } + + // Thread local size + unsigned getLocalSize(int dim) const { return dim <= 2 ? localSize[dim] : 0; } + + void dump(); + +protected: + friend class glslang::TReflectionTraverser; + + void buildCounterIndices(const TIntermediate&); + void buildUniformStageMask(const TIntermediate& intermediate); + void buildAttributeReflection(EShLanguage, const TIntermediate&); + + // Need a TString hash: typedef std::unordered_map TNameToIndex; + typedef std::map TNameToIndex; + typedef std::vector TMapIndexToReflection; + typedef std::vector TIndices; + + TMapIndexToReflection& GetBlockMapForStorage(TStorageQualifier storage) + { + if ((options & EShReflectionSeparateBuffers) && storage == EvqBuffer) + return indexToBufferBlock; + return indexToUniformBlock; + } + TMapIndexToReflection& GetVariableMapForStorage(TStorageQualifier storage) + { + if ((options & EShReflectionSeparateBuffers) && storage == EvqBuffer) + return indexToBufferVariable; + return indexToUniform; + } + + EShReflectionOptions options; + + EShLanguage firstStage; + EShLanguage lastStage; + + TObjectReflection badReflection; // return for queries of -1 or generally out of range; has expected descriptions with in it for this + TNameToIndex nameToIndex; // maps names to indexes; can hold all types of data: uniform/buffer and which function names have been processed + TNameToIndex pipeInNameToIndex; // maps pipe in names to indexes, this is a fix to seperate pipe I/O from uniforms and buffers. + TNameToIndex pipeOutNameToIndex; // maps pipe out names to indexes, this is a fix to seperate pipe I/O from uniforms and buffers. + TMapIndexToReflection indexToUniform; + TMapIndexToReflection indexToUniformBlock; + TMapIndexToReflection indexToBufferVariable; + TMapIndexToReflection indexToBufferBlock; + TMapIndexToReflection indexToPipeInput; + TMapIndexToReflection indexToPipeOutput; + TIndices atomicCounterUniformIndices; + + unsigned int localSize[3]; +}; + +} // end namespace glslang + +#endif // _REFLECTION_INCLUDED + +#endif // GLSLANG_WEB diff --git a/mac/include/glslang/Public/ShaderLang.h b/mac/include/glslang/Public/ShaderLang.h new file mode 100644 index 00000000..acb2a078 --- /dev/null +++ b/mac/include/glslang/Public/ShaderLang.h @@ -0,0 +1,927 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013-2016 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +#ifndef _COMPILER_INTERFACE_INCLUDED_ +#define _COMPILER_INTERFACE_INCLUDED_ + +#include "../Include/ResourceLimits.h" +#include "../MachineIndependent/Versions.h" + +#include +#include + +#ifdef _WIN32 +#define C_DECL __cdecl +//#ifdef SH_EXPORTING +// #define SH_IMPORT_EXPORT __declspec(dllexport) +//#else +// #define SH_IMPORT_EXPORT __declspec(dllimport) +//#endif +#define SH_IMPORT_EXPORT +#else +#define SH_IMPORT_EXPORT +#define C_DECL +#endif + +// +// This is the platform independent interface between an OGL driver +// and the shading language compiler/linker. +// + +#ifdef __cplusplus + extern "C" { +#endif + +// This should always increase, as some paths to do not consume +// a more major number. +// It should increment by one when new functionality is added. +#define GLSLANG_MINOR_VERSION 13 + +// +// Call before doing any other compiler/linker operations. +// +// (Call once per process, not once per thread.) +// +SH_IMPORT_EXPORT int ShInitialize(); + +// +// Call this at process shutdown to clean up memory. +// +SH_IMPORT_EXPORT int ShFinalize(); + +// +// Types of languages the compiler can consume. +// +typedef enum { + EShLangVertex, + EShLangTessControl, + EShLangTessEvaluation, + EShLangGeometry, + EShLangFragment, + EShLangCompute, + EShLangRayGen, + EShLangRayGenNV = EShLangRayGen, + EShLangIntersect, + EShLangIntersectNV = EShLangIntersect, + EShLangAnyHit, + EShLangAnyHitNV = EShLangAnyHit, + EShLangClosestHit, + EShLangClosestHitNV = EShLangClosestHit, + EShLangMiss, + EShLangMissNV = EShLangMiss, + EShLangCallable, + EShLangCallableNV = EShLangCallable, + EShLangTaskNV, + EShLangMeshNV, + LAST_ELEMENT_MARKER(EShLangCount), +} EShLanguage; // would be better as stage, but this is ancient now + +typedef enum { + EShLangVertexMask = (1 << EShLangVertex), + EShLangTessControlMask = (1 << EShLangTessControl), + EShLangTessEvaluationMask = (1 << EShLangTessEvaluation), + EShLangGeometryMask = (1 << EShLangGeometry), + EShLangFragmentMask = (1 << EShLangFragment), + EShLangComputeMask = (1 << EShLangCompute), + EShLangRayGenMask = (1 << EShLangRayGen), + EShLangRayGenNVMask = EShLangRayGenMask, + EShLangIntersectMask = (1 << EShLangIntersect), + EShLangIntersectNVMask = EShLangIntersectMask, + EShLangAnyHitMask = (1 << EShLangAnyHit), + EShLangAnyHitNVMask = EShLangAnyHitMask, + EShLangClosestHitMask = (1 << EShLangClosestHit), + EShLangClosestHitNVMask = EShLangClosestHitMask, + EShLangMissMask = (1 << EShLangMiss), + EShLangMissNVMask = EShLangMissMask, + EShLangCallableMask = (1 << EShLangCallable), + EShLangCallableNVMask = EShLangCallableMask, + EShLangTaskNVMask = (1 << EShLangTaskNV), + EShLangMeshNVMask = (1 << EShLangMeshNV), + LAST_ELEMENT_MARKER(EShLanguageMaskCount), +} EShLanguageMask; + +namespace glslang { + +class TType; + +typedef enum { + EShSourceNone, + EShSourceGlsl, // GLSL, includes ESSL (OpenGL ES GLSL) + EShSourceHlsl, // HLSL + LAST_ELEMENT_MARKER(EShSourceCount), +} EShSource; // if EShLanguage were EShStage, this could be EShLanguage instead + +typedef enum { + EShClientNone, // use when there is no client, e.g. for validation + EShClientVulkan, + EShClientOpenGL, + LAST_ELEMENT_MARKER(EShClientCount), +} EShClient; + +typedef enum { + EShTargetNone, + EShTargetSpv, // SPIR-V (preferred spelling) + EshTargetSpv = EShTargetSpv, // legacy spelling + LAST_ELEMENT_MARKER(EShTargetCount), +} EShTargetLanguage; + +typedef enum { + EShTargetVulkan_1_0 = (1 << 22), // Vulkan 1.0 + EShTargetVulkan_1_1 = (1 << 22) | (1 << 12), // Vulkan 1.1 + EShTargetVulkan_1_2 = (1 << 22) | (2 << 12), // Vulkan 1.2 + EShTargetOpenGL_450 = 450, // OpenGL + LAST_ELEMENT_MARKER(EShTargetClientVersionCount), +} EShTargetClientVersion; + +typedef EShTargetClientVersion EshTargetClientVersion; + +typedef enum { + EShTargetSpv_1_0 = (1 << 16), // SPIR-V 1.0 + EShTargetSpv_1_1 = (1 << 16) | (1 << 8), // SPIR-V 1.1 + EShTargetSpv_1_2 = (1 << 16) | (2 << 8), // SPIR-V 1.2 + EShTargetSpv_1_3 = (1 << 16) | (3 << 8), // SPIR-V 1.3 + EShTargetSpv_1_4 = (1 << 16) | (4 << 8), // SPIR-V 1.4 + EShTargetSpv_1_5 = (1 << 16) | (5 << 8), // SPIR-V 1.5 + LAST_ELEMENT_MARKER(EShTargetLanguageVersionCount), +} EShTargetLanguageVersion; + +struct TInputLanguage { + EShSource languageFamily; // redundant information with other input, this one overrides when not EShSourceNone + EShLanguage stage; // redundant information with other input, this one overrides when not EShSourceNone + EShClient dialect; + int dialectVersion; // version of client's language definition, not the client (when not EShClientNone) +}; + +struct TClient { + EShClient client; + EShTargetClientVersion version; // version of client itself (not the client's input dialect) +}; + +struct TTarget { + EShTargetLanguage language; + EShTargetLanguageVersion version; // version to target, if SPIR-V, defined by "word 1" of the SPIR-V header + bool hlslFunctionality1; // can target hlsl_functionality1 extension(s) +}; + +// All source/client/target versions and settings. +// Can override previous methods of setting, when items are set here. +// Expected to grow, as more are added, rather than growing parameter lists. +struct TEnvironment { + TInputLanguage input; // definition of the input language + TClient client; // what client is the overall compilation being done for? + TTarget target; // what to generate +}; + +const char* StageName(EShLanguage); + +} // end namespace glslang + +// +// Types of output the linker will create. +// +typedef enum { + EShExVertexFragment, + EShExFragment +} EShExecutable; + +// +// Optimization level for the compiler. +// +typedef enum { + EShOptNoGeneration, + EShOptNone, + EShOptSimple, // Optimizations that can be done quickly + EShOptFull, // Optimizations that will take more time + LAST_ELEMENT_MARKER(EshOptLevelCount), +} EShOptimizationLevel; + +// +// Texture and Sampler transformation mode. +// +typedef enum { + EShTexSampTransKeep, // keep textures and samplers as is (default) + EShTexSampTransUpgradeTextureRemoveSampler, // change texture w/o embeded sampler into sampled texture and throw away all samplers + LAST_ELEMENT_MARKER(EShTexSampTransCount), +} EShTextureSamplerTransformMode; + +// +// Message choices for what errors and warnings are given. +// +enum EShMessages { + EShMsgDefault = 0, // default is to give all required errors and extra warnings + EShMsgRelaxedErrors = (1 << 0), // be liberal in accepting input + EShMsgSuppressWarnings = (1 << 1), // suppress all warnings, except those required by the specification + EShMsgAST = (1 << 2), // print the AST intermediate representation + EShMsgSpvRules = (1 << 3), // issue messages for SPIR-V generation + EShMsgVulkanRules = (1 << 4), // issue messages for Vulkan-requirements of GLSL for SPIR-V + EShMsgOnlyPreprocessor = (1 << 5), // only print out errors produced by the preprocessor + EShMsgReadHlsl = (1 << 6), // use HLSL parsing rules and semantics + EShMsgCascadingErrors = (1 << 7), // get cascading errors; risks error-recovery issues, instead of an early exit + EShMsgKeepUncalled = (1 << 8), // for testing, don't eliminate uncalled functions + EShMsgHlslOffsets = (1 << 9), // allow block offsets to follow HLSL rules instead of GLSL rules + EShMsgDebugInfo = (1 << 10), // save debug information + EShMsgHlslEnable16BitTypes = (1 << 11), // enable use of 16-bit types in SPIR-V for HLSL + EShMsgHlslLegalization = (1 << 12), // enable HLSL Legalization messages + EShMsgHlslDX9Compatible = (1 << 13), // enable HLSL DX9 compatible mode (right now only for samplers) + EShMsgBuiltinSymbolTable = (1 << 14), // print the builtin symbol table + LAST_ELEMENT_MARKER(EShMsgCount), +}; + +// +// Options for building reflection +// +typedef enum { + EShReflectionDefault = 0, // default is original behaviour before options were added + EShReflectionStrictArraySuffix = (1 << 0), // reflection will follow stricter rules for array-of-structs suffixes + EShReflectionBasicArraySuffix = (1 << 1), // arrays of basic types will be appended with [0] as in GL reflection + EShReflectionIntermediateIO = (1 << 2), // reflect inputs and outputs to program, even with no vertex shader + EShReflectionSeparateBuffers = (1 << 3), // buffer variables and buffer blocks are reflected separately + EShReflectionAllBlockVariables = (1 << 4), // reflect all variables in blocks, even if they are inactive + EShReflectionUnwrapIOBlocks = (1 << 5), // unwrap input/output blocks the same as with uniform blocks + LAST_ELEMENT_MARKER(EShReflectionCount), +} EShReflectionOptions; + +// +// Build a table for bindings. This can be used for locating +// attributes, uniforms, globals, etc., as needed. +// +typedef struct { + const char* name; + int binding; +} ShBinding; + +typedef struct { + int numBindings; + ShBinding* bindings; // array of bindings +} ShBindingTable; + +// +// ShHandle held by but opaque to the driver. It is allocated, +// managed, and de-allocated by the compiler/linker. It's contents +// are defined by and used by the compiler and linker. For example, +// symbol table information and object code passed from the compiler +// to the linker can be stored where ShHandle points. +// +// If handle creation fails, 0 will be returned. +// +typedef void* ShHandle; + +// +// Driver calls these to create and destroy compiler/linker +// objects. +// +SH_IMPORT_EXPORT ShHandle ShConstructCompiler(const EShLanguage, int debugOptions); // one per shader +SH_IMPORT_EXPORT ShHandle ShConstructLinker(const EShExecutable, int debugOptions); // one per shader pair +SH_IMPORT_EXPORT ShHandle ShConstructUniformMap(); // one per uniform namespace (currently entire program object) +SH_IMPORT_EXPORT void ShDestruct(ShHandle); + +// +// The return value of ShCompile is boolean, non-zero indicating +// success. +// +// The info-log should be written by ShCompile into +// ShHandle, so it can answer future queries. +// +SH_IMPORT_EXPORT int ShCompile( + const ShHandle, + const char* const shaderStrings[], + const int numStrings, + const int* lengths, + const EShOptimizationLevel, + const TBuiltInResource *resources, + int debugOptions, + int defaultVersion = 110, // use 100 for ES environment, overridden by #version in shader + bool forwardCompatible = false, // give errors for use of deprecated features + EShMessages messages = EShMsgDefault // warnings and errors + ); + +SH_IMPORT_EXPORT int ShLinkExt( + const ShHandle, // linker object + const ShHandle h[], // compiler objects to link together + const int numHandles); + +// +// ShSetEncrpytionMethod is a place-holder for specifying +// how source code is encrypted. +// +SH_IMPORT_EXPORT void ShSetEncryptionMethod(ShHandle); + +// +// All the following return 0 if the information is not +// available in the object passed down, or the object is bad. +// +SH_IMPORT_EXPORT const char* ShGetInfoLog(const ShHandle); +SH_IMPORT_EXPORT const void* ShGetExecutable(const ShHandle); +SH_IMPORT_EXPORT int ShSetVirtualAttributeBindings(const ShHandle, const ShBindingTable*); // to detect user aliasing +SH_IMPORT_EXPORT int ShSetFixedAttributeBindings(const ShHandle, const ShBindingTable*); // to force any physical mappings +// +// Tell the linker to never assign a vertex attribute to this list of physical attributes +// +SH_IMPORT_EXPORT int ShExcludeAttributes(const ShHandle, int *attributes, int count); + +// +// Returns the location ID of the named uniform. +// Returns -1 if error. +// +SH_IMPORT_EXPORT int ShGetUniformLocation(const ShHandle uniformMap, const char* name); + +#ifdef __cplusplus + } // end extern "C" +#endif + +//////////////////////////////////////////////////////////////////////////////////////////// +// +// Deferred-Lowering C++ Interface +// ----------------------------------- +// +// Below is a new alternate C++ interface, which deprecates the above +// opaque handle-based interface. +// +// The below is further designed to handle multiple compilation units per stage, where +// the intermediate results, including the parse tree, are preserved until link time, +// rather than the above interface which is designed to have each compilation unit +// lowered at compile time. In the above model, linking occurs on the lowered results, +// whereas in this model intra-stage linking can occur at the parse tree +// (treeRoot in TIntermediate) level, and then a full stage can be lowered. +// + +#include +#include +#include + +class TCompiler; +class TInfoSink; + +namespace glslang { + +const char* GetEsslVersionString(); +const char* GetGlslVersionString(); +int GetKhronosToolId(); + +class TIntermediate; +class TProgram; +class TPoolAllocator; + +// Call this exactly once per process before using anything else +bool InitializeProcess(); + +// Call once per process to tear down everything +void FinalizeProcess(); + +// Resource type for IO resolver +enum TResourceType { + EResSampler, + EResTexture, + EResImage, + EResUbo, + EResSsbo, + EResUav, + EResCount +}; + +// Make one TShader per shader that you will link into a program. Then +// - provide the shader through setStrings() or setStringsWithLengths() +// - optionally call setEnv*(), see below for more detail +// - optionally use setPreamble() to set a special shader string that will be +// processed before all others but won't affect the validity of #version +// - optionally call addProcesses() for each setting/transform, +// see comment for class TProcesses +// - call parse(): source language and target environment must be selected +// either by correct setting of EShMessages sent to parse(), or by +// explicitly calling setEnv*() +// - query the info logs +// +// N.B.: Does not yet support having the same TShader instance being linked into +// multiple programs. +// +// N.B.: Destruct a linked program *before* destructing the shaders linked into it. +// +class TShader { +public: + explicit TShader(EShLanguage); + virtual ~TShader(); + void setStrings(const char* const* s, int n); + void setStringsWithLengths(const char* const* s, const int* l, int n); + void setStringsWithLengthsAndNames( + const char* const* s, const int* l, const char* const* names, int n); + void setPreamble(const char* s) { preamble = s; } + void setEntryPoint(const char* entryPoint); + void setSourceEntryPoint(const char* sourceEntryPointName); + void addProcesses(const std::vector&); + + // IO resolver binding data: see comments in ShaderLang.cpp + void setShiftBinding(TResourceType res, unsigned int base); + void setShiftSamplerBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftTextureBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftImageBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftUboBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftUavBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftCbufferBinding(unsigned int base); // synonym for setShiftUboBinding + void setShiftSsboBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftBindingForSet(TResourceType res, unsigned int base, unsigned int set); + void setResourceSetBinding(const std::vector& base); + void setAutoMapBindings(bool map); + void setAutoMapLocations(bool map); + void addUniformLocationOverride(const char* name, int loc); + void setUniformLocationBase(int base); + void setInvertY(bool invert); +#ifdef ENABLE_HLSL + void setHlslIoMapping(bool hlslIoMap); + void setFlattenUniformArrays(bool flatten); +#endif + void setNoStorageFormat(bool useUnknownFormat); + void setNanMinMaxClamp(bool nanMinMaxClamp); + void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode); + + // For setting up the environment (cleared to nothingness in the constructor). + // These must be called so that parsing is done for the right source language and + // target environment, either indirectly through TranslateEnvironment() based on + // EShMessages et. al., or directly by the user. + // + // setEnvInput: The input source language and stage. If generating code for a + // specific client, the input client semantics to use and the + // version of the that client's input semantics to use, otherwise + // use EShClientNone and version of 0, e.g. for validation mode. + // Note 'version' does not describe the target environment, + // just the version of the source dialect to compile under. + // + // See the definitions of TEnvironment, EShSource, EShLanguage, + // and EShClient for choices and more detail. + // + // setEnvClient: The client that will be hosting the execution, and it's version. + // Note 'version' is not the version of the languages involved, but + // the version of the client environment. + // Use EShClientNone and version of 0 if there is no client, e.g. + // for validation mode. + // + // See EShTargetClientVersion for choices. + // + // setEnvTarget: The language to translate to when generating code, and that + // language's version. + // Use EShTargetNone and version of 0 if there is no client, e.g. + // for validation mode. + // + void setEnvInput(EShSource lang, EShLanguage envStage, EShClient client, int version) + { + environment.input.languageFamily = lang; + environment.input.stage = envStage; + environment.input.dialect = client; + environment.input.dialectVersion = version; + } + void setEnvClient(EShClient client, EShTargetClientVersion version) + { + environment.client.client = client; + environment.client.version = version; + } + void setEnvTarget(EShTargetLanguage lang, EShTargetLanguageVersion version) + { + environment.target.language = lang; + environment.target.version = version; + } + + void getStrings(const char* const* &s, int& n) { s = strings; n = numStrings; } + +#ifdef ENABLE_HLSL + void setEnvTargetHlslFunctionality1() { environment.target.hlslFunctionality1 = true; } + bool getEnvTargetHlslFunctionality1() const { return environment.target.hlslFunctionality1; } +#else + bool getEnvTargetHlslFunctionality1() const { return false; } +#endif + + // Interface to #include handlers. + // + // To support #include, a client of Glslang does the following: + // 1. Call setStringsWithNames to set the source strings and associated + // names. For example, the names could be the names of the files + // containing the shader sources. + // 2. Call parse with an Includer. + // + // When the Glslang parser encounters an #include directive, it calls + // the Includer's include method with the requested include name + // together with the current string name. The returned IncludeResult + // contains the fully resolved name of the included source, together + // with the source text that should replace the #include directive + // in the source stream. After parsing that source, Glslang will + // release the IncludeResult object. + class Includer { + public: + // An IncludeResult contains the resolved name and content of a source + // inclusion. + struct IncludeResult { + IncludeResult(const std::string& headerName, const char* const headerData, const size_t headerLength, void* userData) : + headerName(headerName), headerData(headerData), headerLength(headerLength), userData(userData) { } + // For a successful inclusion, the fully resolved name of the requested + // include. For example, in a file system-based includer, full resolution + // should convert a relative path name into an absolute path name. + // For a failed inclusion, this is an empty string. + const std::string headerName; + // The content and byte length of the requested inclusion. The + // Includer producing this IncludeResult retains ownership of the + // storage. + // For a failed inclusion, the header + // field points to a string containing error details. + const char* const headerData; + const size_t headerLength; + // Include resolver's context. + void* userData; + protected: + IncludeResult& operator=(const IncludeResult&); + IncludeResult(); + }; + + // For both include methods below: + // + // Resolves an inclusion request by name, current source name, + // and include depth. + // On success, returns an IncludeResult containing the resolved name + // and content of the include. + // On failure, returns a nullptr, or an IncludeResult + // with an empty string for the headerName and error details in the + // header field. + // The Includer retains ownership of the contents + // of the returned IncludeResult value, and those contents must + // remain valid until the releaseInclude method is called on that + // IncludeResult object. + // + // Note "local" vs. "system" is not an "either/or": "local" is an + // extra thing to do over "system". Both might get called, as per + // the C++ specification. + + // For the "system" or <>-style includes; search the "system" paths. + virtual IncludeResult* includeSystem(const char* /*headerName*/, + const char* /*includerName*/, + size_t /*inclusionDepth*/) { return nullptr; } + + // For the "local"-only aspect of a "" include. Should not search in the + // "system" paths, because on returning a failure, the parser will + // call includeSystem() to look in the "system" locations. + virtual IncludeResult* includeLocal(const char* /*headerName*/, + const char* /*includerName*/, + size_t /*inclusionDepth*/) { return nullptr; } + + // Signals that the parser will no longer use the contents of the + // specified IncludeResult. + virtual void releaseInclude(IncludeResult*) = 0; + virtual ~Includer() {} + }; + + // Fail all Includer searches + class ForbidIncluder : public Includer { + public: + virtual void releaseInclude(IncludeResult*) override { } + }; + + bool parse(const TBuiltInResource*, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, + bool forwardCompatible, EShMessages, Includer&); + + bool parse(const TBuiltInResource* res, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, + bool forwardCompatible, EShMessages messages) + { + TShader::ForbidIncluder includer; + return parse(res, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, messages, includer); + } + + // Equivalent to parse() without a default profile and without forcing defaults. + bool parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages) + { + return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages); + } + + bool parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages, + Includer& includer) + { + return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages, includer); + } + + // NOTE: Doing just preprocessing to obtain a correct preprocessed shader string + // is not an officially supported or fully working path. + bool preprocess(const TBuiltInResource* builtInResources, + int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, + bool forwardCompatible, EShMessages message, std::string* outputString, + Includer& includer); + + const char* getInfoLog(); + const char* getInfoDebugLog(); + EShLanguage getStage() const { return stage; } + TIntermediate* getIntermediate() const { return intermediate; } + +protected: + TPoolAllocator* pool; + EShLanguage stage; + TCompiler* compiler; + TIntermediate* intermediate; + TInfoSink* infoSink; + // strings and lengths follow the standard for glShaderSource: + // strings is an array of numStrings pointers to string data. + // lengths can be null, but if not it is an array of numStrings + // integers containing the length of the associated strings. + // if lengths is null or lengths[n] < 0 the associated strings[n] is + // assumed to be null-terminated. + // stringNames is the optional names for all the strings. If stringNames + // is null, then none of the strings has name. If a certain element in + // stringNames is null, then the corresponding string does not have name. + const char* const* strings; // explicit code to compile, see previous comment + const int* lengths; + const char* const* stringNames; + int numStrings; // size of the above arrays + const char* preamble; // string of implicit code to compile before the explicitly provided code + + // a function in the source string can be renamed FROM this TO the name given in setEntryPoint. + std::string sourceEntryPointName; + + TEnvironment environment; + + friend class TProgram; + +private: + TShader& operator=(TShader&); +}; + +#ifndef GLSLANG_WEB + +// +// A reflection database and its interface, consistent with the OpenGL API reflection queries. +// + +// Data needed for just a single object at the granularity exchanged by the reflection API +class TObjectReflection { +public: + TObjectReflection(const std::string& pName, const TType& pType, int pOffset, int pGLDefineType, int pSize, int pIndex); + + const TType* getType() const { return type; } + int getBinding() const; + void dump() const; + static TObjectReflection badReflection() { return TObjectReflection(); } + + std::string name; + int offset; + int glDefineType; + int size; // data size in bytes for a block, array size for a (non-block) object that's an array + int index; + int counterIndex; + int numMembers; + int arrayStride; // stride of an array variable + int topLevelArrayStride; // stride of the top-level variable in a storage buffer member + EShLanguageMask stages; + +protected: + TObjectReflection() + : offset(-1), glDefineType(-1), size(-1), index(-1), counterIndex(-1), numMembers(-1), arrayStride(0), + topLevelArrayStride(0), stages(EShLanguageMask(0)), type(nullptr) + { + } + + const TType* type; +}; + +class TReflection; +class TIoMapper; +struct TVarEntryInfo; + +// Allows to customize the binding layout after linking. +// All used uniform variables will invoke at least validateBinding. +// If validateBinding returned true then the other resolveBinding, +// resolveSet, and resolveLocation are invoked to resolve the binding +// and descriptor set index respectively. +// +// Invocations happen in a particular order: +// 1) all shader inputs +// 2) all shader outputs +// 3) all uniforms with binding and set already defined +// 4) all uniforms with binding but no set defined +// 5) all uniforms with set but no binding defined +// 6) all uniforms with no binding and no set defined +// +// mapIO will use this resolver in two phases. The first +// phase is a notification phase, calling the corresponging +// notifiy callbacks, this phase ends with a call to endNotifications. +// Phase two starts directly after the call to endNotifications +// and calls all other callbacks to validate and to get the +// bindings, sets, locations, component and color indices. +// +// NOTE: that still limit checks are applied to bindings and sets +// and may result in an error. +class TIoMapResolver +{ +public: + virtual ~TIoMapResolver() {} + + // Should return true if the resulting/current binding would be okay. + // Basic idea is to do aliasing binding checks with this. + virtual bool validateBinding(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current binding should be overridden. + // Return -1 if the current binding (including no binding) should be kept. + virtual int resolveBinding(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current set should be overridden. + // Return -1 if the current set (including no set) should be kept. + virtual int resolveSet(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current location should be overridden. + // Return -1 if the current location (including no location) should be kept. + virtual int resolveUniformLocation(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return true if the resulting/current setup would be okay. + // Basic idea is to do aliasing checks and reject invalid semantic names. + virtual bool validateInOut(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current location should be overridden. + // Return -1 if the current location (including no location) should be kept. + virtual int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current component index should be overridden. + // Return -1 if the current component index (including no index) should be kept. + virtual int resolveInOutComponent(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current color index should be overridden. + // Return -1 if the current color index (including no index) should be kept. + virtual int resolveInOutIndex(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Notification of a uniform variable + virtual void notifyBinding(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Notification of a in or out variable + virtual void notifyInOut(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Called by mapIO when it starts its notify pass for the given stage + virtual void beginNotifications(EShLanguage stage) = 0; + // Called by mapIO when it has finished the notify pass + virtual void endNotifications(EShLanguage stage) = 0; + // Called by mipIO when it starts its resolve pass for the given stage + virtual void beginResolve(EShLanguage stage) = 0; + // Called by mapIO when it has finished the resolve pass + virtual void endResolve(EShLanguage stage) = 0; + // Called by mapIO when it starts its symbol collect for teh given stage + virtual void beginCollect(EShLanguage stage) = 0; + // Called by mapIO when it has finished the symbol collect + virtual void endCollect(EShLanguage stage) = 0; + // Called by TSlotCollector to resolve storage locations or bindings + virtual void reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) = 0; + // Called by TSlotCollector to resolve resource locations or bindings + virtual void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) = 0; + // Called by mapIO.addStage to set shader stage mask to mark a stage be added to this pipeline + virtual void addStage(EShLanguage stage) = 0; +}; + +#endif // GLSLANG_WEB + +// Make one TProgram per set of shaders that will get linked together. Add all +// the shaders that are to be linked together. After calling shader.parse() +// for all shaders, call link(). +// +// N.B.: Destruct a linked program *before* destructing the shaders linked into it. +// +class TProgram { +public: + TProgram(); + virtual ~TProgram(); + void addShader(TShader* shader) { stages[shader->stage].push_back(shader); } + std::list& getShaders(EShLanguage stage) { return stages[stage]; } + // Link Validation interface + bool link(EShMessages); + const char* getInfoLog(); + const char* getInfoDebugLog(); + + TIntermediate* getIntermediate(EShLanguage stage) const { return intermediate[stage]; } + +#ifndef GLSLANG_WEB + + // Reflection Interface + + // call first, to do liveness analysis, index mapping, etc.; returns false on failure + bool buildReflection(int opts = EShReflectionDefault); + unsigned getLocalSize(int dim) const; // return dim'th local size + int getReflectionIndex(const char *name) const; + int getReflectionPipeIOIndex(const char* name, const bool inOrOut) const; + int getNumUniformVariables() const; + const TObjectReflection& getUniform(int index) const; + int getNumUniformBlocks() const; + const TObjectReflection& getUniformBlock(int index) const; + int getNumPipeInputs() const; + const TObjectReflection& getPipeInput(int index) const; + int getNumPipeOutputs() const; + const TObjectReflection& getPipeOutput(int index) const; + int getNumBufferVariables() const; + const TObjectReflection& getBufferVariable(int index) const; + int getNumBufferBlocks() const; + const TObjectReflection& getBufferBlock(int index) const; + int getNumAtomicCounters() const; + const TObjectReflection& getAtomicCounter(int index) const; + + // Legacy Reflection Interface - expressed in terms of above interface + + // can be used for glGetProgramiv(GL_ACTIVE_UNIFORMS) + int getNumLiveUniformVariables() const { return getNumUniformVariables(); } + + // can be used for glGetProgramiv(GL_ACTIVE_UNIFORM_BLOCKS) + int getNumLiveUniformBlocks() const { return getNumUniformBlocks(); } + + // can be used for glGetProgramiv(GL_ACTIVE_ATTRIBUTES) + int getNumLiveAttributes() const { return getNumPipeInputs(); } + + // can be used for glGetUniformIndices() + int getUniformIndex(const char *name) const { return getReflectionIndex(name); } + + int getPipeIOIndex(const char *name, const bool inOrOut) const + { return getReflectionPipeIOIndex(name, inOrOut); } + + // can be used for "name" part of glGetActiveUniform() + const char *getUniformName(int index) const { return getUniform(index).name.c_str(); } + + // returns the binding number + int getUniformBinding(int index) const { return getUniform(index).getBinding(); } + + // returns Shaders Stages where a Uniform is present + EShLanguageMask getUniformStages(int index) const { return getUniform(index).stages; } + + // can be used for glGetActiveUniformsiv(GL_UNIFORM_BLOCK_INDEX) + int getUniformBlockIndex(int index) const { return getUniform(index).index; } + + // can be used for glGetActiveUniformsiv(GL_UNIFORM_TYPE) + int getUniformType(int index) const { return getUniform(index).glDefineType; } + + // can be used for glGetActiveUniformsiv(GL_UNIFORM_OFFSET) + int getUniformBufferOffset(int index) const { return getUniform(index).offset; } + + // can be used for glGetActiveUniformsiv(GL_UNIFORM_SIZE) + int getUniformArraySize(int index) const { return getUniform(index).size; } + + // returns a TType* + const TType *getUniformTType(int index) const { return getUniform(index).getType(); } + + // can be used for glGetActiveUniformBlockName() + const char *getUniformBlockName(int index) const { return getUniformBlock(index).name.c_str(); } + + // can be used for glGetActiveUniformBlockiv(UNIFORM_BLOCK_DATA_SIZE) + int getUniformBlockSize(int index) const { return getUniformBlock(index).size; } + + // returns the block binding number + int getUniformBlockBinding(int index) const { return getUniformBlock(index).getBinding(); } + + // returns block index of associated counter. + int getUniformBlockCounterIndex(int index) const { return getUniformBlock(index).counterIndex; } + + // returns a TType* + const TType *getUniformBlockTType(int index) const { return getUniformBlock(index).getType(); } + + // can be used for glGetActiveAttrib() + const char *getAttributeName(int index) const { return getPipeInput(index).name.c_str(); } + + // can be used for glGetActiveAttrib() + int getAttributeType(int index) const { return getPipeInput(index).glDefineType; } + + // returns a TType* + const TType *getAttributeTType(int index) const { return getPipeInput(index).getType(); } + + void dumpReflection(); + // I/O mapping: apply base offsets and map live unbound variables + // If resolver is not provided it uses the previous approach + // and respects auto assignment and offsets. + bool mapIO(TIoMapResolver* pResolver = nullptr, TIoMapper* pIoMapper = nullptr); +#endif + +protected: + bool linkStage(EShLanguage, EShMessages); + + TPoolAllocator* pool; + std::list stages[EShLangCount]; + TIntermediate* intermediate[EShLangCount]; + bool newedIntermediate[EShLangCount]; // track which intermediate were "new" versus reusing a singleton unit in a stage + TInfoSink* infoSink; +#ifndef GLSLANG_WEB + TReflection* reflection; +#endif + bool linked; + +private: + TProgram(TProgram&); + TProgram& operator=(TProgram&); +}; + +} // end namespace glslang + +#endif // _COMPILER_INTERFACE_INCLUDED_ diff --git a/mac/include/glslang/SPIRV/GLSL.ext.AMD.h b/mac/include/glslang/SPIRV/GLSL.ext.AMD.h new file mode 100644 index 00000000..009d2f1c --- /dev/null +++ b/mac/include/glslang/SPIRV/GLSL.ext.AMD.h @@ -0,0 +1,108 @@ +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextAMD_H +#define GLSLextAMD_H + +static const int GLSLextAMDVersion = 100; +static const int GLSLextAMDRevision = 7; + +// SPV_AMD_shader_ballot +static const char* const E_SPV_AMD_shader_ballot = "SPV_AMD_shader_ballot"; + +enum ShaderBallotAMD { + ShaderBallotBadAMD = 0, // Don't use + + SwizzleInvocationsAMD = 1, + SwizzleInvocationsMaskedAMD = 2, + WriteInvocationAMD = 3, + MbcntAMD = 4, + + ShaderBallotCountAMD +}; + +// SPV_AMD_shader_trinary_minmax +static const char* const E_SPV_AMD_shader_trinary_minmax = "SPV_AMD_shader_trinary_minmax"; + +enum ShaderTrinaryMinMaxAMD { + ShaderTrinaryMinMaxBadAMD = 0, // Don't use + + FMin3AMD = 1, + UMin3AMD = 2, + SMin3AMD = 3, + FMax3AMD = 4, + UMax3AMD = 5, + SMax3AMD = 6, + FMid3AMD = 7, + UMid3AMD = 8, + SMid3AMD = 9, + + ShaderTrinaryMinMaxCountAMD +}; + +// SPV_AMD_shader_explicit_vertex_parameter +static const char* const E_SPV_AMD_shader_explicit_vertex_parameter = "SPV_AMD_shader_explicit_vertex_parameter"; + +enum ShaderExplicitVertexParameterAMD { + ShaderExplicitVertexParameterBadAMD = 0, // Don't use + + InterpolateAtVertexAMD = 1, + + ShaderExplicitVertexParameterCountAMD +}; + +// SPV_AMD_gcn_shader +static const char* const E_SPV_AMD_gcn_shader = "SPV_AMD_gcn_shader"; + +enum GcnShaderAMD { + GcnShaderBadAMD = 0, // Don't use + + CubeFaceIndexAMD = 1, + CubeFaceCoordAMD = 2, + TimeAMD = 3, + + GcnShaderCountAMD +}; + +// SPV_AMD_gpu_shader_half_float +static const char* const E_SPV_AMD_gpu_shader_half_float = "SPV_AMD_gpu_shader_half_float"; + +// SPV_AMD_texture_gather_bias_lod +static const char* const E_SPV_AMD_texture_gather_bias_lod = "SPV_AMD_texture_gather_bias_lod"; + +// SPV_AMD_gpu_shader_int16 +static const char* const E_SPV_AMD_gpu_shader_int16 = "SPV_AMD_gpu_shader_int16"; + +// SPV_AMD_shader_image_load_store_lod +static const char* const E_SPV_AMD_shader_image_load_store_lod = "SPV_AMD_shader_image_load_store_lod"; + +// SPV_AMD_shader_fragment_mask +static const char* const E_SPV_AMD_shader_fragment_mask = "SPV_AMD_shader_fragment_mask"; + +// SPV_AMD_gpu_shader_half_float_fetch +static const char* const E_SPV_AMD_gpu_shader_half_float_fetch = "SPV_AMD_gpu_shader_half_float_fetch"; + +#endif // #ifndef GLSLextAMD_H diff --git a/mac/include/glslang/SPIRV/GLSL.ext.EXT.h b/mac/include/glslang/SPIRV/GLSL.ext.EXT.h new file mode 100644 index 00000000..40164b61 --- /dev/null +++ b/mac/include/glslang/SPIRV/GLSL.ext.EXT.h @@ -0,0 +1,39 @@ +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextEXT_H +#define GLSLextEXT_H + +static const int GLSLextEXTVersion = 100; +static const int GLSLextEXTRevision = 2; + +static const char* const E_SPV_EXT_shader_stencil_export = "SPV_EXT_shader_stencil_export"; +static const char* const E_SPV_EXT_shader_viewport_index_layer = "SPV_EXT_shader_viewport_index_layer"; +static const char* const E_SPV_EXT_fragment_fully_covered = "SPV_EXT_fragment_fully_covered"; +static const char* const E_SPV_EXT_fragment_invocation_density = "SPV_EXT_fragment_invocation_density"; +static const char* const E_SPV_EXT_demote_to_helper_invocation = "SPV_EXT_demote_to_helper_invocation"; + +#endif // #ifndef GLSLextEXT_H diff --git a/mac/include/glslang/SPIRV/GLSL.ext.KHR.h b/mac/include/glslang/SPIRV/GLSL.ext.KHR.h new file mode 100644 index 00000000..d783a8f2 --- /dev/null +++ b/mac/include/glslang/SPIRV/GLSL.ext.KHR.h @@ -0,0 +1,51 @@ +/* +** Copyright (c) 2014-2020 The Khronos Group Inc. +** Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextKHR_H +#define GLSLextKHR_H + +static const int GLSLextKHRVersion = 100; +static const int GLSLextKHRRevision = 2; + +static const char* const E_SPV_KHR_shader_ballot = "SPV_KHR_shader_ballot"; +static const char* const E_SPV_KHR_subgroup_vote = "SPV_KHR_subgroup_vote"; +static const char* const E_SPV_KHR_device_group = "SPV_KHR_device_group"; +static const char* const E_SPV_KHR_multiview = "SPV_KHR_multiview"; +static const char* const E_SPV_KHR_shader_draw_parameters = "SPV_KHR_shader_draw_parameters"; +static const char* const E_SPV_KHR_16bit_storage = "SPV_KHR_16bit_storage"; +static const char* const E_SPV_KHR_8bit_storage = "SPV_KHR_8bit_storage"; +static const char* const E_SPV_KHR_storage_buffer_storage_class = "SPV_KHR_storage_buffer_storage_class"; +static const char* const E_SPV_KHR_post_depth_coverage = "SPV_KHR_post_depth_coverage"; +static const char* const E_SPV_KHR_vulkan_memory_model = "SPV_KHR_vulkan_memory_model"; +static const char* const E_SPV_EXT_physical_storage_buffer = "SPV_EXT_physical_storage_buffer"; +static const char* const E_SPV_KHR_physical_storage_buffer = "SPV_KHR_physical_storage_buffer"; +static const char* const E_SPV_EXT_fragment_shader_interlock = "SPV_EXT_fragment_shader_interlock"; +static const char* const E_SPV_KHR_shader_clock = "SPV_KHR_shader_clock"; +static const char* const E_SPV_KHR_non_semantic_info = "SPV_KHR_non_semantic_info"; +static const char* const E_SPV_KHR_ray_tracing = "SPV_KHR_ray_tracing"; +static const char* const E_SPV_KHR_ray_query = "SPV_KHR_ray_query"; +#endif // #ifndef GLSLextKHR_H diff --git a/mac/include/glslang/SPIRV/GLSL.ext.NV.h b/mac/include/glslang/SPIRV/GLSL.ext.NV.h new file mode 100644 index 00000000..50146da1 --- /dev/null +++ b/mac/include/glslang/SPIRV/GLSL.ext.NV.h @@ -0,0 +1,81 @@ +/* +** Copyright (c) 2014-2017 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLextNV_H +#define GLSLextNV_H + +enum BuiltIn; +enum Decoration; +enum Op; +enum Capability; + +static const int GLSLextNVVersion = 100; +static const int GLSLextNVRevision = 11; + +//SPV_NV_sample_mask_override_coverage +const char* const E_SPV_NV_sample_mask_override_coverage = "SPV_NV_sample_mask_override_coverage"; + +//SPV_NV_geometry_shader_passthrough +const char* const E_SPV_NV_geometry_shader_passthrough = "SPV_NV_geometry_shader_passthrough"; + +//SPV_NV_viewport_array2 +const char* const E_SPV_NV_viewport_array2 = "SPV_NV_viewport_array2"; +const char* const E_ARB_shader_viewport_layer_array = "SPV_ARB_shader_viewport_layer_array"; + +//SPV_NV_stereo_view_rendering +const char* const E_SPV_NV_stereo_view_rendering = "SPV_NV_stereo_view_rendering"; + +//SPV_NVX_multiview_per_view_attributes +const char* const E_SPV_NVX_multiview_per_view_attributes = "SPV_NVX_multiview_per_view_attributes"; + +//SPV_NV_shader_subgroup_partitioned +const char* const E_SPV_NV_shader_subgroup_partitioned = "SPV_NV_shader_subgroup_partitioned"; + +//SPV_NV_fragment_shader_barycentric +const char* const E_SPV_NV_fragment_shader_barycentric = "SPV_NV_fragment_shader_barycentric"; + +//SPV_NV_compute_shader_derivatives +const char* const E_SPV_NV_compute_shader_derivatives = "SPV_NV_compute_shader_derivatives"; + +//SPV_NV_shader_image_footprint +const char* const E_SPV_NV_shader_image_footprint = "SPV_NV_shader_image_footprint"; + +//SPV_NV_mesh_shader +const char* const E_SPV_NV_mesh_shader = "SPV_NV_mesh_shader"; + +//SPV_NV_raytracing +const char* const E_SPV_NV_ray_tracing = "SPV_NV_ray_tracing"; + +//SPV_NV_shading_rate +const char* const E_SPV_NV_shading_rate = "SPV_NV_shading_rate"; + +//SPV_NV_cooperative_matrix +const char* const E_SPV_NV_cooperative_matrix = "SPV_NV_cooperative_matrix"; + +//SPV_NV_shader_sm_builtins +const char* const E_SPV_NV_shader_sm_builtins = "SPV_NV_shader_sm_builtins"; + +#endif // #ifndef GLSLextNV_H diff --git a/mac/include/glslang/SPIRV/GLSL.std.450.h b/mac/include/glslang/SPIRV/GLSL.std.450.h new file mode 100644 index 00000000..df31092b --- /dev/null +++ b/mac/include/glslang/SPIRV/GLSL.std.450.h @@ -0,0 +1,131 @@ +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLstd450_H +#define GLSLstd450_H + +static const int GLSLstd450Version = 100; +static const int GLSLstd450Revision = 1; + +enum GLSLstd450 { + GLSLstd450Bad = 0, // Don't use + + GLSLstd450Round = 1, + GLSLstd450RoundEven = 2, + GLSLstd450Trunc = 3, + GLSLstd450FAbs = 4, + GLSLstd450SAbs = 5, + GLSLstd450FSign = 6, + GLSLstd450SSign = 7, + GLSLstd450Floor = 8, + GLSLstd450Ceil = 9, + GLSLstd450Fract = 10, + + GLSLstd450Radians = 11, + GLSLstd450Degrees = 12, + GLSLstd450Sin = 13, + GLSLstd450Cos = 14, + GLSLstd450Tan = 15, + GLSLstd450Asin = 16, + GLSLstd450Acos = 17, + GLSLstd450Atan = 18, + GLSLstd450Sinh = 19, + GLSLstd450Cosh = 20, + GLSLstd450Tanh = 21, + GLSLstd450Asinh = 22, + GLSLstd450Acosh = 23, + GLSLstd450Atanh = 24, + GLSLstd450Atan2 = 25, + + GLSLstd450Pow = 26, + GLSLstd450Exp = 27, + GLSLstd450Log = 28, + GLSLstd450Exp2 = 29, + GLSLstd450Log2 = 30, + GLSLstd450Sqrt = 31, + GLSLstd450InverseSqrt = 32, + + GLSLstd450Determinant = 33, + GLSLstd450MatrixInverse = 34, + + GLSLstd450Modf = 35, // second operand needs an OpVariable to write to + GLSLstd450ModfStruct = 36, // no OpVariable operand + GLSLstd450FMin = 37, + GLSLstd450UMin = 38, + GLSLstd450SMin = 39, + GLSLstd450FMax = 40, + GLSLstd450UMax = 41, + GLSLstd450SMax = 42, + GLSLstd450FClamp = 43, + GLSLstd450UClamp = 44, + GLSLstd450SClamp = 45, + GLSLstd450FMix = 46, + GLSLstd450IMix = 47, // Reserved + GLSLstd450Step = 48, + GLSLstd450SmoothStep = 49, + + GLSLstd450Fma = 50, + GLSLstd450Frexp = 51, // second operand needs an OpVariable to write to + GLSLstd450FrexpStruct = 52, // no OpVariable operand + GLSLstd450Ldexp = 53, + + GLSLstd450PackSnorm4x8 = 54, + GLSLstd450PackUnorm4x8 = 55, + GLSLstd450PackSnorm2x16 = 56, + GLSLstd450PackUnorm2x16 = 57, + GLSLstd450PackHalf2x16 = 58, + GLSLstd450PackDouble2x32 = 59, + GLSLstd450UnpackSnorm2x16 = 60, + GLSLstd450UnpackUnorm2x16 = 61, + GLSLstd450UnpackHalf2x16 = 62, + GLSLstd450UnpackSnorm4x8 = 63, + GLSLstd450UnpackUnorm4x8 = 64, + GLSLstd450UnpackDouble2x32 = 65, + + GLSLstd450Length = 66, + GLSLstd450Distance = 67, + GLSLstd450Cross = 68, + GLSLstd450Normalize = 69, + GLSLstd450FaceForward = 70, + GLSLstd450Reflect = 71, + GLSLstd450Refract = 72, + + GLSLstd450FindILsb = 73, + GLSLstd450FindSMsb = 74, + GLSLstd450FindUMsb = 75, + + GLSLstd450InterpolateAtCentroid = 76, + GLSLstd450InterpolateAtSample = 77, + GLSLstd450InterpolateAtOffset = 78, + + GLSLstd450NMin = 79, + GLSLstd450NMax = 80, + GLSLstd450NClamp = 81, + + GLSLstd450Count +}; + +#endif // #ifndef GLSLstd450_H diff --git a/mac/include/glslang/SPIRV/GlslangToSpv.h b/mac/include/glslang/SPIRV/GlslangToSpv.h new file mode 100644 index 00000000..3907be43 --- /dev/null +++ b/mac/include/glslang/SPIRV/GlslangToSpv.h @@ -0,0 +1,61 @@ +// +// Copyright (C) 2014 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#pragma once + +#if defined(_MSC_VER) && _MSC_VER >= 1900 + #pragma warning(disable : 4464) // relative include path contains '..' +#endif + +#include "SpvTools.h" +#include "glslang/Include/intermediate.h" + +#include +#include + +#include "Logger.h" + +namespace glslang { + +void GetSpirvVersion(std::string&); +int GetSpirvGeneratorVersion(); +void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, + SpvOptions* options = nullptr); +void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger* logger, SpvOptions* options = nullptr); +void OutputSpvBin(const std::vector& spirv, const char* baseName); +void OutputSpvHex(const std::vector& spirv, const char* baseName, const char* varName); + +} diff --git a/mac/include/glslang/SPIRV/Logger.h b/mac/include/glslang/SPIRV/Logger.h new file mode 100644 index 00000000..411367c0 --- /dev/null +++ b/mac/include/glslang/SPIRV/Logger.h @@ -0,0 +1,83 @@ +// +// Copyright (C) 2016 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef GLSLANG_SPIRV_LOGGER_H +#define GLSLANG_SPIRV_LOGGER_H + +#include +#include + +namespace spv { + +// A class for holding all SPIR-V build status messages, including +// missing/TBD functionalities, warnings, and errors. +class SpvBuildLogger { +public: + SpvBuildLogger() {} + +#ifdef GLSLANG_WEB + void tbdFunctionality(const std::string& f) { } + void missingFunctionality(const std::string& f) { } + void warning(const std::string& w) { } + void error(const std::string& e) { errors.push_back(e); } + std::string getAllMessages() { return ""; } +#else + + // Registers a TBD functionality. + void tbdFunctionality(const std::string& f); + // Registers a missing functionality. + void missingFunctionality(const std::string& f); + + // Logs a warning. + void warning(const std::string& w) { warnings.push_back(w); } + // Logs an error. + void error(const std::string& e) { errors.push_back(e); } + + // Returns all messages accumulated in the order of: + // TBD functionalities, missing functionalities, warnings, errors. + std::string getAllMessages() const; +#endif + +private: + SpvBuildLogger(const SpvBuildLogger&); + + std::vector tbdFeatures; + std::vector missingFeatures; + std::vector warnings; + std::vector errors; +}; + +} // end spv namespace + +#endif // GLSLANG_SPIRV_LOGGER_H diff --git a/mac/include/glslang/SPIRV/NonSemanticDebugPrintf.h b/mac/include/glslang/SPIRV/NonSemanticDebugPrintf.h new file mode 100644 index 00000000..83796d75 --- /dev/null +++ b/mac/include/glslang/SPIRV/NonSemanticDebugPrintf.h @@ -0,0 +1,50 @@ +// Copyright (c) 2020 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and/or associated documentation files (the +// "Materials"), to deal in the Materials without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Materials, and to +// permit persons to whom the Materials are furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS +// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS +// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT +// https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +// + +#ifndef SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ +#define SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + NonSemanticDebugPrintfRevision = 1, + NonSemanticDebugPrintfRevision_BitWidthPadding = 0x7fffffff +}; + +enum NonSemanticDebugPrintfInstructions { + NonSemanticDebugPrintfDebugPrintf = 1, + NonSemanticDebugPrintfInstructionsMax = 0x7fffffff +}; + + +#ifdef __cplusplus +} +#endif + +#endif // SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ diff --git a/mac/include/glslang/SPIRV/SPVRemapper.h b/mac/include/glslang/SPIRV/SPVRemapper.h new file mode 100644 index 00000000..d6b9c346 --- /dev/null +++ b/mac/include/glslang/SPIRV/SPVRemapper.h @@ -0,0 +1,304 @@ +// +// Copyright (C) 2015 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef SPIRVREMAPPER_H +#define SPIRVREMAPPER_H + +#include +#include +#include +#include + +namespace spv { + +// MSVC defines __cplusplus as an older value, even when it supports almost all of 11. +// We handle that here by making our own symbol. +#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1700) +# define use_cpp11 1 +#endif + +class spirvbin_base_t +{ +public: + enum Options { + NONE = 0, + STRIP = (1<<0), + MAP_TYPES = (1<<1), + MAP_NAMES = (1<<2), + MAP_FUNCS = (1<<3), + DCE_FUNCS = (1<<4), + DCE_VARS = (1<<5), + DCE_TYPES = (1<<6), + OPT_LOADSTORE = (1<<7), + OPT_FWD_LS = (1<<8), // EXPERIMENTAL: PRODUCES INVALID SCHEMA-0 SPIRV + MAP_ALL = (MAP_TYPES | MAP_NAMES | MAP_FUNCS), + DCE_ALL = (DCE_FUNCS | DCE_VARS | DCE_TYPES), + OPT_ALL = (OPT_LOADSTORE), + + ALL_BUT_STRIP = (MAP_ALL | DCE_ALL | OPT_ALL), + DO_EVERYTHING = (STRIP | ALL_BUT_STRIP) + }; +}; + +} // namespace SPV + +#if !defined (use_cpp11) +#include +#include + +namespace spv { +class spirvbin_t : public spirvbin_base_t +{ +public: + spirvbin_t(int /*verbose = 0*/) { } + + void remap(std::vector& /*spv*/, unsigned int /*opts = 0*/) + { + printf("Tool not compiled for C++11, which is required for SPIR-V remapping.\n"); + exit(5); + } +}; + +} // namespace SPV + +#else // defined (use_cpp11) + +#include +#include +#include +#include +#include +#include +#include + +#include "spirv.hpp" +#include "spvIR.h" + +namespace spv { + +// class to hold SPIR-V binary data for remapping, DCE, and debug stripping +class spirvbin_t : public spirvbin_base_t +{ +public: + spirvbin_t(int verbose = 0) : entryPoint(spv::NoResult), largestNewId(0), verbose(verbose), errorLatch(false) + { } + + virtual ~spirvbin_t() { } + + // remap on an existing binary in memory + void remap(std::vector& spv, std::uint32_t opts = DO_EVERYTHING); + + // Type for error/log handler functions + typedef std::function errorfn_t; + typedef std::function logfn_t; + + // Register error/log handling functions (can be lambda fn / functor / etc) + static void registerErrorHandler(errorfn_t handler) { errorHandler = handler; } + static void registerLogHandler(logfn_t handler) { logHandler = handler; } + +protected: + // This can be overridden to provide other message behavior if needed + virtual void msg(int minVerbosity, int indent, const std::string& txt) const; + +private: + // Local to global, or global to local ID map + typedef std::unordered_map idmap_t; + typedef std::unordered_set idset_t; + typedef std::unordered_map blockmap_t; + + void remap(std::uint32_t opts = DO_EVERYTHING); + + // Map of names to IDs + typedef std::unordered_map namemap_t; + + typedef std::uint32_t spirword_t; + + typedef std::pair range_t; + typedef std::function idfn_t; + typedef std::function instfn_t; + + // Special Values for ID map: + static const spv::Id unmapped; // unchanged from default value + static const spv::Id unused; // unused ID + static const int header_size; // SPIR header = 5 words + + class id_iterator_t; + + // For mapping type entries between different shaders + typedef std::vector typeentry_t; + typedef std::map globaltypes_t; + + // A set that preserves position order, and a reverse map + typedef std::set posmap_t; + typedef std::unordered_map posmap_rev_t; + + // Maps and ID to the size of its base type, if known. + typedef std::unordered_map typesize_map_t; + + // handle error + void error(const std::string& txt) const { errorLatch = true; errorHandler(txt); } + + bool isConstOp(spv::Op opCode) const; + bool isTypeOp(spv::Op opCode) const; + bool isStripOp(spv::Op opCode) const; + bool isFlowCtrl(spv::Op opCode) const; + range_t literalRange(spv::Op opCode) const; + range_t typeRange(spv::Op opCode) const; + range_t constRange(spv::Op opCode) const; + unsigned typeSizeInWords(spv::Id id) const; + unsigned idTypeSizeInWords(spv::Id id) const; + + spv::Id& asId(unsigned word) { return spv[word]; } + const spv::Id& asId(unsigned word) const { return spv[word]; } + spv::Op asOpCode(unsigned word) const { return opOpCode(spv[word]); } + std::uint32_t asOpCodeHash(unsigned word); + spv::Decoration asDecoration(unsigned word) const { return spv::Decoration(spv[word]); } + unsigned asWordCount(unsigned word) const { return opWordCount(spv[word]); } + spv::Id asTypeConstId(unsigned word) const { return asId(word + (isTypeOp(asOpCode(word)) ? 1 : 2)); } + unsigned idPos(spv::Id id) const; + + static unsigned opWordCount(spirword_t data) { return data >> spv::WordCountShift; } + static spv::Op opOpCode(spirword_t data) { return spv::Op(data & spv::OpCodeMask); } + + // Header access & set methods + spirword_t magic() const { return spv[0]; } // return magic number + spirword_t bound() const { return spv[3]; } // return Id bound from header + spirword_t bound(spirword_t b) { return spv[3] = b; } + spirword_t genmagic() const { return spv[2]; } // generator magic + spirword_t genmagic(spirword_t m) { return spv[2] = m; } + spirword_t schemaNum() const { return spv[4]; } // schema number from header + + // Mapping fns: get + spv::Id localId(spv::Id id) const { return idMapL[id]; } + + // Mapping fns: set + inline spv::Id localId(spv::Id id, spv::Id newId); + void countIds(spv::Id id); + + // Return next unused new local ID. + // NOTE: boost::dynamic_bitset would be more efficient due to find_next(), + // which std::vector doens't have. + inline spv::Id nextUnusedId(spv::Id id); + + void buildLocalMaps(); + std::string literalString(unsigned word) const; // Return literal as a std::string + int literalStringWords(const std::string& str) const { return (int(str.size())+4)/4; } + + bool isNewIdMapped(spv::Id newId) const { return isMapped(newId); } + bool isOldIdUnmapped(spv::Id oldId) const { return localId(oldId) == unmapped; } + bool isOldIdUnused(spv::Id oldId) const { return localId(oldId) == unused; } + bool isOldIdMapped(spv::Id oldId) const { return !isOldIdUnused(oldId) && !isOldIdUnmapped(oldId); } + bool isFunction(spv::Id oldId) const { return fnPos.find(oldId) != fnPos.end(); } + + // bool matchType(const globaltypes_t& globalTypes, spv::Id lt, spv::Id gt) const; + // spv::Id findType(const globaltypes_t& globalTypes, spv::Id lt) const; + std::uint32_t hashType(unsigned typeStart) const; + + spirvbin_t& process(instfn_t, idfn_t, unsigned begin = 0, unsigned end = 0); + int processInstruction(unsigned word, instfn_t, idfn_t); + + void validate() const; + void mapTypeConst(); + void mapFnBodies(); + void optLoadStore(); + void dceFuncs(); + void dceVars(); + void dceTypes(); + void mapNames(); + void foldIds(); // fold IDs to smallest space + void forwardLoadStores(); // load store forwarding (EXPERIMENTAL) + void offsetIds(); // create relative offset IDs + + void applyMap(); // remap per local name map + void mapRemainder(); // map any IDs we haven't touched yet + void stripDebug(); // strip all debug info + void stripDeadRefs(); // strips debug info for now-dead references after DCE + void strip(); // remove debug symbols + + std::vector spv; // SPIR words + + namemap_t nameMap; // ID names from OpName + + // Since we want to also do binary ops, we can't use std::vector. we could use + // boost::dynamic_bitset, but we're trying to avoid a boost dependency. + typedef std::uint64_t bits_t; + std::vector mapped; // which new IDs have been mapped + static const int mBits = sizeof(bits_t) * 4; + + bool isMapped(spv::Id id) const { return id < maxMappedId() && ((mapped[id/mBits] & (1LL<<(id%mBits))) != 0); } + void setMapped(spv::Id id) { resizeMapped(id); mapped[id/mBits] |= (1LL<<(id%mBits)); } + void resizeMapped(spv::Id id) { if (id >= maxMappedId()) mapped.resize(id/mBits+1, 0); } + size_t maxMappedId() const { return mapped.size() * mBits; } + + // Add a strip range for a given instruction starting at 'start' + // Note: avoiding brace initializers to please older versions os MSVC. + void stripInst(unsigned start) { stripRange.push_back(range_t(start, start + asWordCount(start))); } + + // Function start and end. use unordered_map because we'll have + // many fewer functions than IDs. + std::unordered_map fnPos; + + // Which functions are called, anywhere in the module, with a call count + std::unordered_map fnCalls; + + posmap_t typeConstPos; // word positions that define types & consts (ordered) + posmap_rev_t idPosR; // reverse map from IDs to positions + typesize_map_t idTypeSizeMap; // maps each ID to its type size, if known. + + std::vector idMapL; // ID {M}ap from {L}ocal to {G}lobal IDs + + spv::Id entryPoint; // module entry point + spv::Id largestNewId; // biggest new ID we have mapped anything to + + // Sections of the binary to strip, given as [begin,end) + std::vector stripRange; + + // processing options: + std::uint32_t options; + int verbose; // verbosity level + + // Error latch: this is set if the error handler is ever executed. It would be better to + // use a try/catch block and throw, but that's not desired for certain environments, so + // this is the alternative. + mutable bool errorLatch; + + static errorfn_t errorHandler; + static logfn_t logHandler; +}; + +} // namespace SPV + +#endif // defined (use_cpp11) +#endif // SPIRVREMAPPER_H diff --git a/mac/include/glslang/SPIRV/SpvBuilder.h b/mac/include/glslang/SPIRV/SpvBuilder.h new file mode 100644 index 00000000..71b90d60 --- /dev/null +++ b/mac/include/glslang/SPIRV/SpvBuilder.h @@ -0,0 +1,838 @@ +// +// Copyright (C) 2014-2015 LunarG, Inc. +// Copyright (C) 2015-2020 Google, Inc. +// Copyright (C) 2017 ARM Limited. +// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// "Builder" is an interface to fully build SPIR-V IR. Allocate one of +// these to build (a thread safe) internal SPIR-V representation (IR), +// and then dump it as a binary stream according to the SPIR-V specification. +// +// A Builder has a 1:1 relationship with a SPIR-V module. +// + +#pragma once +#ifndef SpvBuilder_H +#define SpvBuilder_H + +#include "Logger.h" +#include "spirv.hpp" +#include "spvIR.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace spv { + +typedef enum { + Spv_1_0 = (1 << 16), + Spv_1_1 = (1 << 16) | (1 << 8), + Spv_1_2 = (1 << 16) | (2 << 8), + Spv_1_3 = (1 << 16) | (3 << 8), + Spv_1_4 = (1 << 16) | (4 << 8), + Spv_1_5 = (1 << 16) | (5 << 8), +} SpvVersion; + +class Builder { +public: + Builder(unsigned int spvVersion, unsigned int userNumber, SpvBuildLogger* logger); + virtual ~Builder(); + + static const int maxMatrixSize = 4; + + unsigned int getSpvVersion() const { return spvVersion; } + + void setSource(spv::SourceLanguage lang, int version) + { + source = lang; + sourceVersion = version; + } + spv::Id getStringId(const std::string& str) + { + auto sItr = stringIds.find(str); + if (sItr != stringIds.end()) + return sItr->second; + spv::Id strId = getUniqueId(); + Instruction* fileString = new Instruction(strId, NoType, OpString); + const char* file_c_str = str.c_str(); + fileString->addStringOperand(file_c_str); + strings.push_back(std::unique_ptr(fileString)); + module.mapInstruction(fileString); + stringIds[file_c_str] = strId; + return strId; + } + void setSourceFile(const std::string& file) + { + sourceFileStringId = getStringId(file); + } + void setSourceText(const std::string& text) { sourceText = text; } + void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); } + void addModuleProcessed(const std::string& p) { moduleProcesses.push_back(p.c_str()); } + void setEmitOpLines() { emitOpLines = true; } + void addExtension(const char* ext) { extensions.insert(ext); } + void removeExtension(const char* ext) + { + extensions.erase(ext); + } + void addIncorporatedExtension(const char* ext, SpvVersion incorporatedVersion) + { + if (getSpvVersion() < static_cast(incorporatedVersion)) + addExtension(ext); + } + void promoteIncorporatedExtension(const char* baseExt, const char* promoExt, SpvVersion incorporatedVersion) + { + removeExtension(baseExt); + addIncorporatedExtension(promoExt, incorporatedVersion); + } + void addInclude(const std::string& name, const std::string& text) + { + spv::Id incId = getStringId(name); + includeFiles[incId] = &text; + } + Id import(const char*); + void setMemoryModel(spv::AddressingModel addr, spv::MemoryModel mem) + { + addressModel = addr; + memoryModel = mem; + } + + void addCapability(spv::Capability cap) { capabilities.insert(cap); } + + // To get a new for anything needing a new one. + Id getUniqueId() { return ++uniqueId; } + + // To get a set of new s, e.g., for a set of function parameters + Id getUniqueIds(int numIds) + { + Id id = uniqueId + 1; + uniqueId += numIds; + return id; + } + + // Generate OpLine for non-filename-based #line directives (ie no filename + // seen yet): Log the current line, and if different than the last one, + // issue a new OpLine using the new line and current source file name. + void setLine(int line); + + // If filename null, generate OpLine for non-filename-based line directives, + // else do filename-based: Log the current line and file, and if different + // than the last one, issue a new OpLine using the new line and file + // name. + void setLine(int line, const char* filename); + // Low-level OpLine. See setLine() for a layered helper. + void addLine(Id fileName, int line, int column); + + // For creating new types (will return old type if the requested one was already made). + Id makeVoidType(); + Id makeBoolType(); + Id makePointer(StorageClass, Id pointee); + Id makeForwardPointer(StorageClass); + Id makePointerFromForwardPointer(StorageClass, Id forwardPointerType, Id pointee); + Id makeIntegerType(int width, bool hasSign); // generic + Id makeIntType(int width) { return makeIntegerType(width, true); } + Id makeUintType(int width) { return makeIntegerType(width, false); } + Id makeFloatType(int width); + Id makeStructType(const std::vector& members, const char*); + Id makeStructResultType(Id type0, Id type1); + Id makeVectorType(Id component, int size); + Id makeMatrixType(Id component, int cols, int rows); + Id makeArrayType(Id element, Id sizeId, int stride); // 0 stride means no stride decoration + Id makeRuntimeArray(Id element); + Id makeFunctionType(Id returnType, const std::vector& paramTypes); + Id makeImageType(Id sampledType, Dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format); + Id makeSamplerType(); + Id makeSampledImageType(Id imageType); + Id makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols); + + // accelerationStructureNV type + Id makeAccelerationStructureType(); + // rayQueryEXT type + Id makeRayQueryType(); + + // For querying about types. + Id getTypeId(Id resultId) const { return module.getTypeId(resultId); } + Id getDerefTypeId(Id resultId) const; + Op getOpCode(Id id) const { return module.getInstruction(id)->getOpCode(); } + Op getTypeClass(Id typeId) const { return getOpCode(typeId); } + Op getMostBasicTypeClass(Id typeId) const; + int getNumComponents(Id resultId) const { return getNumTypeComponents(getTypeId(resultId)); } + int getNumTypeConstituents(Id typeId) const; + int getNumTypeComponents(Id typeId) const { return getNumTypeConstituents(typeId); } + Id getScalarTypeId(Id typeId) const; + Id getContainedTypeId(Id typeId) const; + Id getContainedTypeId(Id typeId, int) const; + StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); } + ImageFormat getImageTypeFormat(Id typeId) const + { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); } + + bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); } + bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); } + bool isVector(Id resultId) const { return isVectorType(getTypeId(resultId)); } + bool isMatrix(Id resultId) const { return isMatrixType(getTypeId(resultId)); } + bool isCooperativeMatrix(Id resultId)const { return isCooperativeMatrixType(getTypeId(resultId)); } + bool isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); } + bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); } + + bool isBoolType(Id typeId) + { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); } + bool isIntType(Id typeId) const + { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; } + bool isUintType(Id typeId) const + { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; } + bool isFloatType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat; } + bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; } + bool isScalarType(Id typeId) const + { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt || + getTypeClass(typeId) == OpTypeBool; } + bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; } + bool isMatrixType(Id typeId) const { return getTypeClass(typeId) == OpTypeMatrix; } + bool isStructType(Id typeId) const { return getTypeClass(typeId) == OpTypeStruct; } + bool isArrayType(Id typeId) const { return getTypeClass(typeId) == OpTypeArray; } +#ifdef GLSLANG_WEB + bool isCooperativeMatrixType(Id typeId)const { return false; } +#else + bool isCooperativeMatrixType(Id typeId)const { return getTypeClass(typeId) == OpTypeCooperativeMatrixNV; } +#endif + bool isAggregateType(Id typeId) const + { return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); } + bool isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; } + bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; } + bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; } + bool containsType(Id typeId, Op typeOp, unsigned int width) const; + bool containsPhysicalStorageBufferOrArray(Id typeId) const; + + bool isConstantOpCode(Op opcode) const; + bool isSpecConstantOpCode(Op opcode) const; + bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); } + bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; } + bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); } + unsigned int getConstantScalar(Id resultId) const + { return module.getInstruction(resultId)->getImmediateOperand(0); } + StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); } + + int getScalarTypeWidth(Id typeId) const + { + Id scalarTypeId = getScalarTypeId(typeId); + assert(getTypeClass(scalarTypeId) == OpTypeInt || getTypeClass(scalarTypeId) == OpTypeFloat); + return module.getInstruction(scalarTypeId)->getImmediateOperand(0); + } + + int getTypeNumColumns(Id typeId) const + { + assert(isMatrixType(typeId)); + return getNumTypeConstituents(typeId); + } + int getNumColumns(Id resultId) const { return getTypeNumColumns(getTypeId(resultId)); } + int getTypeNumRows(Id typeId) const + { + assert(isMatrixType(typeId)); + return getNumTypeComponents(getContainedTypeId(typeId)); + } + int getNumRows(Id resultId) const { return getTypeNumRows(getTypeId(resultId)); } + + Dim getTypeDimensionality(Id typeId) const + { + assert(isImageType(typeId)); + return (Dim)module.getInstruction(typeId)->getImmediateOperand(1); + } + Id getImageType(Id resultId) const + { + Id typeId = getTypeId(resultId); + assert(isImageType(typeId) || isSampledImageType(typeId)); + return isSampledImageType(typeId) ? module.getInstruction(typeId)->getIdOperand(0) : typeId; + } + bool isArrayedImageType(Id typeId) const + { + assert(isImageType(typeId)); + return module.getInstruction(typeId)->getImmediateOperand(3) != 0; + } + + // For making new constants (will return old constant if the requested one was already made). + Id makeBoolConstant(bool b, bool specConstant = false); + Id makeInt8Constant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); } + Id makeUint8Constant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(8), u, specConstant); } + Id makeInt16Constant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(16), (unsigned)i, specConstant); } + Id makeUint16Constant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(16), u, specConstant); } + Id makeIntConstant(int i, bool specConstant = false) + { return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); } + Id makeUintConstant(unsigned u, bool specConstant = false) + { return makeIntConstant(makeUintType(32), u, specConstant); } + Id makeInt64Constant(long long i, bool specConstant = false) + { return makeInt64Constant(makeIntType(64), (unsigned long long)i, specConstant); } + Id makeUint64Constant(unsigned long long u, bool specConstant = false) + { return makeInt64Constant(makeUintType(64), u, specConstant); } + Id makeFloatConstant(float f, bool specConstant = false); + Id makeDoubleConstant(double d, bool specConstant = false); + Id makeFloat16Constant(float f16, bool specConstant = false); + Id makeFpConstant(Id type, double d, bool specConstant = false); + + // Turn the array of constants into a proper spv constant of the requested type. + Id makeCompositeConstant(Id type, const std::vector& comps, bool specConst = false); + + // Methods for adding information outside the CFG. + Instruction* addEntryPoint(ExecutionModel, Function*, const char* name); + void addExecutionMode(Function*, ExecutionMode mode, int value1 = -1, int value2 = -1, int value3 = -1); + void addName(Id, const char* name); + void addMemberName(Id, int member, const char* name); + void addDecoration(Id, Decoration, int num = -1); + void addDecoration(Id, Decoration, const char*); + void addDecorationId(Id id, Decoration, Id idDecoration); + void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1); + void addMemberDecoration(Id, unsigned int member, Decoration, const char*); + + // At the end of what block do the next create*() instructions go? + void setBuildPoint(Block* bp) { buildPoint = bp; } + Block* getBuildPoint() const { return buildPoint; } + + // Make the entry-point function. The returned pointer is only valid + // for the lifetime of this builder. + Function* makeEntryPoint(const char*); + + // Make a shader-style function, and create its entry block if entry is non-zero. + // Return the function, pass back the entry. + // The returned pointer is only valid for the lifetime of this builder. + Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, + const std::vector& paramTypes, const std::vector>& precisions, Block **entry = 0); + + // Create a return. An 'implicit' return is one not appearing in the source + // code. In the case of an implicit return, no post-return block is inserted. + void makeReturn(bool implicit, Id retVal = 0); + + // Generate all the code needed to finish up a function. + void leaveFunction(); + + // Create a discard. + void makeDiscard(); + + // Create a global or function local or IO variable. + Id createVariable(StorageClass, Id type, const char* name = 0, Id initializer = NoResult); + + // Create an intermediate with an undefined value. + Id createUndefined(Id type); + + // Store into an Id and return the l-value + void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + + // Load from an Id and return it + Id createLoad(Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + + // Create an OpAccessChain instruction + Id createAccessChain(StorageClass, Id base, const std::vector& offsets); + + // Create an OpArrayLength instruction + Id createArrayLength(Id base, unsigned int member); + + // Create an OpCooperativeMatrixLengthNV instruction + Id createCooperativeMatrixLength(Id type); + + // Create an OpCompositeExtract instruction + Id createCompositeExtract(Id composite, Id typeId, unsigned index); + Id createCompositeExtract(Id composite, Id typeId, const std::vector& indexes); + Id createCompositeInsert(Id object, Id composite, Id typeId, unsigned index); + Id createCompositeInsert(Id object, Id composite, Id typeId, const std::vector& indexes); + + Id createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex); + Id createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex); + + void createNoResultOp(Op); + void createNoResultOp(Op, Id operand); + void createNoResultOp(Op, const std::vector& operands); + void createNoResultOp(Op, const std::vector& operands); + void createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask); + void createMemoryBarrier(unsigned executionScope, unsigned memorySemantics); + Id createUnaryOp(Op, Id typeId, Id operand); + Id createBinOp(Op, Id typeId, Id operand1, Id operand2); + Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3); + Id createOp(Op, Id typeId, const std::vector& operands); + Id createOp(Op, Id typeId, const std::vector& operands); + Id createFunctionCall(spv::Function*, const std::vector&); + Id createSpecConstantOp(Op, Id typeId, const std::vector& operands, const std::vector& literals); + + // Take an rvalue (source) and a set of channels to extract from it to + // make a new rvalue, which is returned. + Id createRvalueSwizzle(Decoration precision, Id typeId, Id source, const std::vector& channels); + + // Take a copy of an lvalue (target) and a source of components, and set the + // source components into the lvalue where the 'channels' say to put them. + // An updated version of the target is returned. + // (No true lvalue or stores are used.) + Id createLvalueSwizzle(Id typeId, Id target, Id source, const std::vector& channels); + + // If both the id and precision are valid, the id + // gets tagged with the requested precision. + // The passed in id is always the returned id, to simplify use patterns. + Id setPrecision(Id id, Decoration precision) + { + if (precision != NoPrecision && id != NoResult) + addDecoration(id, precision); + + return id; + } + + // Can smear a scalar to a vector for the following forms: + // - promoteScalar(scalar, vector) // smear scalar to width of vector + // - promoteScalar(vector, scalar) // smear scalar to width of vector + // - promoteScalar(pointer, scalar) // smear scalar to width of what pointer points to + // - promoteScalar(scalar, scalar) // do nothing + // Other forms are not allowed. + // + // Generally, the type of 'scalar' does not need to be the same type as the components in 'vector'. + // The type of the created vector is a vector of components of the same type as the scalar. + // + // Note: One of the arguments will change, with the result coming back that way rather than + // through the return value. + void promoteScalar(Decoration precision, Id& left, Id& right); + + // Make a value by smearing the scalar to fill the type. + // vectorType should be the correct type for making a vector of scalarVal. + // (No conversions are done.) + Id smearScalar(Decoration precision, Id scalarVal, Id vectorType); + + // Create a call to a built-in function. + Id createBuiltinCall(Id resultType, Id builtins, int entryPoint, const std::vector& args); + + // List of parameters used to create a texture operation + struct TextureParameters { + Id sampler; + Id coords; + Id bias; + Id lod; + Id Dref; + Id offset; + Id offsets; + Id gradX; + Id gradY; + Id sample; + Id component; + Id texelOut; + Id lodClamp; + Id granularity; + Id coarse; + bool nonprivate; + bool volatil; + }; + + // Select the correct texture operation based on all inputs, and emit the correct instruction + Id createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, + bool noImplicit, const TextureParameters&, ImageOperandsMask); + + // Emit the OpTextureQuery* instruction that was passed in. + // Figure out the right return value and type, and return it. + Id createTextureQueryCall(Op, const TextureParameters&, bool isUnsignedResult); + + Id createSamplePositionCall(Decoration precision, Id, Id); + + Id createBitFieldExtractCall(Decoration precision, Id, Id, Id, bool isSigned); + Id createBitFieldInsertCall(Decoration precision, Id, Id, Id, Id); + + // Reduction comparison for composites: For equal and not-equal resulting in a scalar. + Id createCompositeCompare(Decoration precision, Id, Id, bool /* true if for equal, false if for not-equal */); + + // OpCompositeConstruct + Id createCompositeConstruct(Id typeId, const std::vector& constituents); + + // vector or scalar constructor + Id createConstructor(Decoration precision, const std::vector& sources, Id resultTypeId); + + // matrix constructor + Id createMatrixConstructor(Decoration precision, const std::vector& sources, Id constructee); + + // Helper to use for building nested control flow with if-then-else. + class If { + public: + If(Id condition, unsigned int ctrl, Builder& builder); + ~If() {} + + void makeBeginElse(); + void makeEndIf(); + + private: + If(const If&); + If& operator=(If&); + + Builder& builder; + Id condition; + unsigned int control; + Function* function; + Block* headerBlock; + Block* thenBlock; + Block* elseBlock; + Block* mergeBlock; + }; + + // Make a switch statement. A switch has 'numSegments' of pieces of code, not containing + // any case/default labels, all separated by one or more case/default labels. Each possible + // case value v is a jump to the caseValues[v] segment. The defaultSegment is also in this + // number space. How to compute the value is given by 'condition', as in switch(condition). + // + // The SPIR-V Builder will maintain the stack of post-switch merge blocks for nested switches. + // + // Use a defaultSegment < 0 if there is no default segment (to branch to post switch). + // + // Returns the right set of basic blocks to start each code segment with, so that the caller's + // recursion stack can hold the memory for it. + // + void makeSwitch(Id condition, unsigned int control, int numSegments, const std::vector& caseValues, + const std::vector& valueToSegment, int defaultSegment, std::vector& segmentBB); + + // Add a branch to the innermost switch's merge block. + void addSwitchBreak(); + + // Move to the next code segment, passing in the return argument in makeSwitch() + void nextSwitchSegment(std::vector& segmentBB, int segment); + + // Finish off the innermost switch. + void endSwitch(std::vector& segmentBB); + + struct LoopBlocks { + LoopBlocks(Block& head, Block& body, Block& merge, Block& continue_target) : + head(head), body(body), merge(merge), continue_target(continue_target) { } + Block &head, &body, &merge, &continue_target; + private: + LoopBlocks(); + LoopBlocks& operator=(const LoopBlocks&) = delete; + }; + + // Start a new loop and prepare the builder to generate code for it. Until + // closeLoop() is called for this loop, createLoopContinue() and + // createLoopExit() will target its corresponding blocks. + LoopBlocks& makeNewLoop(); + + // Create a new block in the function containing the build point. Memory is + // owned by the function object. + Block& makeNewBlock(); + + // Add a branch to the continue_target of the current (innermost) loop. + void createLoopContinue(); + + // Add an exit (e.g. "break") from the innermost loop that we're currently + // in. + void createLoopExit(); + + // Close the innermost loop that you're in + void closeLoop(); + + // + // Access chain design for an R-Value vs. L-Value: + // + // There is a single access chain the builder is building at + // any particular time. Such a chain can be used to either to a load or + // a store, when desired. + // + // Expressions can be r-values, l-values, or both, or only r-values: + // a[b.c].d = .... // l-value + // ... = a[b.c].d; // r-value, that also looks like an l-value + // ++a[b.c].d; // r-value and l-value + // (x + y)[2]; // r-value only, can't possibly be l-value + // + // Computing an r-value means generating code. Hence, + // r-values should only be computed when they are needed, not speculatively. + // + // Computing an l-value means saving away information for later use in the compiler, + // no code is generated until the l-value is later dereferenced. It is okay + // to speculatively generate an l-value, just not okay to speculatively dereference it. + // + // The base of the access chain (the left-most variable or expression + // from which everything is based) can be set either as an l-value + // or as an r-value. Most efficient would be to set an l-value if one + // is available. If an expression was evaluated, the resulting r-value + // can be set as the chain base. + // + // The users of this single access chain can save and restore if they + // want to nest or manage multiple chains. + // + + struct AccessChain { + Id base; // for l-values, pointer to the base object, for r-values, the base object + std::vector indexChain; + Id instr; // cache the instruction that generates this access chain + std::vector swizzle; // each std::vector element selects the next GLSL component number + Id component; // a dynamic component index, can coexist with a swizzle, + // done after the swizzle, NoResult if not present + Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied; + // NoType unless a swizzle or component is present + bool isRValue; // true if 'base' is an r-value, otherwise, base is an l-value + unsigned int alignment; // bitwise OR of alignment values passed in. Accumulates worst alignment. + // Only tracks base and (optional) component selection alignment. + + // Accumulate whether anything in the chain of structures has coherent decorations. + struct CoherentFlags { + CoherentFlags() { clear(); } +#ifdef GLSLANG_WEB + void clear() { } + bool isVolatile() const { return false; } + CoherentFlags operator |=(const CoherentFlags &other) { return *this; } +#else + bool isVolatile() const { return volatil; } + bool anyCoherent() const { + return coherent || devicecoherent || queuefamilycoherent || workgroupcoherent || + subgroupcoherent || shadercallcoherent; + } + + unsigned coherent : 1; + unsigned devicecoherent : 1; + unsigned queuefamilycoherent : 1; + unsigned workgroupcoherent : 1; + unsigned subgroupcoherent : 1; + unsigned shadercallcoherent : 1; + unsigned nonprivate : 1; + unsigned volatil : 1; + unsigned isImage : 1; + + void clear() { + coherent = 0; + devicecoherent = 0; + queuefamilycoherent = 0; + workgroupcoherent = 0; + subgroupcoherent = 0; + shadercallcoherent = 0; + nonprivate = 0; + volatil = 0; + isImage = 0; + } + + CoherentFlags operator |=(const CoherentFlags &other) { + coherent |= other.coherent; + devicecoherent |= other.devicecoherent; + queuefamilycoherent |= other.queuefamilycoherent; + workgroupcoherent |= other.workgroupcoherent; + subgroupcoherent |= other.subgroupcoherent; + shadercallcoherent |= other.shadercallcoherent; + nonprivate |= other.nonprivate; + volatil |= other.volatil; + isImage |= other.isImage; + return *this; + } +#endif + }; + CoherentFlags coherentFlags; + }; + + // + // the SPIR-V builder maintains a single active chain that + // the following methods operate on + // + + // for external save and restore + AccessChain getAccessChain() { return accessChain; } + void setAccessChain(AccessChain newChain) { accessChain = newChain; } + + // clear accessChain + void clearAccessChain(); + + // set new base as an l-value base + void setAccessChainLValue(Id lValue) + { + assert(isPointer(lValue)); + accessChain.base = lValue; + } + + // set new base value as an r-value + void setAccessChainRValue(Id rValue) + { + accessChain.isRValue = true; + accessChain.base = rValue; + } + + // push offset onto the end of the chain + void accessChainPush(Id offset, AccessChain::CoherentFlags coherentFlags, unsigned int alignment) + { + accessChain.indexChain.push_back(offset); + accessChain.coherentFlags |= coherentFlags; + accessChain.alignment |= alignment; + } + + // push new swizzle onto the end of any existing swizzle, merging into a single swizzle + void accessChainPushSwizzle(std::vector& swizzle, Id preSwizzleBaseType, + AccessChain::CoherentFlags coherentFlags, unsigned int alignment); + + // push a dynamic component selection onto the access chain, only applicable with a + // non-trivial swizzle or no swizzle + void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, + unsigned int alignment) + { + if (accessChain.swizzle.size() != 1) { + accessChain.component = component; + if (accessChain.preSwizzleBaseType == NoType) + accessChain.preSwizzleBaseType = preSwizzleBaseType; + } + accessChain.coherentFlags |= coherentFlags; + accessChain.alignment |= alignment; + } + + // use accessChain and swizzle to store value + void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, + spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); + + // use accessChain and swizzle to load an r-value + Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType, + spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, + unsigned int alignment = 0); + + // Return whether or not the access chain can be represented in SPIR-V + // as an l-value. + // E.g., a[3].yx cannot be, while a[3].y and a[3].y[x] can be. + bool isSpvLvalue() const { return accessChain.swizzle.size() <= 1; } + + // get the direct pointer for an l-value + Id accessChainGetLValue(); + + // Get the inferred SPIR-V type of the result of the current access chain, + // based on the type of the base and the chain of dereferences. + Id accessChainGetInferredType(); + + // Add capabilities, extensions, remove unneeded decorations, etc., + // based on the resulting SPIR-V. + void postProcess(); + + // Prune unreachable blocks in the CFG and remove unneeded decorations. + void postProcessCFG(); + +#ifndef GLSLANG_WEB + // Add capabilities, extensions based on instructions in the module. + void postProcessFeatures(); + // Hook to visit each instruction in a block in a function + void postProcess(Instruction&); + // Hook to visit each non-32-bit sized float/int operation in a block. + void postProcessType(const Instruction&, spv::Id typeId); +#endif + + void dump(std::vector&) const; + + void createBranch(Block* block); + void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock); + void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, + const std::vector& operands); + + // Sets to generate opcode for specialization constants. + void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; } + // Sets to generate opcode for non-specialization constants (normal mode). + void setToNormalCodeGenMode() { generatingOpCodeForSpecConst = false; } + // Check if the builder is generating code for spec constants. + bool isInSpecConstCodeGenMode() { return generatingOpCodeForSpecConst; } + + protected: + Id makeIntConstant(Id typeId, unsigned value, bool specConstant); + Id makeInt64Constant(Id typeId, unsigned long long value, bool specConstant); + Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value); + Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2); + Id findCompositeConstant(Op typeClass, Id typeId, const std::vector& comps); + Id findStructConstant(Id typeId, const std::vector& comps); + Id collapseAccessChain(); + void remapDynamicSwizzle(); + void transferAccessChainSwizzle(bool dynamic); + void simplifyAccessChainSwizzle(); + void createAndSetNoPredecessorBlock(const char*); + void createSelectionMerge(Block* mergeBlock, unsigned int control); + void dumpSourceInstructions(std::vector&) const; + void dumpSourceInstructions(const spv::Id fileId, const std::string& text, std::vector&) const; + void dumpInstructions(std::vector&, const std::vector >&) const; + void dumpModuleProcesses(std::vector&) const; + spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) + const; + + unsigned int spvVersion; // the version of SPIR-V to emit in the header + SourceLanguage source; + int sourceVersion; + spv::Id sourceFileStringId; + std::string sourceText; + int currentLine; + const char* currentFile; + bool emitOpLines; + std::set extensions; + std::vector sourceExtensions; + std::vector moduleProcesses; + AddressingModel addressModel; + MemoryModel memoryModel; + std::set capabilities; + int builderNumber; + Module module; + Block* buildPoint; + Id uniqueId; + Function* entryPointFunction; + bool generatingOpCodeForSpecConst; + AccessChain accessChain; + + // special blocks of instructions for output + std::vector > strings; + std::vector > imports; + std::vector > entryPoints; + std::vector > executionModes; + std::vector > names; + std::vector > decorations; + std::vector > constantsTypesGlobals; + std::vector > externals; + std::vector > functions; + + // not output, internally used for quick & dirty canonical (unique) creation + + // map type opcodes to constant inst. + std::unordered_map> groupedConstants; + // map struct-id to constant instructions + std::unordered_map> groupedStructConstants; + // map type opcodes to type instructions + std::unordered_map> groupedTypes; + + // stack of switches + std::stack switchMerges; + + // Our loop stack. + std::stack loops; + + // map from strings to their string ids + std::unordered_map stringIds; + + // map from include file name ids to their contents + std::map includeFiles; + + // The stream for outputting warnings and errors. + SpvBuildLogger* logger; +}; // end Builder class + +}; // end spv namespace + +#endif // SpvBuilder_H diff --git a/mac/include/glslang/SPIRV/SpvTools.h b/mac/include/glslang/SPIRV/SpvTools.h new file mode 100644 index 00000000..59c914da --- /dev/null +++ b/mac/include/glslang/SPIRV/SpvTools.h @@ -0,0 +1,82 @@ +// +// Copyright (C) 2014-2016 LunarG, Inc. +// Copyright (C) 2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Call into SPIRV-Tools to disassemble, validate, and optimize. +// + +#pragma once +#ifndef GLSLANG_SPV_TOOLS_H +#define GLSLANG_SPV_TOOLS_H + +#ifdef ENABLE_OPT +#include +#include +#endif + +#include "glslang/MachineIndependent/localintermediate.h" +#include "Logger.h" + +namespace glslang { + +struct SpvOptions { + SpvOptions() : generateDebugInfo(false), disableOptimizer(true), + optimizeSize(false), disassemble(false), validate(false) { } + bool generateDebugInfo; + bool disableOptimizer; + bool optimizeSize; + bool disassemble; + bool validate; +}; + +#ifdef ENABLE_OPT + +// Use the SPIRV-Tools disassembler to print SPIR-V. +void SpirvToolsDisassemble(std::ostream& out, const std::vector& spirv); + +// Apply the SPIRV-Tools validator to generated SPIR-V. +void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger*, bool prelegalization); + +// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of +// legalizing HLSL SPIR-V. +void SpirvToolsLegalize(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger*, const SpvOptions*); + +#endif + +} // end namespace glslang + +#endif // GLSLANG_SPV_TOOLS_H diff --git a/mac/include/glslang/SPIRV/bitutils.h b/mac/include/glslang/SPIRV/bitutils.h new file mode 100644 index 00000000..22e44cec --- /dev/null +++ b/mac/include/glslang/SPIRV/bitutils.h @@ -0,0 +1,81 @@ +// Copyright (c) 2015-2016 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef LIBSPIRV_UTIL_BITUTILS_H_ +#define LIBSPIRV_UTIL_BITUTILS_H_ + +#include +#include + +namespace spvutils { + +// Performs a bitwise copy of source to the destination type Dest. +template +Dest BitwiseCast(Src source) { + Dest dest; + static_assert(sizeof(source) == sizeof(dest), + "BitwiseCast: Source and destination must have the same size"); + std::memcpy(static_cast(&dest), &source, sizeof(dest)); + return dest; +} + +// SetBits returns an integer of type with bits set +// for position through , counting from the least +// significant bit. In particular when Num == 0, no positions are set to 1. +// A static assert will be triggered if First + Num > sizeof(T) * 8, that is, +// a bit that will not fit in the underlying type is set. +template +struct SetBits { + static_assert(First < sizeof(T) * 8, + "Tried to set a bit that is shifted too far."); + const static T get = (T(1) << First) | SetBits::get; +}; + +template +struct SetBits { + const static T get = T(0); +}; + +// This is all compile-time so we can put our tests right here. +static_assert(SetBits::get == uint32_t(0x00000000), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x00000001), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x80000000), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x00000006), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0xc0000000), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0x7FFFFFFF), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0xFFFFFFFF), + "SetBits failed"); +static_assert(SetBits::get == uint32_t(0xFFFF0000), + "SetBits failed"); + +static_assert(SetBits::get == uint64_t(0x0000000000000001LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0x8000000000000000LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0xc000000000000000LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0x0000000080000000LL), + "SetBits failed"); +static_assert(SetBits::get == uint64_t(0x00000000FFFF0000LL), + "SetBits failed"); + +} // namespace spvutils + +#endif // LIBSPIRV_UTIL_BITUTILS_H_ diff --git a/mac/include/glslang/SPIRV/disassemble.h b/mac/include/glslang/SPIRV/disassemble.h new file mode 100644 index 00000000..b6a46357 --- /dev/null +++ b/mac/include/glslang/SPIRV/disassemble.h @@ -0,0 +1,53 @@ +// +// Copyright (C) 2014-2015 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Disassembler for SPIR-V. +// + +#pragma once +#ifndef disassembler_H +#define disassembler_H + +#include +#include + +namespace spv { + + // disassemble with glslang custom disassembler + void Disassemble(std::ostream& out, const std::vector&); + +} // end namespace spv + +#endif // disassembler_H diff --git a/mac/include/glslang/SPIRV/doc.h b/mac/include/glslang/SPIRV/doc.h new file mode 100644 index 00000000..293256a2 --- /dev/null +++ b/mac/include/glslang/SPIRV/doc.h @@ -0,0 +1,258 @@ +// +// Copyright (C) 2014-2015 LunarG, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// +// Parameterize the SPIR-V enumerants. +// + +#pragma once + +#include "spirv.hpp" + +#include + +namespace spv { + +// Fill in all the parameters +void Parameterize(); + +// Return the English names of all the enums. +const char* SourceString(int); +const char* AddressingString(int); +const char* MemoryString(int); +const char* ExecutionModelString(int); +const char* ExecutionModeString(int); +const char* StorageClassString(int); +const char* DecorationString(int); +const char* BuiltInString(int); +const char* DimensionString(int); +const char* SelectControlString(int); +const char* LoopControlString(int); +const char* FunctionControlString(int); +const char* SamplerAddressingModeString(int); +const char* SamplerFilterModeString(int); +const char* ImageFormatString(int); +const char* ImageChannelOrderString(int); +const char* ImageChannelTypeString(int); +const char* ImageChannelDataTypeString(int type); +const char* ImageOperandsString(int format); +const char* ImageOperands(int); +const char* FPFastMathString(int); +const char* FPRoundingModeString(int); +const char* LinkageTypeString(int); +const char* FuncParamAttrString(int); +const char* AccessQualifierString(int); +const char* MemorySemanticsString(int); +const char* MemoryAccessString(int); +const char* ExecutionScopeString(int); +const char* GroupOperationString(int); +const char* KernelEnqueueFlagsString(int); +const char* KernelProfilingInfoString(int); +const char* CapabilityString(int); +const char* OpcodeString(int); +const char* ScopeString(int mem); + +// For grouping opcodes into subsections +enum OpcodeClass { + OpClassMisc, + OpClassDebug, + OpClassAnnotate, + OpClassExtension, + OpClassMode, + OpClassType, + OpClassConstant, + OpClassMemory, + OpClassFunction, + OpClassImage, + OpClassConvert, + OpClassComposite, + OpClassArithmetic, + OpClassBit, + OpClassRelationalLogical, + OpClassDerivative, + OpClassFlowControl, + OpClassAtomic, + OpClassPrimitive, + OpClassBarrier, + OpClassGroup, + OpClassDeviceSideEnqueue, + OpClassPipe, + + OpClassCount, + OpClassMissing // all instructions start out as missing +}; + +// For parameterizing operands. +enum OperandClass { + OperandNone, + OperandId, + OperandVariableIds, + OperandOptionalLiteral, + OperandOptionalLiteralString, + OperandVariableLiterals, + OperandVariableIdLiteral, + OperandVariableLiteralId, + OperandLiteralNumber, + OperandLiteralString, + OperandSource, + OperandExecutionModel, + OperandAddressing, + OperandMemory, + OperandExecutionMode, + OperandStorage, + OperandDimensionality, + OperandSamplerAddressingMode, + OperandSamplerFilterMode, + OperandSamplerImageFormat, + OperandImageChannelOrder, + OperandImageChannelDataType, + OperandImageOperands, + OperandFPFastMath, + OperandFPRoundingMode, + OperandLinkageType, + OperandAccessQualifier, + OperandFuncParamAttr, + OperandDecoration, + OperandBuiltIn, + OperandSelect, + OperandLoop, + OperandFunction, + OperandMemorySemantics, + OperandMemoryAccess, + OperandScope, + OperandGroupOperation, + OperandKernelEnqueueFlags, + OperandKernelProfilingInfo, + OperandCapability, + + OperandOpcode, + + OperandCount +}; + +// Any specific enum can have a set of capabilities that allow it: +typedef std::vector EnumCaps; + +// Parameterize a set of operands with their OperandClass(es) and descriptions. +class OperandParameters { +public: + OperandParameters() { } + void push(OperandClass oc, const char* d, bool opt = false) + { + opClass.push_back(oc); + desc.push_back(d); + optional.push_back(opt); + } + void setOptional(); + OperandClass getClass(int op) const { return opClass[op]; } + const char* getDesc(int op) const { return desc[op]; } + bool isOptional(int op) const { return optional[op]; } + int getNum() const { return (int)opClass.size(); } + +protected: + std::vector opClass; + std::vector desc; + std::vector optional; +}; + +// Parameterize an enumerant +class EnumParameters { +public: + EnumParameters() : desc(0) { } + const char* desc; +}; + +// Parameterize a set of enumerants that form an enum +class EnumDefinition : public EnumParameters { +public: + EnumDefinition() : + ceiling(0), bitmask(false), getName(0), enumParams(0), operandParams(0) { } + void set(int ceil, const char* (*name)(int), EnumParameters* ep, bool mask = false) + { + ceiling = ceil; + getName = name; + bitmask = mask; + enumParams = ep; + } + void setOperands(OperandParameters* op) { operandParams = op; } + int ceiling; // ceiling of enumerants + bool bitmask; // true if these enumerants combine into a bitmask + const char* (*getName)(int); // a function that returns the name for each enumerant value (or shift) + EnumParameters* enumParams; // parameters for each individual enumerant + OperandParameters* operandParams; // sets of operands +}; + +// Parameterize an instruction's logical format, including its known set of operands, +// per OperandParameters above. +class InstructionParameters { +public: + InstructionParameters() : + opDesc("TBD"), + opClass(OpClassMissing), + typePresent(true), // most normal, only exceptions have to be spelled out + resultPresent(true) // most normal, only exceptions have to be spelled out + { } + + void setResultAndType(bool r, bool t) + { + resultPresent = r; + typePresent = t; + } + + bool hasResult() const { return resultPresent != 0; } + bool hasType() const { return typePresent != 0; } + + const char* opDesc; + OpcodeClass opClass; + OperandParameters operands; + +protected: + int typePresent : 1; + int resultPresent : 1; +}; + +// The set of objects that hold all the instruction/operand +// parameterization information. +extern InstructionParameters InstructionDesc[]; + +// These hold definitions of the enumerants used for operands +extern EnumDefinition OperandClassParams[]; + +const char* GetOperandDesc(OperandClass operand); +void PrintImmediateRow(int imm, const char* name, const EnumParameters* enumParams, bool caps, bool hex = false); +const char* AccessQualifierString(int attr); + +void PrintOperands(const OperandParameters& operands, int reservedOperands); + +} // end namespace spv diff --git a/mac/include/glslang/SPIRV/hex_float.h b/mac/include/glslang/SPIRV/hex_float.h new file mode 100644 index 00000000..8be8e9f7 --- /dev/null +++ b/mac/include/glslang/SPIRV/hex_float.h @@ -0,0 +1,1078 @@ +// Copyright (c) 2015-2016 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef LIBSPIRV_UTIL_HEX_FLOAT_H_ +#define LIBSPIRV_UTIL_HEX_FLOAT_H_ + +#include +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) && _MSC_VER < 1800 +namespace std { +bool isnan(double f) +{ + return ::_isnan(f) != 0; +} +bool isinf(double f) +{ + return ::_finite(f) == 0; +} +} +#endif + +#include "bitutils.h" + +namespace spvutils { + +class Float16 { + public: + Float16(uint16_t v) : val(v) {} + Float16() {} + static bool isNan(const Float16& val) { + return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) != 0); + } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(const Float16& val) { + return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) == 0); + } + Float16(const Float16& other) { val = other.val; } + uint16_t get_value() const { return val; } + + // Returns the maximum normal value. + static Float16 max() { return Float16(0x7bff); } + // Returns the lowest normal value. + static Float16 lowest() { return Float16(0xfbff); } + + private: + uint16_t val; +}; + +// To specialize this type, you must override uint_type to define +// an unsigned integer that can fit your floating point type. +// You must also add a isNan function that returns true if +// a value is Nan. +template +struct FloatProxyTraits { + typedef void uint_type; +}; + +template <> +struct FloatProxyTraits { + typedef uint32_t uint_type; + static bool isNan(float f) { return std::isnan(f); } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(float f) { return std::isinf(f); } + // Returns the maximum normal value. + static float max() { return std::numeric_limits::max(); } + // Returns the lowest normal value. + static float lowest() { return std::numeric_limits::lowest(); } +}; + +template <> +struct FloatProxyTraits { + typedef uint64_t uint_type; + static bool isNan(double f) { return std::isnan(f); } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(double f) { return std::isinf(f); } + // Returns the maximum normal value. + static double max() { return std::numeric_limits::max(); } + // Returns the lowest normal value. + static double lowest() { return std::numeric_limits::lowest(); } +}; + +template <> +struct FloatProxyTraits { + typedef uint16_t uint_type; + static bool isNan(Float16 f) { return Float16::isNan(f); } + // Returns true if the given value is any kind of infinity. + static bool isInfinity(Float16 f) { return Float16::isInfinity(f); } + // Returns the maximum normal value. + static Float16 max() { return Float16::max(); } + // Returns the lowest normal value. + static Float16 lowest() { return Float16::lowest(); } +}; + +// Since copying a floating point number (especially if it is NaN) +// does not guarantee that bits are preserved, this class lets us +// store the type and use it as a float when necessary. +template +class FloatProxy { + public: + typedef typename FloatProxyTraits::uint_type uint_type; + + // Since this is to act similar to the normal floats, + // do not initialize the data by default. + FloatProxy() {} + + // Intentionally non-explicit. This is a proxy type so + // implicit conversions allow us to use it more transparently. + FloatProxy(T val) { data_ = BitwiseCast(val); } + + // Intentionally non-explicit. This is a proxy type so + // implicit conversions allow us to use it more transparently. + FloatProxy(uint_type val) { data_ = val; } + + // This is helpful to have and is guaranteed not to stomp bits. + FloatProxy operator-() const { + return static_cast(data_ ^ + (uint_type(0x1) << (sizeof(T) * 8 - 1))); + } + + // Returns the data as a floating point value. + T getAsFloat() const { return BitwiseCast(data_); } + + // Returns the raw data. + uint_type data() const { return data_; } + + // Returns true if the value represents any type of NaN. + bool isNan() { return FloatProxyTraits::isNan(getAsFloat()); } + // Returns true if the value represents any type of infinity. + bool isInfinity() { return FloatProxyTraits::isInfinity(getAsFloat()); } + + // Returns the maximum normal value. + static FloatProxy max() { + return FloatProxy(FloatProxyTraits::max()); + } + // Returns the lowest normal value. + static FloatProxy lowest() { + return FloatProxy(FloatProxyTraits::lowest()); + } + + private: + uint_type data_; +}; + +template +bool operator==(const FloatProxy& first, const FloatProxy& second) { + return first.data() == second.data(); +} + +// Reads a FloatProxy value as a normal float from a stream. +template +std::istream& operator>>(std::istream& is, FloatProxy& value) { + T float_val; + is >> float_val; + value = FloatProxy(float_val); + return is; +} + +// This is an example traits. It is not meant to be used in practice, but will +// be the default for any non-specialized type. +template +struct HexFloatTraits { + // Integer type that can store this hex-float. + typedef void uint_type; + // Signed integer type that can store this hex-float. + typedef void int_type; + // The numerical type that this HexFloat represents. + typedef void underlying_type; + // The type needed to construct the underlying type. + typedef void native_type; + // The number of bits that are actually relevant in the uint_type. + // This allows us to deal with, for example, 24-bit values in a 32-bit + // integer. + static const uint32_t num_used_bits = 0; + // Number of bits that represent the exponent. + static const uint32_t num_exponent_bits = 0; + // Number of bits that represent the fractional part. + static const uint32_t num_fraction_bits = 0; + // The bias of the exponent. (How much we need to subtract from the stored + // value to get the correct value.) + static const uint32_t exponent_bias = 0; +}; + +// Traits for IEEE float. +// 1 sign bit, 8 exponent bits, 23 fractional bits. +template <> +struct HexFloatTraits> { + typedef uint32_t uint_type; + typedef int32_t int_type; + typedef FloatProxy underlying_type; + typedef float native_type; + static const uint_type num_used_bits = 32; + static const uint_type num_exponent_bits = 8; + static const uint_type num_fraction_bits = 23; + static const uint_type exponent_bias = 127; +}; + +// Traits for IEEE double. +// 1 sign bit, 11 exponent bits, 52 fractional bits. +template <> +struct HexFloatTraits> { + typedef uint64_t uint_type; + typedef int64_t int_type; + typedef FloatProxy underlying_type; + typedef double native_type; + static const uint_type num_used_bits = 64; + static const uint_type num_exponent_bits = 11; + static const uint_type num_fraction_bits = 52; + static const uint_type exponent_bias = 1023; +}; + +// Traits for IEEE half. +// 1 sign bit, 5 exponent bits, 10 fractional bits. +template <> +struct HexFloatTraits> { + typedef uint16_t uint_type; + typedef int16_t int_type; + typedef uint16_t underlying_type; + typedef uint16_t native_type; + static const uint_type num_used_bits = 16; + static const uint_type num_exponent_bits = 5; + static const uint_type num_fraction_bits = 10; + static const uint_type exponent_bias = 15; +}; + +enum round_direction { + kRoundToZero, + kRoundToNearestEven, + kRoundToPositiveInfinity, + kRoundToNegativeInfinity +}; + +// Template class that houses a floating pointer number. +// It exposes a number of constants based on the provided traits to +// assist in interpreting the bits of the value. +template > +class HexFloat { + public: + typedef typename Traits::uint_type uint_type; + typedef typename Traits::int_type int_type; + typedef typename Traits::underlying_type underlying_type; + typedef typename Traits::native_type native_type; + + explicit HexFloat(T f) : value_(f) {} + + T value() const { return value_; } + void set_value(T f) { value_ = f; } + + // These are all written like this because it is convenient to have + // compile-time constants for all of these values. + + // Pass-through values to save typing. + static const uint32_t num_used_bits = Traits::num_used_bits; + static const uint32_t exponent_bias = Traits::exponent_bias; + static const uint32_t num_exponent_bits = Traits::num_exponent_bits; + static const uint32_t num_fraction_bits = Traits::num_fraction_bits; + + // Number of bits to shift left to set the highest relevant bit. + static const uint32_t top_bit_left_shift = num_used_bits - 1; + // How many nibbles (hex characters) the fractional part takes up. + static const uint32_t fraction_nibbles = (num_fraction_bits + 3) / 4; + // If the fractional part does not fit evenly into a hex character (4-bits) + // then we have to left-shift to get rid of leading 0s. This is the amount + // we have to shift (might be 0). + static const uint32_t num_overflow_bits = + fraction_nibbles * 4 - num_fraction_bits; + + // The representation of the fraction, not the actual bits. This + // includes the leading bit that is usually implicit. + static const uint_type fraction_represent_mask = + spvutils::SetBits::get; + + // The topmost bit in the nibble-aligned fraction. + static const uint_type fraction_top_bit = + uint_type(1) << (num_fraction_bits + num_overflow_bits - 1); + + // The least significant bit in the exponent, which is also the bit + // immediately to the left of the significand. + static const uint_type first_exponent_bit = uint_type(1) + << (num_fraction_bits); + + // The mask for the encoded fraction. It does not include the + // implicit bit. + static const uint_type fraction_encode_mask = + spvutils::SetBits::get; + + // The bit that is used as a sign. + static const uint_type sign_mask = uint_type(1) << top_bit_left_shift; + + // The bits that represent the exponent. + static const uint_type exponent_mask = + spvutils::SetBits::get; + + // How far left the exponent is shifted. + static const uint32_t exponent_left_shift = num_fraction_bits; + + // How far from the right edge the fraction is shifted. + static const uint32_t fraction_right_shift = + static_cast(sizeof(uint_type) * 8) - num_fraction_bits; + + // The maximum representable unbiased exponent. + static const int_type max_exponent = + (exponent_mask >> num_fraction_bits) - exponent_bias; + // The minimum representable exponent for normalized numbers. + static const int_type min_exponent = -static_cast(exponent_bias); + + // Returns the bits associated with the value. + uint_type getBits() const { return spvutils::BitwiseCast(value_); } + + // Returns the bits associated with the value, without the leading sign bit. + uint_type getUnsignedBits() const { + return static_cast(spvutils::BitwiseCast(value_) & + ~sign_mask); + } + + // Returns the bits associated with the exponent, shifted to start at the + // lsb of the type. + const uint_type getExponentBits() const { + return static_cast((getBits() & exponent_mask) >> + num_fraction_bits); + } + + // Returns the exponent in unbiased form. This is the exponent in the + // human-friendly form. + const int_type getUnbiasedExponent() const { + return static_cast(getExponentBits() - exponent_bias); + } + + // Returns just the significand bits from the value. + const uint_type getSignificandBits() const { + return getBits() & fraction_encode_mask; + } + + // If the number was normalized, returns the unbiased exponent. + // If the number was denormal, normalize the exponent first. + const int_type getUnbiasedNormalizedExponent() const { + if ((getBits() & ~sign_mask) == 0) { // special case if everything is 0 + return 0; + } + int_type exp = getUnbiasedExponent(); + if (exp == min_exponent) { // We are in denorm land. + uint_type significand_bits = getSignificandBits(); + while ((significand_bits & (first_exponent_bit >> 1)) == 0) { + significand_bits = static_cast(significand_bits << 1); + exp = static_cast(exp - 1); + } + significand_bits &= fraction_encode_mask; + } + return exp; + } + + // Returns the signficand after it has been normalized. + const uint_type getNormalizedSignificand() const { + int_type unbiased_exponent = getUnbiasedNormalizedExponent(); + uint_type significand = getSignificandBits(); + for (int_type i = unbiased_exponent; i <= min_exponent; ++i) { + significand = static_cast(significand << 1); + } + significand &= fraction_encode_mask; + return significand; + } + + // Returns true if this number represents a negative value. + bool isNegative() const { return (getBits() & sign_mask) != 0; } + + // Sets this HexFloat from the individual components. + // Note this assumes EVERY significand is normalized, and has an implicit + // leading one. This means that the only way that this method will set 0, + // is if you set a number so denormalized that it underflows. + // Do not use this method with raw bits extracted from a subnormal number, + // since subnormals do not have an implicit leading 1 in the significand. + // The significand is also expected to be in the + // lowest-most num_fraction_bits of the uint_type. + // The exponent is expected to be unbiased, meaning an exponent of + // 0 actually means 0. + // If underflow_round_up is set, then on underflow, if a number is non-0 + // and would underflow, we round up to the smallest denorm. + void setFromSignUnbiasedExponentAndNormalizedSignificand( + bool negative, int_type exponent, uint_type significand, + bool round_denorm_up) { + bool significand_is_zero = significand == 0; + + if (exponent <= min_exponent) { + // If this was denormalized, then we have to shift the bit on, meaning + // the significand is not zero. + significand_is_zero = false; + significand |= first_exponent_bit; + significand = static_cast(significand >> 1); + } + + while (exponent < min_exponent) { + significand = static_cast(significand >> 1); + ++exponent; + } + + if (exponent == min_exponent) { + if (significand == 0 && !significand_is_zero && round_denorm_up) { + significand = static_cast(0x1); + } + } + + uint_type new_value = 0; + if (negative) { + new_value = static_cast(new_value | sign_mask); + } + exponent = static_cast(exponent + exponent_bias); + assert(exponent >= 0); + + // put it all together + exponent = static_cast((exponent << exponent_left_shift) & + exponent_mask); + significand = static_cast(significand & fraction_encode_mask); + new_value = static_cast(new_value | (exponent | significand)); + value_ = BitwiseCast(new_value); + } + + // Increments the significand of this number by the given amount. + // If this would spill the significand into the implicit bit, + // carry is set to true and the significand is shifted to fit into + // the correct location, otherwise carry is set to false. + // All significands and to_increment are assumed to be within the bounds + // for a valid significand. + static uint_type incrementSignificand(uint_type significand, + uint_type to_increment, bool* carry) { + significand = static_cast(significand + to_increment); + *carry = false; + if (significand & first_exponent_bit) { + *carry = true; + // The implicit 1-bit will have carried, so we should zero-out the + // top bit and shift back. + significand = static_cast(significand & ~first_exponent_bit); + significand = static_cast(significand >> 1); + } + return significand; + } + + // These exist because MSVC throws warnings on negative right-shifts + // even if they are not going to be executed. Eg: + // constant_number < 0? 0: constant_number + // These convert the negative left-shifts into right shifts. + + template + uint_type negatable_left_shift(int_type N, uint_type val) + { + if(N >= 0) + return val << N; + + return val >> -N; + } + + template + uint_type negatable_right_shift(int_type N, uint_type val) + { + if(N >= 0) + return val >> N; + + return val << -N; + } + + // Returns the significand, rounded to fit in a significand in + // other_T. This is shifted so that the most significant + // bit of the rounded number lines up with the most significant bit + // of the returned significand. + template + typename other_T::uint_type getRoundedNormalizedSignificand( + round_direction dir, bool* carry_bit) { + typedef typename other_T::uint_type other_uint_type; + static const int_type num_throwaway_bits = + static_cast(num_fraction_bits) - + static_cast(other_T::num_fraction_bits); + + static const uint_type last_significant_bit = + (num_throwaway_bits < 0) + ? 0 + : negatable_left_shift(num_throwaway_bits, 1u); + static const uint_type first_rounded_bit = + (num_throwaway_bits < 1) + ? 0 + : negatable_left_shift(num_throwaway_bits - 1, 1u); + + static const uint_type throwaway_mask_bits = + num_throwaway_bits > 0 ? num_throwaway_bits : 0; + static const uint_type throwaway_mask = + spvutils::SetBits::get; + + *carry_bit = false; + other_uint_type out_val = 0; + uint_type significand = getNormalizedSignificand(); + // If we are up-casting, then we just have to shift to the right location. + if (num_throwaway_bits <= 0) { + out_val = static_cast(significand); + uint_type shift_amount = static_cast(-num_throwaway_bits); + out_val = static_cast(out_val << shift_amount); + return out_val; + } + + // If every non-representable bit is 0, then we don't have any casting to + // do. + if ((significand & throwaway_mask) == 0) { + return static_cast( + negatable_right_shift(num_throwaway_bits, significand)); + } + + bool round_away_from_zero = false; + // We actually have to narrow the significand here, so we have to follow the + // rounding rules. + switch (dir) { + case kRoundToZero: + break; + case kRoundToPositiveInfinity: + round_away_from_zero = !isNegative(); + break; + case kRoundToNegativeInfinity: + round_away_from_zero = isNegative(); + break; + case kRoundToNearestEven: + // Have to round down, round bit is 0 + if ((first_rounded_bit & significand) == 0) { + break; + } + if (((significand & throwaway_mask) & ~first_rounded_bit) != 0) { + // If any subsequent bit of the rounded portion is non-0 then we round + // up. + round_away_from_zero = true; + break; + } + // We are exactly half-way between 2 numbers, pick even. + if ((significand & last_significant_bit) != 0) { + // 1 for our last bit, round up. + round_away_from_zero = true; + break; + } + break; + } + + if (round_away_from_zero) { + return static_cast( + negatable_right_shift(num_throwaway_bits, incrementSignificand( + significand, last_significant_bit, carry_bit))); + } else { + return static_cast( + negatable_right_shift(num_throwaway_bits, significand)); + } + } + + // Casts this value to another HexFloat. If the cast is widening, + // then round_dir is ignored. If the cast is narrowing, then + // the result is rounded in the direction specified. + // This number will retain Nan and Inf values. + // It will also saturate to Inf if the number overflows, and + // underflow to (0 or min depending on rounding) if the number underflows. + template + void castTo(other_T& other, round_direction round_dir) { + other = other_T(static_cast(0)); + bool negate = isNegative(); + if (getUnsignedBits() == 0) { + if (negate) { + other.set_value(-other.value()); + } + return; + } + uint_type significand = getSignificandBits(); + bool carried = false; + typename other_T::uint_type rounded_significand = + getRoundedNormalizedSignificand(round_dir, &carried); + + int_type exponent = getUnbiasedExponent(); + if (exponent == min_exponent) { + // If we are denormal, normalize the exponent, so that we can encode + // easily. + exponent = static_cast(exponent + 1); + for (uint_type check_bit = first_exponent_bit >> 1; check_bit != 0; + check_bit = static_cast(check_bit >> 1)) { + exponent = static_cast(exponent - 1); + if (check_bit & significand) break; + } + } + + bool is_nan = + (getBits() & exponent_mask) == exponent_mask && significand != 0; + bool is_inf = + !is_nan && + ((exponent + carried) > static_cast(other_T::exponent_bias) || + (significand == 0 && (getBits() & exponent_mask) == exponent_mask)); + + // If we are Nan or Inf we should pass that through. + if (is_inf) { + other.set_value(BitwiseCast( + static_cast( + (negate ? other_T::sign_mask : 0) | other_T::exponent_mask))); + return; + } + if (is_nan) { + typename other_T::uint_type shifted_significand; + shifted_significand = static_cast( + negatable_left_shift( + static_cast(other_T::num_fraction_bits) - + static_cast(num_fraction_bits), significand)); + + // We are some sort of Nan. We try to keep the bit-pattern of the Nan + // as close as possible. If we had to shift off bits so we are 0, then we + // just set the last bit. + other.set_value(BitwiseCast( + static_cast( + (negate ? other_T::sign_mask : 0) | other_T::exponent_mask | + (shifted_significand == 0 ? 0x1 : shifted_significand)))); + return; + } + + bool round_underflow_up = + isNegative() ? round_dir == kRoundToNegativeInfinity + : round_dir == kRoundToPositiveInfinity; + typedef typename other_T::int_type other_int_type; + // setFromSignUnbiasedExponentAndNormalizedSignificand will + // zero out any underflowing value (but retain the sign). + other.setFromSignUnbiasedExponentAndNormalizedSignificand( + negate, static_cast(exponent), rounded_significand, + round_underflow_up); + return; + } + + private: + T value_; + + static_assert(num_used_bits == + Traits::num_exponent_bits + Traits::num_fraction_bits + 1, + "The number of bits do not fit"); + static_assert(sizeof(T) == sizeof(uint_type), "The type sizes do not match"); +}; + +// Returns 4 bits represented by the hex character. +inline uint8_t get_nibble_from_character(int character) { + const char* dec = "0123456789"; + const char* lower = "abcdef"; + const char* upper = "ABCDEF"; + const char* p = nullptr; + if ((p = strchr(dec, character))) { + return static_cast(p - dec); + } else if ((p = strchr(lower, character))) { + return static_cast(p - lower + 0xa); + } else if ((p = strchr(upper, character))) { + return static_cast(p - upper + 0xa); + } + + assert(false && "This was called with a non-hex character"); + return 0; +} + +// Outputs the given HexFloat to the stream. +template +std::ostream& operator<<(std::ostream& os, const HexFloat& value) { + typedef HexFloat HF; + typedef typename HF::uint_type uint_type; + typedef typename HF::int_type int_type; + + static_assert(HF::num_used_bits != 0, + "num_used_bits must be non-zero for a valid float"); + static_assert(HF::num_exponent_bits != 0, + "num_exponent_bits must be non-zero for a valid float"); + static_assert(HF::num_fraction_bits != 0, + "num_fractin_bits must be non-zero for a valid float"); + + const uint_type bits = spvutils::BitwiseCast(value.value()); + const char* const sign = (bits & HF::sign_mask) ? "-" : ""; + const uint_type exponent = static_cast( + (bits & HF::exponent_mask) >> HF::num_fraction_bits); + + uint_type fraction = static_cast((bits & HF::fraction_encode_mask) + << HF::num_overflow_bits); + + const bool is_zero = exponent == 0 && fraction == 0; + const bool is_denorm = exponent == 0 && !is_zero; + + // exponent contains the biased exponent we have to convert it back into + // the normal range. + int_type int_exponent = static_cast(exponent - HF::exponent_bias); + // If the number is all zeros, then we actually have to NOT shift the + // exponent. + int_exponent = is_zero ? 0 : int_exponent; + + // If we are denorm, then start shifting, and decreasing the exponent until + // our leading bit is 1. + + if (is_denorm) { + while ((fraction & HF::fraction_top_bit) == 0) { + fraction = static_cast(fraction << 1); + int_exponent = static_cast(int_exponent - 1); + } + // Since this is denormalized, we have to consume the leading 1 since it + // will end up being implicit. + fraction = static_cast(fraction << 1); // eat the leading 1 + fraction &= HF::fraction_represent_mask; + } + + uint_type fraction_nibbles = HF::fraction_nibbles; + // We do not have to display any trailing 0s, since this represents the + // fractional part. + while (fraction_nibbles > 0 && (fraction & 0xF) == 0) { + // Shift off any trailing values; + fraction = static_cast(fraction >> 4); + --fraction_nibbles; + } + + const auto saved_flags = os.flags(); + const auto saved_fill = os.fill(); + + os << sign << "0x" << (is_zero ? '0' : '1'); + if (fraction_nibbles) { + // Make sure to keep the leading 0s in place, since this is the fractional + // part. + os << "." << std::setw(static_cast(fraction_nibbles)) + << std::setfill('0') << std::hex << fraction; + } + os << "p" << std::dec << (int_exponent >= 0 ? "+" : "") << int_exponent; + + os.flags(saved_flags); + os.fill(saved_fill); + + return os; +} + +// Returns true if negate_value is true and the next character on the +// input stream is a plus or minus sign. In that case we also set the fail bit +// on the stream and set the value to the zero value for its type. +template +inline bool RejectParseDueToLeadingSign(std::istream& is, bool negate_value, + HexFloat& value) { + if (negate_value) { + auto next_char = is.peek(); + if (next_char == '-' || next_char == '+') { + // Fail the parse. Emulate standard behaviour by setting the value to + // the zero value, and set the fail bit on the stream. + value = HexFloat(typename HexFloat::uint_type(0)); + is.setstate(std::ios_base::failbit); + return true; + } + } + return false; +} + +// Parses a floating point number from the given stream and stores it into the +// value parameter. +// If negate_value is true then the number may not have a leading minus or +// plus, and if it successfully parses, then the number is negated before +// being stored into the value parameter. +// If the value cannot be correctly parsed or overflows the target floating +// point type, then set the fail bit on the stream. +// TODO(dneto): Promise C++11 standard behavior in how the value is set in +// the error case, but only after all target platforms implement it correctly. +// In particular, the Microsoft C++ runtime appears to be out of spec. +template +inline std::istream& ParseNormalFloat(std::istream& is, bool negate_value, + HexFloat& value) { + if (RejectParseDueToLeadingSign(is, negate_value, value)) { + return is; + } + T val; + is >> val; + if (negate_value) { + val = -val; + } + value.set_value(val); + // In the failure case, map -0.0 to 0.0. + if (is.fail() && value.getUnsignedBits() == 0u) { + value = HexFloat(typename HexFloat::uint_type(0)); + } + if (val.isInfinity()) { + // Fail the parse. Emulate standard behaviour by setting the value to + // the closest normal value, and set the fail bit on the stream. + value.set_value((value.isNegative() || negate_value) ? T::lowest() + : T::max()); + is.setstate(std::ios_base::failbit); + } + return is; +} + +// Specialization of ParseNormalFloat for FloatProxy values. +// This will parse the float as it were a 32-bit floating point number, +// and then round it down to fit into a Float16 value. +// The number is rounded towards zero. +// If negate_value is true then the number may not have a leading minus or +// plus, and if it successfully parses, then the number is negated before +// being stored into the value parameter. +// If the value cannot be correctly parsed or overflows the target floating +// point type, then set the fail bit on the stream. +// TODO(dneto): Promise C++11 standard behavior in how the value is set in +// the error case, but only after all target platforms implement it correctly. +// In particular, the Microsoft C++ runtime appears to be out of spec. +template <> +inline std::istream& +ParseNormalFloat, HexFloatTraits>>( + std::istream& is, bool negate_value, + HexFloat, HexFloatTraits>>& value) { + // First parse as a 32-bit float. + HexFloat> float_val(0.0f); + ParseNormalFloat(is, negate_value, float_val); + + // Then convert to 16-bit float, saturating at infinities, and + // rounding toward zero. + float_val.castTo(value, kRoundToZero); + + // Overflow on 16-bit behaves the same as for 32- and 64-bit: set the + // fail bit and set the lowest or highest value. + if (Float16::isInfinity(value.value().getAsFloat())) { + value.set_value(value.isNegative() ? Float16::lowest() : Float16::max()); + is.setstate(std::ios_base::failbit); + } + return is; +} + +// Reads a HexFloat from the given stream. +// If the float is not encoded as a hex-float then it will be parsed +// as a regular float. +// This may fail if your stream does not support at least one unget. +// Nan values can be encoded with "0x1.p+exponent_bias". +// This would normally overflow a float and round to +// infinity but this special pattern is the exact representation for a NaN, +// and therefore is actually encoded as the correct NaN. To encode inf, +// either 0x0p+exponent_bias can be specified or any exponent greater than +// exponent_bias. +// Examples using IEEE 32-bit float encoding. +// 0x1.0p+128 (+inf) +// -0x1.0p-128 (-inf) +// +// 0x1.1p+128 (+Nan) +// -0x1.1p+128 (-Nan) +// +// 0x1p+129 (+inf) +// -0x1p+129 (-inf) +template +std::istream& operator>>(std::istream& is, HexFloat& value) { + using HF = HexFloat; + using uint_type = typename HF::uint_type; + using int_type = typename HF::int_type; + + value.set_value(static_cast(0.f)); + + if (is.flags() & std::ios::skipws) { + // If the user wants to skip whitespace , then we should obey that. + while (std::isspace(is.peek())) { + is.get(); + } + } + + auto next_char = is.peek(); + bool negate_value = false; + + if (next_char != '-' && next_char != '0') { + return ParseNormalFloat(is, negate_value, value); + } + + if (next_char == '-') { + negate_value = true; + is.get(); + next_char = is.peek(); + } + + if (next_char == '0') { + is.get(); // We may have to unget this. + auto maybe_hex_start = is.peek(); + if (maybe_hex_start != 'x' && maybe_hex_start != 'X') { + is.unget(); + return ParseNormalFloat(is, negate_value, value); + } else { + is.get(); // Throw away the 'x'; + } + } else { + return ParseNormalFloat(is, negate_value, value); + } + + // This "looks" like a hex-float so treat it as one. + bool seen_p = false; + bool seen_dot = false; + uint_type fraction_index = 0; + + uint_type fraction = 0; + int_type exponent = HF::exponent_bias; + + // Strip off leading zeros so we don't have to special-case them later. + while ((next_char = is.peek()) == '0') { + is.get(); + } + + bool is_denorm = + true; // Assume denorm "representation" until we hear otherwise. + // NB: This does not mean the value is actually denorm, + // it just means that it was written 0. + bool bits_written = false; // Stays false until we write a bit. + while (!seen_p && !seen_dot) { + // Handle characters that are left of the fractional part. + if (next_char == '.') { + seen_dot = true; + } else if (next_char == 'p') { + seen_p = true; + } else if (::isxdigit(next_char)) { + // We know this is not denormalized since we have stripped all leading + // zeroes and we are not a ".". + is_denorm = false; + int number = get_nibble_from_character(next_char); + for (int i = 0; i < 4; ++i, number <<= 1) { + uint_type write_bit = (number & 0x8) ? 0x1 : 0x0; + if (bits_written) { + // If we are here the bits represented belong in the fractional + // part of the float, and we have to adjust the exponent accordingly. + fraction = static_cast( + fraction | + static_cast( + write_bit << (HF::top_bit_left_shift - fraction_index++))); + exponent = static_cast(exponent + 1); + } + bits_written |= write_bit != 0; + } + } else { + // We have not found our exponent yet, so we have to fail. + is.setstate(std::ios::failbit); + return is; + } + is.get(); + next_char = is.peek(); + } + bits_written = false; + while (seen_dot && !seen_p) { + // Handle only fractional parts now. + if (next_char == 'p') { + seen_p = true; + } else if (::isxdigit(next_char)) { + int number = get_nibble_from_character(next_char); + for (int i = 0; i < 4; ++i, number <<= 1) { + uint_type write_bit = (number & 0x8) ? 0x01 : 0x00; + bits_written |= write_bit != 0; + if (is_denorm && !bits_written) { + // Handle modifying the exponent here this way we can handle + // an arbitrary number of hex values without overflowing our + // integer. + exponent = static_cast(exponent - 1); + } else { + fraction = static_cast( + fraction | + static_cast( + write_bit << (HF::top_bit_left_shift - fraction_index++))); + } + } + } else { + // We still have not found our 'p' exponent yet, so this is not a valid + // hex-float. + is.setstate(std::ios::failbit); + return is; + } + is.get(); + next_char = is.peek(); + } + + bool seen_sign = false; + int8_t exponent_sign = 1; + int_type written_exponent = 0; + while (true) { + if ((next_char == '-' || next_char == '+')) { + if (seen_sign) { + is.setstate(std::ios::failbit); + return is; + } + seen_sign = true; + exponent_sign = (next_char == '-') ? -1 : 1; + } else if (::isdigit(next_char)) { + // Hex-floats express their exponent as decimal. + written_exponent = static_cast(written_exponent * 10); + written_exponent = + static_cast(written_exponent + (next_char - '0')); + } else { + break; + } + is.get(); + next_char = is.peek(); + } + + written_exponent = static_cast(written_exponent * exponent_sign); + exponent = static_cast(exponent + written_exponent); + + bool is_zero = is_denorm && (fraction == 0); + if (is_denorm && !is_zero) { + fraction = static_cast(fraction << 1); + exponent = static_cast(exponent - 1); + } else if (is_zero) { + exponent = 0; + } + + if (exponent <= 0 && !is_zero) { + fraction = static_cast(fraction >> 1); + fraction |= static_cast(1) << HF::top_bit_left_shift; + } + + fraction = (fraction >> HF::fraction_right_shift) & HF::fraction_encode_mask; + + const int_type max_exponent = + SetBits::get; + + // Handle actual denorm numbers + while (exponent < 0 && !is_zero) { + fraction = static_cast(fraction >> 1); + exponent = static_cast(exponent + 1); + + fraction &= HF::fraction_encode_mask; + if (fraction == 0) { + // We have underflowed our fraction. We should clamp to zero. + is_zero = true; + exponent = 0; + } + } + + // We have overflowed so we should be inf/-inf. + if (exponent > max_exponent) { + exponent = max_exponent; + fraction = 0; + } + + uint_type output_bits = static_cast( + static_cast(negate_value ? 1 : 0) << HF::top_bit_left_shift); + output_bits |= fraction; + + uint_type shifted_exponent = static_cast( + static_cast(exponent << HF::exponent_left_shift) & + HF::exponent_mask); + output_bits |= shifted_exponent; + + T output_float = spvutils::BitwiseCast(output_bits); + value.set_value(output_float); + + return is; +} + +// Writes a FloatProxy value to a stream. +// Zero and normal numbers are printed in the usual notation, but with +// enough digits to fully reproduce the value. Other values (subnormal, +// NaN, and infinity) are printed as a hex float. +template +std::ostream& operator<<(std::ostream& os, const FloatProxy& value) { + auto float_val = value.getAsFloat(); + switch (std::fpclassify(float_val)) { + case FP_ZERO: + case FP_NORMAL: { + auto saved_precision = os.precision(); + os.precision(std::numeric_limits::digits10); + os << float_val; + os.precision(saved_precision); + } break; + default: + os << HexFloat>(value); + break; + } + return os; +} + +template <> +inline std::ostream& operator<<(std::ostream& os, + const FloatProxy& value) { + os << HexFloat>(value); + return os; +} +} + +#endif // LIBSPIRV_UTIL_HEX_FLOAT_H_ diff --git a/mac/include/glslang/SPIRV/spirv.hpp b/mac/include/glslang/SPIRV/spirv.hpp new file mode 100644 index 00000000..dae36cf2 --- /dev/null +++ b/mac/include/glslang/SPIRV/spirv.hpp @@ -0,0 +1,2114 @@ +// Copyright (c) 2014-2020 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and/or associated documentation files (the "Materials"), +// to deal in the Materials without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Materials, and to permit persons to whom the +// Materials are furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +// IN THE MATERIALS. + +// This header is automatically generated by the same tool that creates +// the Binary Section of the SPIR-V specification. + +// Enumeration tokens for SPIR-V, in various styles: +// C, C++, C++11, JSON, Lua, Python, C#, D +// +// - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL +// - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL +// - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL +// - Lua will use tables, e.g.: spv.SourceLanguage.GLSL +// - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] +// - C# will use enum classes in the Specification class located in the "Spv" namespace, +// e.g.: Spv.Specification.SourceLanguage.GLSL +// - D will have tokens under the "spv" module, e.g: spv.SourceLanguage.GLSL +// +// Some tokens act like mask values, which can be OR'd together, +// while others are mutually exclusive. The mask-like ones have +// "Mask" in their name, and a parallel enum that has the shift +// amount (1 << x) for each corresponding enumerant. + +#ifndef spirv_HPP +#define spirv_HPP + +namespace spv { + +typedef unsigned int Id; + +#define SPV_VERSION 0x10500 +#define SPV_REVISION 3 + +static const unsigned int MagicNumber = 0x07230203; +static const unsigned int Version = 0x00010500; +static const unsigned int Revision = 3; +static const unsigned int OpCodeMask = 0xffff; +static const unsigned int WordCountShift = 16; + +enum SourceLanguage { + SourceLanguageUnknown = 0, + SourceLanguageESSL = 1, + SourceLanguageGLSL = 2, + SourceLanguageOpenCL_C = 3, + SourceLanguageOpenCL_CPP = 4, + SourceLanguageHLSL = 5, + SourceLanguageMax = 0x7fffffff, +}; + +enum ExecutionModel { + ExecutionModelVertex = 0, + ExecutionModelTessellationControl = 1, + ExecutionModelTessellationEvaluation = 2, + ExecutionModelGeometry = 3, + ExecutionModelFragment = 4, + ExecutionModelGLCompute = 5, + ExecutionModelKernel = 6, + ExecutionModelTaskNV = 5267, + ExecutionModelMeshNV = 5268, + ExecutionModelRayGenerationKHR = 5313, + ExecutionModelRayGenerationNV = 5313, + ExecutionModelIntersectionKHR = 5314, + ExecutionModelIntersectionNV = 5314, + ExecutionModelAnyHitKHR = 5315, + ExecutionModelAnyHitNV = 5315, + ExecutionModelClosestHitKHR = 5316, + ExecutionModelClosestHitNV = 5316, + ExecutionModelMissKHR = 5317, + ExecutionModelMissNV = 5317, + ExecutionModelCallableKHR = 5318, + ExecutionModelCallableNV = 5318, + ExecutionModelMax = 0x7fffffff, +}; + +enum AddressingModel { + AddressingModelLogical = 0, + AddressingModelPhysical32 = 1, + AddressingModelPhysical64 = 2, + AddressingModelPhysicalStorageBuffer64 = 5348, + AddressingModelPhysicalStorageBuffer64EXT = 5348, + AddressingModelMax = 0x7fffffff, +}; + +enum MemoryModel { + MemoryModelSimple = 0, + MemoryModelGLSL450 = 1, + MemoryModelOpenCL = 2, + MemoryModelVulkan = 3, + MemoryModelVulkanKHR = 3, + MemoryModelMax = 0x7fffffff, +}; + +enum ExecutionMode { + ExecutionModeInvocations = 0, + ExecutionModeSpacingEqual = 1, + ExecutionModeSpacingFractionalEven = 2, + ExecutionModeSpacingFractionalOdd = 3, + ExecutionModeVertexOrderCw = 4, + ExecutionModeVertexOrderCcw = 5, + ExecutionModePixelCenterInteger = 6, + ExecutionModeOriginUpperLeft = 7, + ExecutionModeOriginLowerLeft = 8, + ExecutionModeEarlyFragmentTests = 9, + ExecutionModePointMode = 10, + ExecutionModeXfb = 11, + ExecutionModeDepthReplacing = 12, + ExecutionModeDepthGreater = 14, + ExecutionModeDepthLess = 15, + ExecutionModeDepthUnchanged = 16, + ExecutionModeLocalSize = 17, + ExecutionModeLocalSizeHint = 18, + ExecutionModeInputPoints = 19, + ExecutionModeInputLines = 20, + ExecutionModeInputLinesAdjacency = 21, + ExecutionModeTriangles = 22, + ExecutionModeInputTrianglesAdjacency = 23, + ExecutionModeQuads = 24, + ExecutionModeIsolines = 25, + ExecutionModeOutputVertices = 26, + ExecutionModeOutputPoints = 27, + ExecutionModeOutputLineStrip = 28, + ExecutionModeOutputTriangleStrip = 29, + ExecutionModeVecTypeHint = 30, + ExecutionModeContractionOff = 31, + ExecutionModeInitializer = 33, + ExecutionModeFinalizer = 34, + ExecutionModeSubgroupSize = 35, + ExecutionModeSubgroupsPerWorkgroup = 36, + ExecutionModeSubgroupsPerWorkgroupId = 37, + ExecutionModeLocalSizeId = 38, + ExecutionModeLocalSizeHintId = 39, + ExecutionModePostDepthCoverage = 4446, + ExecutionModeDenormPreserve = 4459, + ExecutionModeDenormFlushToZero = 4460, + ExecutionModeSignedZeroInfNanPreserve = 4461, + ExecutionModeRoundingModeRTE = 4462, + ExecutionModeRoundingModeRTZ = 4463, + ExecutionModeStencilRefReplacingEXT = 5027, + ExecutionModeOutputLinesNV = 5269, + ExecutionModeOutputPrimitivesNV = 5270, + ExecutionModeDerivativeGroupQuadsNV = 5289, + ExecutionModeDerivativeGroupLinearNV = 5290, + ExecutionModeOutputTrianglesNV = 5298, + ExecutionModePixelInterlockOrderedEXT = 5366, + ExecutionModePixelInterlockUnorderedEXT = 5367, + ExecutionModeSampleInterlockOrderedEXT = 5368, + ExecutionModeSampleInterlockUnorderedEXT = 5369, + ExecutionModeShadingRateInterlockOrderedEXT = 5370, + ExecutionModeShadingRateInterlockUnorderedEXT = 5371, + ExecutionModeMax = 0x7fffffff, +}; + +enum StorageClass { + StorageClassUniformConstant = 0, + StorageClassInput = 1, + StorageClassUniform = 2, + StorageClassOutput = 3, + StorageClassWorkgroup = 4, + StorageClassCrossWorkgroup = 5, + StorageClassPrivate = 6, + StorageClassFunction = 7, + StorageClassGeneric = 8, + StorageClassPushConstant = 9, + StorageClassAtomicCounter = 10, + StorageClassImage = 11, + StorageClassStorageBuffer = 12, + StorageClassCallableDataKHR = 5328, + StorageClassCallableDataNV = 5328, + StorageClassIncomingCallableDataKHR = 5329, + StorageClassIncomingCallableDataNV = 5329, + StorageClassRayPayloadKHR = 5338, + StorageClassRayPayloadNV = 5338, + StorageClassHitAttributeKHR = 5339, + StorageClassHitAttributeNV = 5339, + StorageClassIncomingRayPayloadKHR = 5342, + StorageClassIncomingRayPayloadNV = 5342, + StorageClassShaderRecordBufferKHR = 5343, + StorageClassShaderRecordBufferNV = 5343, + StorageClassPhysicalStorageBuffer = 5349, + StorageClassPhysicalStorageBufferEXT = 5349, + StorageClassMax = 0x7fffffff, +}; + +enum Dim { + Dim1D = 0, + Dim2D = 1, + Dim3D = 2, + DimCube = 3, + DimRect = 4, + DimBuffer = 5, + DimSubpassData = 6, + DimMax = 0x7fffffff, +}; + +enum SamplerAddressingMode { + SamplerAddressingModeNone = 0, + SamplerAddressingModeClampToEdge = 1, + SamplerAddressingModeClamp = 2, + SamplerAddressingModeRepeat = 3, + SamplerAddressingModeRepeatMirrored = 4, + SamplerAddressingModeMax = 0x7fffffff, +}; + +enum SamplerFilterMode { + SamplerFilterModeNearest = 0, + SamplerFilterModeLinear = 1, + SamplerFilterModeMax = 0x7fffffff, +}; + +enum ImageFormat { + ImageFormatUnknown = 0, + ImageFormatRgba32f = 1, + ImageFormatRgba16f = 2, + ImageFormatR32f = 3, + ImageFormatRgba8 = 4, + ImageFormatRgba8Snorm = 5, + ImageFormatRg32f = 6, + ImageFormatRg16f = 7, + ImageFormatR11fG11fB10f = 8, + ImageFormatR16f = 9, + ImageFormatRgba16 = 10, + ImageFormatRgb10A2 = 11, + ImageFormatRg16 = 12, + ImageFormatRg8 = 13, + ImageFormatR16 = 14, + ImageFormatR8 = 15, + ImageFormatRgba16Snorm = 16, + ImageFormatRg16Snorm = 17, + ImageFormatRg8Snorm = 18, + ImageFormatR16Snorm = 19, + ImageFormatR8Snorm = 20, + ImageFormatRgba32i = 21, + ImageFormatRgba16i = 22, + ImageFormatRgba8i = 23, + ImageFormatR32i = 24, + ImageFormatRg32i = 25, + ImageFormatRg16i = 26, + ImageFormatRg8i = 27, + ImageFormatR16i = 28, + ImageFormatR8i = 29, + ImageFormatRgba32ui = 30, + ImageFormatRgba16ui = 31, + ImageFormatRgba8ui = 32, + ImageFormatR32ui = 33, + ImageFormatRgb10a2ui = 34, + ImageFormatRg32ui = 35, + ImageFormatRg16ui = 36, + ImageFormatRg8ui = 37, + ImageFormatR16ui = 38, + ImageFormatR8ui = 39, + ImageFormatMax = 0x7fffffff, +}; + +enum ImageChannelOrder { + ImageChannelOrderR = 0, + ImageChannelOrderA = 1, + ImageChannelOrderRG = 2, + ImageChannelOrderRA = 3, + ImageChannelOrderRGB = 4, + ImageChannelOrderRGBA = 5, + ImageChannelOrderBGRA = 6, + ImageChannelOrderARGB = 7, + ImageChannelOrderIntensity = 8, + ImageChannelOrderLuminance = 9, + ImageChannelOrderRx = 10, + ImageChannelOrderRGx = 11, + ImageChannelOrderRGBx = 12, + ImageChannelOrderDepth = 13, + ImageChannelOrderDepthStencil = 14, + ImageChannelOrdersRGB = 15, + ImageChannelOrdersRGBx = 16, + ImageChannelOrdersRGBA = 17, + ImageChannelOrdersBGRA = 18, + ImageChannelOrderABGR = 19, + ImageChannelOrderMax = 0x7fffffff, +}; + +enum ImageChannelDataType { + ImageChannelDataTypeSnormInt8 = 0, + ImageChannelDataTypeSnormInt16 = 1, + ImageChannelDataTypeUnormInt8 = 2, + ImageChannelDataTypeUnormInt16 = 3, + ImageChannelDataTypeUnormShort565 = 4, + ImageChannelDataTypeUnormShort555 = 5, + ImageChannelDataTypeUnormInt101010 = 6, + ImageChannelDataTypeSignedInt8 = 7, + ImageChannelDataTypeSignedInt16 = 8, + ImageChannelDataTypeSignedInt32 = 9, + ImageChannelDataTypeUnsignedInt8 = 10, + ImageChannelDataTypeUnsignedInt16 = 11, + ImageChannelDataTypeUnsignedInt32 = 12, + ImageChannelDataTypeHalfFloat = 13, + ImageChannelDataTypeFloat = 14, + ImageChannelDataTypeUnormInt24 = 15, + ImageChannelDataTypeUnormInt101010_2 = 16, + ImageChannelDataTypeMax = 0x7fffffff, +}; + +enum ImageOperandsShift { + ImageOperandsBiasShift = 0, + ImageOperandsLodShift = 1, + ImageOperandsGradShift = 2, + ImageOperandsConstOffsetShift = 3, + ImageOperandsOffsetShift = 4, + ImageOperandsConstOffsetsShift = 5, + ImageOperandsSampleShift = 6, + ImageOperandsMinLodShift = 7, + ImageOperandsMakeTexelAvailableShift = 8, + ImageOperandsMakeTexelAvailableKHRShift = 8, + ImageOperandsMakeTexelVisibleShift = 9, + ImageOperandsMakeTexelVisibleKHRShift = 9, + ImageOperandsNonPrivateTexelShift = 10, + ImageOperandsNonPrivateTexelKHRShift = 10, + ImageOperandsVolatileTexelShift = 11, + ImageOperandsVolatileTexelKHRShift = 11, + ImageOperandsSignExtendShift = 12, + ImageOperandsZeroExtendShift = 13, + ImageOperandsMax = 0x7fffffff, +}; + +enum ImageOperandsMask { + ImageOperandsMaskNone = 0, + ImageOperandsBiasMask = 0x00000001, + ImageOperandsLodMask = 0x00000002, + ImageOperandsGradMask = 0x00000004, + ImageOperandsConstOffsetMask = 0x00000008, + ImageOperandsOffsetMask = 0x00000010, + ImageOperandsConstOffsetsMask = 0x00000020, + ImageOperandsSampleMask = 0x00000040, + ImageOperandsMinLodMask = 0x00000080, + ImageOperandsMakeTexelAvailableMask = 0x00000100, + ImageOperandsMakeTexelAvailableKHRMask = 0x00000100, + ImageOperandsMakeTexelVisibleMask = 0x00000200, + ImageOperandsMakeTexelVisibleKHRMask = 0x00000200, + ImageOperandsNonPrivateTexelMask = 0x00000400, + ImageOperandsNonPrivateTexelKHRMask = 0x00000400, + ImageOperandsVolatileTexelMask = 0x00000800, + ImageOperandsVolatileTexelKHRMask = 0x00000800, + ImageOperandsSignExtendMask = 0x00001000, + ImageOperandsZeroExtendMask = 0x00002000, +}; + +enum FPFastMathModeShift { + FPFastMathModeNotNaNShift = 0, + FPFastMathModeNotInfShift = 1, + FPFastMathModeNSZShift = 2, + FPFastMathModeAllowRecipShift = 3, + FPFastMathModeFastShift = 4, + FPFastMathModeMax = 0x7fffffff, +}; + +enum FPFastMathModeMask { + FPFastMathModeMaskNone = 0, + FPFastMathModeNotNaNMask = 0x00000001, + FPFastMathModeNotInfMask = 0x00000002, + FPFastMathModeNSZMask = 0x00000004, + FPFastMathModeAllowRecipMask = 0x00000008, + FPFastMathModeFastMask = 0x00000010, +}; + +enum FPRoundingMode { + FPRoundingModeRTE = 0, + FPRoundingModeRTZ = 1, + FPRoundingModeRTP = 2, + FPRoundingModeRTN = 3, + FPRoundingModeMax = 0x7fffffff, +}; + +enum LinkageType { + LinkageTypeExport = 0, + LinkageTypeImport = 1, + LinkageTypeMax = 0x7fffffff, +}; + +enum AccessQualifier { + AccessQualifierReadOnly = 0, + AccessQualifierWriteOnly = 1, + AccessQualifierReadWrite = 2, + AccessQualifierMax = 0x7fffffff, +}; + +enum FunctionParameterAttribute { + FunctionParameterAttributeZext = 0, + FunctionParameterAttributeSext = 1, + FunctionParameterAttributeByVal = 2, + FunctionParameterAttributeSret = 3, + FunctionParameterAttributeNoAlias = 4, + FunctionParameterAttributeNoCapture = 5, + FunctionParameterAttributeNoWrite = 6, + FunctionParameterAttributeNoReadWrite = 7, + FunctionParameterAttributeMax = 0x7fffffff, +}; + +enum Decoration { + DecorationRelaxedPrecision = 0, + DecorationSpecId = 1, + DecorationBlock = 2, + DecorationBufferBlock = 3, + DecorationRowMajor = 4, + DecorationColMajor = 5, + DecorationArrayStride = 6, + DecorationMatrixStride = 7, + DecorationGLSLShared = 8, + DecorationGLSLPacked = 9, + DecorationCPacked = 10, + DecorationBuiltIn = 11, + DecorationNoPerspective = 13, + DecorationFlat = 14, + DecorationPatch = 15, + DecorationCentroid = 16, + DecorationSample = 17, + DecorationInvariant = 18, + DecorationRestrict = 19, + DecorationAliased = 20, + DecorationVolatile = 21, + DecorationConstant = 22, + DecorationCoherent = 23, + DecorationNonWritable = 24, + DecorationNonReadable = 25, + DecorationUniform = 26, + DecorationUniformId = 27, + DecorationSaturatedConversion = 28, + DecorationStream = 29, + DecorationLocation = 30, + DecorationComponent = 31, + DecorationIndex = 32, + DecorationBinding = 33, + DecorationDescriptorSet = 34, + DecorationOffset = 35, + DecorationXfbBuffer = 36, + DecorationXfbStride = 37, + DecorationFuncParamAttr = 38, + DecorationFPRoundingMode = 39, + DecorationFPFastMathMode = 40, + DecorationLinkageAttributes = 41, + DecorationNoContraction = 42, + DecorationInputAttachmentIndex = 43, + DecorationAlignment = 44, + DecorationMaxByteOffset = 45, + DecorationAlignmentId = 46, + DecorationMaxByteOffsetId = 47, + DecorationNoSignedWrap = 4469, + DecorationNoUnsignedWrap = 4470, + DecorationExplicitInterpAMD = 4999, + DecorationOverrideCoverageNV = 5248, + DecorationPassthroughNV = 5250, + DecorationViewportRelativeNV = 5252, + DecorationSecondaryViewportRelativeNV = 5256, + DecorationPerPrimitiveNV = 5271, + DecorationPerViewNV = 5272, + DecorationPerTaskNV = 5273, + DecorationPerVertexNV = 5285, + DecorationNonUniform = 5300, + DecorationNonUniformEXT = 5300, + DecorationRestrictPointer = 5355, + DecorationRestrictPointerEXT = 5355, + DecorationAliasedPointer = 5356, + DecorationAliasedPointerEXT = 5356, + DecorationCounterBuffer = 5634, + DecorationHlslCounterBufferGOOGLE = 5634, + DecorationHlslSemanticGOOGLE = 5635, + DecorationUserSemantic = 5635, + DecorationUserTypeGOOGLE = 5636, + DecorationMax = 0x7fffffff, +}; + +enum BuiltIn { + BuiltInPosition = 0, + BuiltInPointSize = 1, + BuiltInClipDistance = 3, + BuiltInCullDistance = 4, + BuiltInVertexId = 5, + BuiltInInstanceId = 6, + BuiltInPrimitiveId = 7, + BuiltInInvocationId = 8, + BuiltInLayer = 9, + BuiltInViewportIndex = 10, + BuiltInTessLevelOuter = 11, + BuiltInTessLevelInner = 12, + BuiltInTessCoord = 13, + BuiltInPatchVertices = 14, + BuiltInFragCoord = 15, + BuiltInPointCoord = 16, + BuiltInFrontFacing = 17, + BuiltInSampleId = 18, + BuiltInSamplePosition = 19, + BuiltInSampleMask = 20, + BuiltInFragDepth = 22, + BuiltInHelperInvocation = 23, + BuiltInNumWorkgroups = 24, + BuiltInWorkgroupSize = 25, + BuiltInWorkgroupId = 26, + BuiltInLocalInvocationId = 27, + BuiltInGlobalInvocationId = 28, + BuiltInLocalInvocationIndex = 29, + BuiltInWorkDim = 30, + BuiltInGlobalSize = 31, + BuiltInEnqueuedWorkgroupSize = 32, + BuiltInGlobalOffset = 33, + BuiltInGlobalLinearId = 34, + BuiltInSubgroupSize = 36, + BuiltInSubgroupMaxSize = 37, + BuiltInNumSubgroups = 38, + BuiltInNumEnqueuedSubgroups = 39, + BuiltInSubgroupId = 40, + BuiltInSubgroupLocalInvocationId = 41, + BuiltInVertexIndex = 42, + BuiltInInstanceIndex = 43, + BuiltInSubgroupEqMask = 4416, + BuiltInSubgroupEqMaskKHR = 4416, + BuiltInSubgroupGeMask = 4417, + BuiltInSubgroupGeMaskKHR = 4417, + BuiltInSubgroupGtMask = 4418, + BuiltInSubgroupGtMaskKHR = 4418, + BuiltInSubgroupLeMask = 4419, + BuiltInSubgroupLeMaskKHR = 4419, + BuiltInSubgroupLtMask = 4420, + BuiltInSubgroupLtMaskKHR = 4420, + BuiltInBaseVertex = 4424, + BuiltInBaseInstance = 4425, + BuiltInDrawIndex = 4426, + BuiltInDeviceIndex = 4438, + BuiltInViewIndex = 4440, + BuiltInBaryCoordNoPerspAMD = 4992, + BuiltInBaryCoordNoPerspCentroidAMD = 4993, + BuiltInBaryCoordNoPerspSampleAMD = 4994, + BuiltInBaryCoordSmoothAMD = 4995, + BuiltInBaryCoordSmoothCentroidAMD = 4996, + BuiltInBaryCoordSmoothSampleAMD = 4997, + BuiltInBaryCoordPullModelAMD = 4998, + BuiltInFragStencilRefEXT = 5014, + BuiltInViewportMaskNV = 5253, + BuiltInSecondaryPositionNV = 5257, + BuiltInSecondaryViewportMaskNV = 5258, + BuiltInPositionPerViewNV = 5261, + BuiltInViewportMaskPerViewNV = 5262, + BuiltInFullyCoveredEXT = 5264, + BuiltInTaskCountNV = 5274, + BuiltInPrimitiveCountNV = 5275, + BuiltInPrimitiveIndicesNV = 5276, + BuiltInClipDistancePerViewNV = 5277, + BuiltInCullDistancePerViewNV = 5278, + BuiltInLayerPerViewNV = 5279, + BuiltInMeshViewCountNV = 5280, + BuiltInMeshViewIndicesNV = 5281, + BuiltInBaryCoordNV = 5286, + BuiltInBaryCoordNoPerspNV = 5287, + BuiltInFragSizeEXT = 5292, + BuiltInFragmentSizeNV = 5292, + BuiltInFragInvocationCountEXT = 5293, + BuiltInInvocationsPerPixelNV = 5293, + BuiltInLaunchIdKHR = 5319, + BuiltInLaunchIdNV = 5319, + BuiltInLaunchSizeKHR = 5320, + BuiltInLaunchSizeNV = 5320, + BuiltInWorldRayOriginKHR = 5321, + BuiltInWorldRayOriginNV = 5321, + BuiltInWorldRayDirectionKHR = 5322, + BuiltInWorldRayDirectionNV = 5322, + BuiltInObjectRayOriginKHR = 5323, + BuiltInObjectRayOriginNV = 5323, + BuiltInObjectRayDirectionKHR = 5324, + BuiltInObjectRayDirectionNV = 5324, + BuiltInRayTminKHR = 5325, + BuiltInRayTminNV = 5325, + BuiltInRayTmaxKHR = 5326, + BuiltInRayTmaxNV = 5326, + BuiltInInstanceCustomIndexKHR = 5327, + BuiltInInstanceCustomIndexNV = 5327, + BuiltInObjectToWorldKHR = 5330, + BuiltInObjectToWorldNV = 5330, + BuiltInWorldToObjectKHR = 5331, + BuiltInWorldToObjectNV = 5331, + BuiltInHitTKHR = 5332, + BuiltInHitTNV = 5332, + BuiltInHitKindKHR = 5333, + BuiltInHitKindNV = 5333, + BuiltInIncomingRayFlagsKHR = 5351, + BuiltInIncomingRayFlagsNV = 5351, + BuiltInRayGeometryIndexKHR = 5352, + BuiltInWarpsPerSMNV = 5374, + BuiltInSMCountNV = 5375, + BuiltInWarpIDNV = 5376, + BuiltInSMIDNV = 5377, + BuiltInMax = 0x7fffffff, +}; + +enum SelectionControlShift { + SelectionControlFlattenShift = 0, + SelectionControlDontFlattenShift = 1, + SelectionControlMax = 0x7fffffff, +}; + +enum SelectionControlMask { + SelectionControlMaskNone = 0, + SelectionControlFlattenMask = 0x00000001, + SelectionControlDontFlattenMask = 0x00000002, +}; + +enum LoopControlShift { + LoopControlUnrollShift = 0, + LoopControlDontUnrollShift = 1, + LoopControlDependencyInfiniteShift = 2, + LoopControlDependencyLengthShift = 3, + LoopControlMinIterationsShift = 4, + LoopControlMaxIterationsShift = 5, + LoopControlIterationMultipleShift = 6, + LoopControlPeelCountShift = 7, + LoopControlPartialCountShift = 8, + LoopControlMax = 0x7fffffff, +}; + +enum LoopControlMask { + LoopControlMaskNone = 0, + LoopControlUnrollMask = 0x00000001, + LoopControlDontUnrollMask = 0x00000002, + LoopControlDependencyInfiniteMask = 0x00000004, + LoopControlDependencyLengthMask = 0x00000008, + LoopControlMinIterationsMask = 0x00000010, + LoopControlMaxIterationsMask = 0x00000020, + LoopControlIterationMultipleMask = 0x00000040, + LoopControlPeelCountMask = 0x00000080, + LoopControlPartialCountMask = 0x00000100, +}; + +enum FunctionControlShift { + FunctionControlInlineShift = 0, + FunctionControlDontInlineShift = 1, + FunctionControlPureShift = 2, + FunctionControlConstShift = 3, + FunctionControlMax = 0x7fffffff, +}; + +enum FunctionControlMask { + FunctionControlMaskNone = 0, + FunctionControlInlineMask = 0x00000001, + FunctionControlDontInlineMask = 0x00000002, + FunctionControlPureMask = 0x00000004, + FunctionControlConstMask = 0x00000008, +}; + +enum MemorySemanticsShift { + MemorySemanticsAcquireShift = 1, + MemorySemanticsReleaseShift = 2, + MemorySemanticsAcquireReleaseShift = 3, + MemorySemanticsSequentiallyConsistentShift = 4, + MemorySemanticsUniformMemoryShift = 6, + MemorySemanticsSubgroupMemoryShift = 7, + MemorySemanticsWorkgroupMemoryShift = 8, + MemorySemanticsCrossWorkgroupMemoryShift = 9, + MemorySemanticsAtomicCounterMemoryShift = 10, + MemorySemanticsImageMemoryShift = 11, + MemorySemanticsOutputMemoryShift = 12, + MemorySemanticsOutputMemoryKHRShift = 12, + MemorySemanticsMakeAvailableShift = 13, + MemorySemanticsMakeAvailableKHRShift = 13, + MemorySemanticsMakeVisibleShift = 14, + MemorySemanticsMakeVisibleKHRShift = 14, + MemorySemanticsVolatileShift = 15, + MemorySemanticsMax = 0x7fffffff, +}; + +enum MemorySemanticsMask { + MemorySemanticsMaskNone = 0, + MemorySemanticsAcquireMask = 0x00000002, + MemorySemanticsReleaseMask = 0x00000004, + MemorySemanticsAcquireReleaseMask = 0x00000008, + MemorySemanticsSequentiallyConsistentMask = 0x00000010, + MemorySemanticsUniformMemoryMask = 0x00000040, + MemorySemanticsSubgroupMemoryMask = 0x00000080, + MemorySemanticsWorkgroupMemoryMask = 0x00000100, + MemorySemanticsCrossWorkgroupMemoryMask = 0x00000200, + MemorySemanticsAtomicCounterMemoryMask = 0x00000400, + MemorySemanticsImageMemoryMask = 0x00000800, + MemorySemanticsOutputMemoryMask = 0x00001000, + MemorySemanticsOutputMemoryKHRMask = 0x00001000, + MemorySemanticsMakeAvailableMask = 0x00002000, + MemorySemanticsMakeAvailableKHRMask = 0x00002000, + MemorySemanticsMakeVisibleMask = 0x00004000, + MemorySemanticsMakeVisibleKHRMask = 0x00004000, + MemorySemanticsVolatileMask = 0x00008000, +}; + +enum MemoryAccessShift { + MemoryAccessVolatileShift = 0, + MemoryAccessAlignedShift = 1, + MemoryAccessNontemporalShift = 2, + MemoryAccessMakePointerAvailableShift = 3, + MemoryAccessMakePointerAvailableKHRShift = 3, + MemoryAccessMakePointerVisibleShift = 4, + MemoryAccessMakePointerVisibleKHRShift = 4, + MemoryAccessNonPrivatePointerShift = 5, + MemoryAccessNonPrivatePointerKHRShift = 5, + MemoryAccessMax = 0x7fffffff, +}; + +enum MemoryAccessMask { + MemoryAccessMaskNone = 0, + MemoryAccessVolatileMask = 0x00000001, + MemoryAccessAlignedMask = 0x00000002, + MemoryAccessNontemporalMask = 0x00000004, + MemoryAccessMakePointerAvailableMask = 0x00000008, + MemoryAccessMakePointerAvailableKHRMask = 0x00000008, + MemoryAccessMakePointerVisibleMask = 0x00000010, + MemoryAccessMakePointerVisibleKHRMask = 0x00000010, + MemoryAccessNonPrivatePointerMask = 0x00000020, + MemoryAccessNonPrivatePointerKHRMask = 0x00000020, +}; + +enum Scope { + ScopeCrossDevice = 0, + ScopeDevice = 1, + ScopeWorkgroup = 2, + ScopeSubgroup = 3, + ScopeInvocation = 4, + ScopeQueueFamily = 5, + ScopeQueueFamilyKHR = 5, + ScopeShaderCallKHR = 6, + ScopeMax = 0x7fffffff, +}; + +enum GroupOperation { + GroupOperationReduce = 0, + GroupOperationInclusiveScan = 1, + GroupOperationExclusiveScan = 2, + GroupOperationClusteredReduce = 3, + GroupOperationPartitionedReduceNV = 6, + GroupOperationPartitionedInclusiveScanNV = 7, + GroupOperationPartitionedExclusiveScanNV = 8, + GroupOperationMax = 0x7fffffff, +}; + +enum KernelEnqueueFlags { + KernelEnqueueFlagsNoWait = 0, + KernelEnqueueFlagsWaitKernel = 1, + KernelEnqueueFlagsWaitWorkGroup = 2, + KernelEnqueueFlagsMax = 0x7fffffff, +}; + +enum KernelProfilingInfoShift { + KernelProfilingInfoCmdExecTimeShift = 0, + KernelProfilingInfoMax = 0x7fffffff, +}; + +enum KernelProfilingInfoMask { + KernelProfilingInfoMaskNone = 0, + KernelProfilingInfoCmdExecTimeMask = 0x00000001, +}; + +enum Capability { + CapabilityMatrix = 0, + CapabilityShader = 1, + CapabilityGeometry = 2, + CapabilityTessellation = 3, + CapabilityAddresses = 4, + CapabilityLinkage = 5, + CapabilityKernel = 6, + CapabilityVector16 = 7, + CapabilityFloat16Buffer = 8, + CapabilityFloat16 = 9, + CapabilityFloat64 = 10, + CapabilityInt64 = 11, + CapabilityInt64Atomics = 12, + CapabilityImageBasic = 13, + CapabilityImageReadWrite = 14, + CapabilityImageMipmap = 15, + CapabilityPipes = 17, + CapabilityGroups = 18, + CapabilityDeviceEnqueue = 19, + CapabilityLiteralSampler = 20, + CapabilityAtomicStorage = 21, + CapabilityInt16 = 22, + CapabilityTessellationPointSize = 23, + CapabilityGeometryPointSize = 24, + CapabilityImageGatherExtended = 25, + CapabilityStorageImageMultisample = 27, + CapabilityUniformBufferArrayDynamicIndexing = 28, + CapabilitySampledImageArrayDynamicIndexing = 29, + CapabilityStorageBufferArrayDynamicIndexing = 30, + CapabilityStorageImageArrayDynamicIndexing = 31, + CapabilityClipDistance = 32, + CapabilityCullDistance = 33, + CapabilityImageCubeArray = 34, + CapabilitySampleRateShading = 35, + CapabilityImageRect = 36, + CapabilitySampledRect = 37, + CapabilityGenericPointer = 38, + CapabilityInt8 = 39, + CapabilityInputAttachment = 40, + CapabilitySparseResidency = 41, + CapabilityMinLod = 42, + CapabilitySampled1D = 43, + CapabilityImage1D = 44, + CapabilitySampledCubeArray = 45, + CapabilitySampledBuffer = 46, + CapabilityImageBuffer = 47, + CapabilityImageMSArray = 48, + CapabilityStorageImageExtendedFormats = 49, + CapabilityImageQuery = 50, + CapabilityDerivativeControl = 51, + CapabilityInterpolationFunction = 52, + CapabilityTransformFeedback = 53, + CapabilityGeometryStreams = 54, + CapabilityStorageImageReadWithoutFormat = 55, + CapabilityStorageImageWriteWithoutFormat = 56, + CapabilityMultiViewport = 57, + CapabilitySubgroupDispatch = 58, + CapabilityNamedBarrier = 59, + CapabilityPipeStorage = 60, + CapabilityGroupNonUniform = 61, + CapabilityGroupNonUniformVote = 62, + CapabilityGroupNonUniformArithmetic = 63, + CapabilityGroupNonUniformBallot = 64, + CapabilityGroupNonUniformShuffle = 65, + CapabilityGroupNonUniformShuffleRelative = 66, + CapabilityGroupNonUniformClustered = 67, + CapabilityGroupNonUniformQuad = 68, + CapabilityShaderLayer = 69, + CapabilityShaderViewportIndex = 70, + CapabilitySubgroupBallotKHR = 4423, + CapabilityDrawParameters = 4427, + CapabilitySubgroupVoteKHR = 4431, + CapabilityStorageBuffer16BitAccess = 4433, + CapabilityStorageUniformBufferBlock16 = 4433, + CapabilityStorageUniform16 = 4434, + CapabilityUniformAndStorageBuffer16BitAccess = 4434, + CapabilityStoragePushConstant16 = 4435, + CapabilityStorageInputOutput16 = 4436, + CapabilityDeviceGroup = 4437, + CapabilityMultiView = 4439, + CapabilityVariablePointersStorageBuffer = 4441, + CapabilityVariablePointers = 4442, + CapabilityAtomicStorageOps = 4445, + CapabilitySampleMaskPostDepthCoverage = 4447, + CapabilityStorageBuffer8BitAccess = 4448, + CapabilityUniformAndStorageBuffer8BitAccess = 4449, + CapabilityStoragePushConstant8 = 4450, + CapabilityDenormPreserve = 4464, + CapabilityDenormFlushToZero = 4465, + CapabilitySignedZeroInfNanPreserve = 4466, + CapabilityRoundingModeRTE = 4467, + CapabilityRoundingModeRTZ = 4468, + CapabilityRayQueryProvisionalKHR = 4471, + CapabilityRayTraversalPrimitiveCullingProvisionalKHR = 4478, + CapabilityFloat16ImageAMD = 5008, + CapabilityImageGatherBiasLodAMD = 5009, + CapabilityFragmentMaskAMD = 5010, + CapabilityStencilExportEXT = 5013, + CapabilityImageReadWriteLodAMD = 5015, + CapabilityShaderClockKHR = 5055, + CapabilitySampleMaskOverrideCoverageNV = 5249, + CapabilityGeometryShaderPassthroughNV = 5251, + CapabilityShaderViewportIndexLayerEXT = 5254, + CapabilityShaderViewportIndexLayerNV = 5254, + CapabilityShaderViewportMaskNV = 5255, + CapabilityShaderStereoViewNV = 5259, + CapabilityPerViewAttributesNV = 5260, + CapabilityFragmentFullyCoveredEXT = 5265, + CapabilityMeshShadingNV = 5266, + CapabilityImageFootprintNV = 5282, + CapabilityFragmentBarycentricNV = 5284, + CapabilityComputeDerivativeGroupQuadsNV = 5288, + CapabilityFragmentDensityEXT = 5291, + CapabilityShadingRateNV = 5291, + CapabilityGroupNonUniformPartitionedNV = 5297, + CapabilityShaderNonUniform = 5301, + CapabilityShaderNonUniformEXT = 5301, + CapabilityRuntimeDescriptorArray = 5302, + CapabilityRuntimeDescriptorArrayEXT = 5302, + CapabilityInputAttachmentArrayDynamicIndexing = 5303, + CapabilityInputAttachmentArrayDynamicIndexingEXT = 5303, + CapabilityUniformTexelBufferArrayDynamicIndexing = 5304, + CapabilityUniformTexelBufferArrayDynamicIndexingEXT = 5304, + CapabilityStorageTexelBufferArrayDynamicIndexing = 5305, + CapabilityStorageTexelBufferArrayDynamicIndexingEXT = 5305, + CapabilityUniformBufferArrayNonUniformIndexing = 5306, + CapabilityUniformBufferArrayNonUniformIndexingEXT = 5306, + CapabilitySampledImageArrayNonUniformIndexing = 5307, + CapabilitySampledImageArrayNonUniformIndexingEXT = 5307, + CapabilityStorageBufferArrayNonUniformIndexing = 5308, + CapabilityStorageBufferArrayNonUniformIndexingEXT = 5308, + CapabilityStorageImageArrayNonUniformIndexing = 5309, + CapabilityStorageImageArrayNonUniformIndexingEXT = 5309, + CapabilityInputAttachmentArrayNonUniformIndexing = 5310, + CapabilityInputAttachmentArrayNonUniformIndexingEXT = 5310, + CapabilityUniformTexelBufferArrayNonUniformIndexing = 5311, + CapabilityUniformTexelBufferArrayNonUniformIndexingEXT = 5311, + CapabilityStorageTexelBufferArrayNonUniformIndexing = 5312, + CapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312, + CapabilityRayTracingNV = 5340, + CapabilityVulkanMemoryModel = 5345, + CapabilityVulkanMemoryModelKHR = 5345, + CapabilityVulkanMemoryModelDeviceScope = 5346, + CapabilityVulkanMemoryModelDeviceScopeKHR = 5346, + CapabilityPhysicalStorageBufferAddresses = 5347, + CapabilityPhysicalStorageBufferAddressesEXT = 5347, + CapabilityComputeDerivativeGroupLinearNV = 5350, + CapabilityRayTracingProvisionalKHR = 5353, + CapabilityCooperativeMatrixNV = 5357, + CapabilityFragmentShaderSampleInterlockEXT = 5363, + CapabilityFragmentShaderShadingRateInterlockEXT = 5372, + CapabilityShaderSMBuiltinsNV = 5373, + CapabilityFragmentShaderPixelInterlockEXT = 5378, + CapabilityDemoteToHelperInvocationEXT = 5379, + CapabilitySubgroupShuffleINTEL = 5568, + CapabilitySubgroupBufferBlockIOINTEL = 5569, + CapabilitySubgroupImageBlockIOINTEL = 5570, + CapabilitySubgroupImageMediaBlockIOINTEL = 5579, + CapabilityIntegerFunctions2INTEL = 5584, + CapabilitySubgroupAvcMotionEstimationINTEL = 5696, + CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697, + CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698, + CapabilityMax = 0x7fffffff, +}; + +enum RayFlagsShift { + RayFlagsOpaqueKHRShift = 0, + RayFlagsNoOpaqueKHRShift = 1, + RayFlagsTerminateOnFirstHitKHRShift = 2, + RayFlagsSkipClosestHitShaderKHRShift = 3, + RayFlagsCullBackFacingTrianglesKHRShift = 4, + RayFlagsCullFrontFacingTrianglesKHRShift = 5, + RayFlagsCullOpaqueKHRShift = 6, + RayFlagsCullNoOpaqueKHRShift = 7, + RayFlagsSkipTrianglesKHRShift = 8, + RayFlagsSkipAABBsKHRShift = 9, + RayFlagsMax = 0x7fffffff, +}; + +enum RayFlagsMask { + RayFlagsMaskNone = 0, + RayFlagsOpaqueKHRMask = 0x00000001, + RayFlagsNoOpaqueKHRMask = 0x00000002, + RayFlagsTerminateOnFirstHitKHRMask = 0x00000004, + RayFlagsSkipClosestHitShaderKHRMask = 0x00000008, + RayFlagsCullBackFacingTrianglesKHRMask = 0x00000010, + RayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020, + RayFlagsCullOpaqueKHRMask = 0x00000040, + RayFlagsCullNoOpaqueKHRMask = 0x00000080, + RayFlagsSkipTrianglesKHRMask = 0x00000100, + RayFlagsSkipAABBsKHRMask = 0x00000200, +}; + +enum RayQueryIntersection { + RayQueryIntersectionRayQueryCandidateIntersectionKHR = 0, + RayQueryIntersectionRayQueryCommittedIntersectionKHR = 1, + RayQueryIntersectionMax = 0x7fffffff, +}; + +enum RayQueryCommittedIntersectionType { + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR = 0, + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR = 1, + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR = 2, + RayQueryCommittedIntersectionTypeMax = 0x7fffffff, +}; + +enum RayQueryCandidateIntersectionType { + RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR = 0, + RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR = 1, + RayQueryCandidateIntersectionTypeMax = 0x7fffffff, +}; + +enum Op { + OpNop = 0, + OpUndef = 1, + OpSourceContinued = 2, + OpSource = 3, + OpSourceExtension = 4, + OpName = 5, + OpMemberName = 6, + OpString = 7, + OpLine = 8, + OpExtension = 10, + OpExtInstImport = 11, + OpExtInst = 12, + OpMemoryModel = 14, + OpEntryPoint = 15, + OpExecutionMode = 16, + OpCapability = 17, + OpTypeVoid = 19, + OpTypeBool = 20, + OpTypeInt = 21, + OpTypeFloat = 22, + OpTypeVector = 23, + OpTypeMatrix = 24, + OpTypeImage = 25, + OpTypeSampler = 26, + OpTypeSampledImage = 27, + OpTypeArray = 28, + OpTypeRuntimeArray = 29, + OpTypeStruct = 30, + OpTypeOpaque = 31, + OpTypePointer = 32, + OpTypeFunction = 33, + OpTypeEvent = 34, + OpTypeDeviceEvent = 35, + OpTypeReserveId = 36, + OpTypeQueue = 37, + OpTypePipe = 38, + OpTypeForwardPointer = 39, + OpConstantTrue = 41, + OpConstantFalse = 42, + OpConstant = 43, + OpConstantComposite = 44, + OpConstantSampler = 45, + OpConstantNull = 46, + OpSpecConstantTrue = 48, + OpSpecConstantFalse = 49, + OpSpecConstant = 50, + OpSpecConstantComposite = 51, + OpSpecConstantOp = 52, + OpFunction = 54, + OpFunctionParameter = 55, + OpFunctionEnd = 56, + OpFunctionCall = 57, + OpVariable = 59, + OpImageTexelPointer = 60, + OpLoad = 61, + OpStore = 62, + OpCopyMemory = 63, + OpCopyMemorySized = 64, + OpAccessChain = 65, + OpInBoundsAccessChain = 66, + OpPtrAccessChain = 67, + OpArrayLength = 68, + OpGenericPtrMemSemantics = 69, + OpInBoundsPtrAccessChain = 70, + OpDecorate = 71, + OpMemberDecorate = 72, + OpDecorationGroup = 73, + OpGroupDecorate = 74, + OpGroupMemberDecorate = 75, + OpVectorExtractDynamic = 77, + OpVectorInsertDynamic = 78, + OpVectorShuffle = 79, + OpCompositeConstruct = 80, + OpCompositeExtract = 81, + OpCompositeInsert = 82, + OpCopyObject = 83, + OpTranspose = 84, + OpSampledImage = 86, + OpImageSampleImplicitLod = 87, + OpImageSampleExplicitLod = 88, + OpImageSampleDrefImplicitLod = 89, + OpImageSampleDrefExplicitLod = 90, + OpImageSampleProjImplicitLod = 91, + OpImageSampleProjExplicitLod = 92, + OpImageSampleProjDrefImplicitLod = 93, + OpImageSampleProjDrefExplicitLod = 94, + OpImageFetch = 95, + OpImageGather = 96, + OpImageDrefGather = 97, + OpImageRead = 98, + OpImageWrite = 99, + OpImage = 100, + OpImageQueryFormat = 101, + OpImageQueryOrder = 102, + OpImageQuerySizeLod = 103, + OpImageQuerySize = 104, + OpImageQueryLod = 105, + OpImageQueryLevels = 106, + OpImageQuerySamples = 107, + OpConvertFToU = 109, + OpConvertFToS = 110, + OpConvertSToF = 111, + OpConvertUToF = 112, + OpUConvert = 113, + OpSConvert = 114, + OpFConvert = 115, + OpQuantizeToF16 = 116, + OpConvertPtrToU = 117, + OpSatConvertSToU = 118, + OpSatConvertUToS = 119, + OpConvertUToPtr = 120, + OpPtrCastToGeneric = 121, + OpGenericCastToPtr = 122, + OpGenericCastToPtrExplicit = 123, + OpBitcast = 124, + OpSNegate = 126, + OpFNegate = 127, + OpIAdd = 128, + OpFAdd = 129, + OpISub = 130, + OpFSub = 131, + OpIMul = 132, + OpFMul = 133, + OpUDiv = 134, + OpSDiv = 135, + OpFDiv = 136, + OpUMod = 137, + OpSRem = 138, + OpSMod = 139, + OpFRem = 140, + OpFMod = 141, + OpVectorTimesScalar = 142, + OpMatrixTimesScalar = 143, + OpVectorTimesMatrix = 144, + OpMatrixTimesVector = 145, + OpMatrixTimesMatrix = 146, + OpOuterProduct = 147, + OpDot = 148, + OpIAddCarry = 149, + OpISubBorrow = 150, + OpUMulExtended = 151, + OpSMulExtended = 152, + OpAny = 154, + OpAll = 155, + OpIsNan = 156, + OpIsInf = 157, + OpIsFinite = 158, + OpIsNormal = 159, + OpSignBitSet = 160, + OpLessOrGreater = 161, + OpOrdered = 162, + OpUnordered = 163, + OpLogicalEqual = 164, + OpLogicalNotEqual = 165, + OpLogicalOr = 166, + OpLogicalAnd = 167, + OpLogicalNot = 168, + OpSelect = 169, + OpIEqual = 170, + OpINotEqual = 171, + OpUGreaterThan = 172, + OpSGreaterThan = 173, + OpUGreaterThanEqual = 174, + OpSGreaterThanEqual = 175, + OpULessThan = 176, + OpSLessThan = 177, + OpULessThanEqual = 178, + OpSLessThanEqual = 179, + OpFOrdEqual = 180, + OpFUnordEqual = 181, + OpFOrdNotEqual = 182, + OpFUnordNotEqual = 183, + OpFOrdLessThan = 184, + OpFUnordLessThan = 185, + OpFOrdGreaterThan = 186, + OpFUnordGreaterThan = 187, + OpFOrdLessThanEqual = 188, + OpFUnordLessThanEqual = 189, + OpFOrdGreaterThanEqual = 190, + OpFUnordGreaterThanEqual = 191, + OpShiftRightLogical = 194, + OpShiftRightArithmetic = 195, + OpShiftLeftLogical = 196, + OpBitwiseOr = 197, + OpBitwiseXor = 198, + OpBitwiseAnd = 199, + OpNot = 200, + OpBitFieldInsert = 201, + OpBitFieldSExtract = 202, + OpBitFieldUExtract = 203, + OpBitReverse = 204, + OpBitCount = 205, + OpDPdx = 207, + OpDPdy = 208, + OpFwidth = 209, + OpDPdxFine = 210, + OpDPdyFine = 211, + OpFwidthFine = 212, + OpDPdxCoarse = 213, + OpDPdyCoarse = 214, + OpFwidthCoarse = 215, + OpEmitVertex = 218, + OpEndPrimitive = 219, + OpEmitStreamVertex = 220, + OpEndStreamPrimitive = 221, + OpControlBarrier = 224, + OpMemoryBarrier = 225, + OpAtomicLoad = 227, + OpAtomicStore = 228, + OpAtomicExchange = 229, + OpAtomicCompareExchange = 230, + OpAtomicCompareExchangeWeak = 231, + OpAtomicIIncrement = 232, + OpAtomicIDecrement = 233, + OpAtomicIAdd = 234, + OpAtomicISub = 235, + OpAtomicSMin = 236, + OpAtomicUMin = 237, + OpAtomicSMax = 238, + OpAtomicUMax = 239, + OpAtomicAnd = 240, + OpAtomicOr = 241, + OpAtomicXor = 242, + OpPhi = 245, + OpLoopMerge = 246, + OpSelectionMerge = 247, + OpLabel = 248, + OpBranch = 249, + OpBranchConditional = 250, + OpSwitch = 251, + OpKill = 252, + OpReturn = 253, + OpReturnValue = 254, + OpUnreachable = 255, + OpLifetimeStart = 256, + OpLifetimeStop = 257, + OpGroupAsyncCopy = 259, + OpGroupWaitEvents = 260, + OpGroupAll = 261, + OpGroupAny = 262, + OpGroupBroadcast = 263, + OpGroupIAdd = 264, + OpGroupFAdd = 265, + OpGroupFMin = 266, + OpGroupUMin = 267, + OpGroupSMin = 268, + OpGroupFMax = 269, + OpGroupUMax = 270, + OpGroupSMax = 271, + OpReadPipe = 274, + OpWritePipe = 275, + OpReservedReadPipe = 276, + OpReservedWritePipe = 277, + OpReserveReadPipePackets = 278, + OpReserveWritePipePackets = 279, + OpCommitReadPipe = 280, + OpCommitWritePipe = 281, + OpIsValidReserveId = 282, + OpGetNumPipePackets = 283, + OpGetMaxPipePackets = 284, + OpGroupReserveReadPipePackets = 285, + OpGroupReserveWritePipePackets = 286, + OpGroupCommitReadPipe = 287, + OpGroupCommitWritePipe = 288, + OpEnqueueMarker = 291, + OpEnqueueKernel = 292, + OpGetKernelNDrangeSubGroupCount = 293, + OpGetKernelNDrangeMaxSubGroupSize = 294, + OpGetKernelWorkGroupSize = 295, + OpGetKernelPreferredWorkGroupSizeMultiple = 296, + OpRetainEvent = 297, + OpReleaseEvent = 298, + OpCreateUserEvent = 299, + OpIsValidEvent = 300, + OpSetUserEventStatus = 301, + OpCaptureEventProfilingInfo = 302, + OpGetDefaultQueue = 303, + OpBuildNDRange = 304, + OpImageSparseSampleImplicitLod = 305, + OpImageSparseSampleExplicitLod = 306, + OpImageSparseSampleDrefImplicitLod = 307, + OpImageSparseSampleDrefExplicitLod = 308, + OpImageSparseSampleProjImplicitLod = 309, + OpImageSparseSampleProjExplicitLod = 310, + OpImageSparseSampleProjDrefImplicitLod = 311, + OpImageSparseSampleProjDrefExplicitLod = 312, + OpImageSparseFetch = 313, + OpImageSparseGather = 314, + OpImageSparseDrefGather = 315, + OpImageSparseTexelsResident = 316, + OpNoLine = 317, + OpAtomicFlagTestAndSet = 318, + OpAtomicFlagClear = 319, + OpImageSparseRead = 320, + OpSizeOf = 321, + OpTypePipeStorage = 322, + OpConstantPipeStorage = 323, + OpCreatePipeFromPipeStorage = 324, + OpGetKernelLocalSizeForSubgroupCount = 325, + OpGetKernelMaxNumSubgroups = 326, + OpTypeNamedBarrier = 327, + OpNamedBarrierInitialize = 328, + OpMemoryNamedBarrier = 329, + OpModuleProcessed = 330, + OpExecutionModeId = 331, + OpDecorateId = 332, + OpGroupNonUniformElect = 333, + OpGroupNonUniformAll = 334, + OpGroupNonUniformAny = 335, + OpGroupNonUniformAllEqual = 336, + OpGroupNonUniformBroadcast = 337, + OpGroupNonUniformBroadcastFirst = 338, + OpGroupNonUniformBallot = 339, + OpGroupNonUniformInverseBallot = 340, + OpGroupNonUniformBallotBitExtract = 341, + OpGroupNonUniformBallotBitCount = 342, + OpGroupNonUniformBallotFindLSB = 343, + OpGroupNonUniformBallotFindMSB = 344, + OpGroupNonUniformShuffle = 345, + OpGroupNonUniformShuffleXor = 346, + OpGroupNonUniformShuffleUp = 347, + OpGroupNonUniformShuffleDown = 348, + OpGroupNonUniformIAdd = 349, + OpGroupNonUniformFAdd = 350, + OpGroupNonUniformIMul = 351, + OpGroupNonUniformFMul = 352, + OpGroupNonUniformSMin = 353, + OpGroupNonUniformUMin = 354, + OpGroupNonUniformFMin = 355, + OpGroupNonUniformSMax = 356, + OpGroupNonUniformUMax = 357, + OpGroupNonUniformFMax = 358, + OpGroupNonUniformBitwiseAnd = 359, + OpGroupNonUniformBitwiseOr = 360, + OpGroupNonUniformBitwiseXor = 361, + OpGroupNonUniformLogicalAnd = 362, + OpGroupNonUniformLogicalOr = 363, + OpGroupNonUniformLogicalXor = 364, + OpGroupNonUniformQuadBroadcast = 365, + OpGroupNonUniformQuadSwap = 366, + OpCopyLogical = 400, + OpPtrEqual = 401, + OpPtrNotEqual = 402, + OpPtrDiff = 403, + OpSubgroupBallotKHR = 4421, + OpSubgroupFirstInvocationKHR = 4422, + OpSubgroupAllKHR = 4428, + OpSubgroupAnyKHR = 4429, + OpSubgroupAllEqualKHR = 4430, + OpSubgroupReadInvocationKHR = 4432, + OpTypeRayQueryProvisionalKHR = 4472, + OpRayQueryInitializeKHR = 4473, + OpRayQueryTerminateKHR = 4474, + OpRayQueryGenerateIntersectionKHR = 4475, + OpRayQueryConfirmIntersectionKHR = 4476, + OpRayQueryProceedKHR = 4477, + OpRayQueryGetIntersectionTypeKHR = 4479, + OpGroupIAddNonUniformAMD = 5000, + OpGroupFAddNonUniformAMD = 5001, + OpGroupFMinNonUniformAMD = 5002, + OpGroupUMinNonUniformAMD = 5003, + OpGroupSMinNonUniformAMD = 5004, + OpGroupFMaxNonUniformAMD = 5005, + OpGroupUMaxNonUniformAMD = 5006, + OpGroupSMaxNonUniformAMD = 5007, + OpFragmentMaskFetchAMD = 5011, + OpFragmentFetchAMD = 5012, + OpReadClockKHR = 5056, + OpImageSampleFootprintNV = 5283, + OpGroupNonUniformPartitionNV = 5296, + OpWritePackedPrimitiveIndices4x8NV = 5299, + OpReportIntersectionKHR = 5334, + OpReportIntersectionNV = 5334, + OpIgnoreIntersectionKHR = 5335, + OpIgnoreIntersectionNV = 5335, + OpTerminateRayKHR = 5336, + OpTerminateRayNV = 5336, + OpTraceNV = 5337, + OpTraceRayKHR = 5337, + OpTypeAccelerationStructureKHR = 5341, + OpTypeAccelerationStructureNV = 5341, + OpExecuteCallableKHR = 5344, + OpExecuteCallableNV = 5344, + OpTypeCooperativeMatrixNV = 5358, + OpCooperativeMatrixLoadNV = 5359, + OpCooperativeMatrixStoreNV = 5360, + OpCooperativeMatrixMulAddNV = 5361, + OpCooperativeMatrixLengthNV = 5362, + OpBeginInvocationInterlockEXT = 5364, + OpEndInvocationInterlockEXT = 5365, + OpDemoteToHelperInvocationEXT = 5380, + OpIsHelperInvocationEXT = 5381, + OpSubgroupShuffleINTEL = 5571, + OpSubgroupShuffleDownINTEL = 5572, + OpSubgroupShuffleUpINTEL = 5573, + OpSubgroupShuffleXorINTEL = 5574, + OpSubgroupBlockReadINTEL = 5575, + OpSubgroupBlockWriteINTEL = 5576, + OpSubgroupImageBlockReadINTEL = 5577, + OpSubgroupImageBlockWriteINTEL = 5578, + OpSubgroupImageMediaBlockReadINTEL = 5580, + OpSubgroupImageMediaBlockWriteINTEL = 5581, + OpUCountLeadingZerosINTEL = 5585, + OpUCountTrailingZerosINTEL = 5586, + OpAbsISubINTEL = 5587, + OpAbsUSubINTEL = 5588, + OpIAddSatINTEL = 5589, + OpUAddSatINTEL = 5590, + OpIAverageINTEL = 5591, + OpUAverageINTEL = 5592, + OpIAverageRoundedINTEL = 5593, + OpUAverageRoundedINTEL = 5594, + OpISubSatINTEL = 5595, + OpUSubSatINTEL = 5596, + OpIMul32x16INTEL = 5597, + OpUMul32x16INTEL = 5598, + OpDecorateString = 5632, + OpDecorateStringGOOGLE = 5632, + OpMemberDecorateString = 5633, + OpMemberDecorateStringGOOGLE = 5633, + OpVmeImageINTEL = 5699, + OpTypeVmeImageINTEL = 5700, + OpTypeAvcImePayloadINTEL = 5701, + OpTypeAvcRefPayloadINTEL = 5702, + OpTypeAvcSicPayloadINTEL = 5703, + OpTypeAvcMcePayloadINTEL = 5704, + OpTypeAvcMceResultINTEL = 5705, + OpTypeAvcImeResultINTEL = 5706, + OpTypeAvcImeResultSingleReferenceStreamoutINTEL = 5707, + OpTypeAvcImeResultDualReferenceStreamoutINTEL = 5708, + OpTypeAvcImeSingleReferenceStreaminINTEL = 5709, + OpTypeAvcImeDualReferenceStreaminINTEL = 5710, + OpTypeAvcRefResultINTEL = 5711, + OpTypeAvcSicResultINTEL = 5712, + OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL = 5713, + OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL = 5714, + OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL = 5715, + OpSubgroupAvcMceSetInterShapePenaltyINTEL = 5716, + OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL = 5717, + OpSubgroupAvcMceSetInterDirectionPenaltyINTEL = 5718, + OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL = 5719, + OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL = 5720, + OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL = 5721, + OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL = 5722, + OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL = 5723, + OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL = 5724, + OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL = 5725, + OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL = 5726, + OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL = 5727, + OpSubgroupAvcMceSetAcOnlyHaarINTEL = 5728, + OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL = 5729, + OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL = 5730, + OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL = 5731, + OpSubgroupAvcMceConvertToImePayloadINTEL = 5732, + OpSubgroupAvcMceConvertToImeResultINTEL = 5733, + OpSubgroupAvcMceConvertToRefPayloadINTEL = 5734, + OpSubgroupAvcMceConvertToRefResultINTEL = 5735, + OpSubgroupAvcMceConvertToSicPayloadINTEL = 5736, + OpSubgroupAvcMceConvertToSicResultINTEL = 5737, + OpSubgroupAvcMceGetMotionVectorsINTEL = 5738, + OpSubgroupAvcMceGetInterDistortionsINTEL = 5739, + OpSubgroupAvcMceGetBestInterDistortionsINTEL = 5740, + OpSubgroupAvcMceGetInterMajorShapeINTEL = 5741, + OpSubgroupAvcMceGetInterMinorShapeINTEL = 5742, + OpSubgroupAvcMceGetInterDirectionsINTEL = 5743, + OpSubgroupAvcMceGetInterMotionVectorCountINTEL = 5744, + OpSubgroupAvcMceGetInterReferenceIdsINTEL = 5745, + OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL = 5746, + OpSubgroupAvcImeInitializeINTEL = 5747, + OpSubgroupAvcImeSetSingleReferenceINTEL = 5748, + OpSubgroupAvcImeSetDualReferenceINTEL = 5749, + OpSubgroupAvcImeRefWindowSizeINTEL = 5750, + OpSubgroupAvcImeAdjustRefOffsetINTEL = 5751, + OpSubgroupAvcImeConvertToMcePayloadINTEL = 5752, + OpSubgroupAvcImeSetMaxMotionVectorCountINTEL = 5753, + OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL = 5754, + OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL = 5755, + OpSubgroupAvcImeSetWeightedSadINTEL = 5756, + OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL = 5757, + OpSubgroupAvcImeEvaluateWithDualReferenceINTEL = 5758, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL = 5759, + OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL = 5760, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL = 5761, + OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL = 5762, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL = 5763, + OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL = 5764, + OpSubgroupAvcImeConvertToMceResultINTEL = 5765, + OpSubgroupAvcImeGetSingleReferenceStreaminINTEL = 5766, + OpSubgroupAvcImeGetDualReferenceStreaminINTEL = 5767, + OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL = 5768, + OpSubgroupAvcImeStripDualReferenceStreamoutINTEL = 5769, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL = 5770, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL = 5771, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL = 5772, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL = 5773, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL = 5774, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL = 5775, + OpSubgroupAvcImeGetBorderReachedINTEL = 5776, + OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL = 5777, + OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL = 5778, + OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL = 5779, + OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL = 5780, + OpSubgroupAvcFmeInitializeINTEL = 5781, + OpSubgroupAvcBmeInitializeINTEL = 5782, + OpSubgroupAvcRefConvertToMcePayloadINTEL = 5783, + OpSubgroupAvcRefSetBidirectionalMixDisableINTEL = 5784, + OpSubgroupAvcRefSetBilinearFilterEnableINTEL = 5785, + OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL = 5786, + OpSubgroupAvcRefEvaluateWithDualReferenceINTEL = 5787, + OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL = 5788, + OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL = 5789, + OpSubgroupAvcRefConvertToMceResultINTEL = 5790, + OpSubgroupAvcSicInitializeINTEL = 5791, + OpSubgroupAvcSicConfigureSkcINTEL = 5792, + OpSubgroupAvcSicConfigureIpeLumaINTEL = 5793, + OpSubgroupAvcSicConfigureIpeLumaChromaINTEL = 5794, + OpSubgroupAvcSicGetMotionVectorMaskINTEL = 5795, + OpSubgroupAvcSicConvertToMcePayloadINTEL = 5796, + OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL = 5797, + OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL = 5798, + OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL = 5799, + OpSubgroupAvcSicSetBilinearFilterEnableINTEL = 5800, + OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL = 5801, + OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL = 5802, + OpSubgroupAvcSicEvaluateIpeINTEL = 5803, + OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL = 5804, + OpSubgroupAvcSicEvaluateWithDualReferenceINTEL = 5805, + OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL = 5806, + OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL = 5807, + OpSubgroupAvcSicConvertToMceResultINTEL = 5808, + OpSubgroupAvcSicGetIpeLumaShapeINTEL = 5809, + OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL = 5810, + OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL = 5811, + OpSubgroupAvcSicGetPackedIpeLumaModesINTEL = 5812, + OpSubgroupAvcSicGetIpeChromaModeINTEL = 5813, + OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, + OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, + OpSubgroupAvcSicGetInterRawSadsINTEL = 5816, + OpRayQueryGetRayTMinKHR = 6016, + OpRayQueryGetRayFlagsKHR = 6017, + OpRayQueryGetIntersectionTKHR = 6018, + OpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019, + OpRayQueryGetIntersectionInstanceIdKHR = 6020, + OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021, + OpRayQueryGetIntersectionGeometryIndexKHR = 6022, + OpRayQueryGetIntersectionPrimitiveIndexKHR = 6023, + OpRayQueryGetIntersectionBarycentricsKHR = 6024, + OpRayQueryGetIntersectionFrontFaceKHR = 6025, + OpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026, + OpRayQueryGetIntersectionObjectRayDirectionKHR = 6027, + OpRayQueryGetIntersectionObjectRayOriginKHR = 6028, + OpRayQueryGetWorldRayDirectionKHR = 6029, + OpRayQueryGetWorldRayOriginKHR = 6030, + OpRayQueryGetIntersectionObjectToWorldKHR = 6031, + OpRayQueryGetIntersectionWorldToObjectKHR = 6032, + OpMax = 0x7fffffff, +}; + +#ifdef SPV_ENABLE_UTILITY_CODE +inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) { + *hasResult = *hasResultType = false; + switch (opcode) { + default: /* unknown opcode */ break; + case OpNop: *hasResult = false; *hasResultType = false; break; + case OpUndef: *hasResult = true; *hasResultType = true; break; + case OpSourceContinued: *hasResult = false; *hasResultType = false; break; + case OpSource: *hasResult = false; *hasResultType = false; break; + case OpSourceExtension: *hasResult = false; *hasResultType = false; break; + case OpName: *hasResult = false; *hasResultType = false; break; + case OpMemberName: *hasResult = false; *hasResultType = false; break; + case OpString: *hasResult = true; *hasResultType = false; break; + case OpLine: *hasResult = false; *hasResultType = false; break; + case OpExtension: *hasResult = false; *hasResultType = false; break; + case OpExtInstImport: *hasResult = true; *hasResultType = false; break; + case OpExtInst: *hasResult = true; *hasResultType = true; break; + case OpMemoryModel: *hasResult = false; *hasResultType = false; break; + case OpEntryPoint: *hasResult = false; *hasResultType = false; break; + case OpExecutionMode: *hasResult = false; *hasResultType = false; break; + case OpCapability: *hasResult = false; *hasResultType = false; break; + case OpTypeVoid: *hasResult = true; *hasResultType = false; break; + case OpTypeBool: *hasResult = true; *hasResultType = false; break; + case OpTypeInt: *hasResult = true; *hasResultType = false; break; + case OpTypeFloat: *hasResult = true; *hasResultType = false; break; + case OpTypeVector: *hasResult = true; *hasResultType = false; break; + case OpTypeMatrix: *hasResult = true; *hasResultType = false; break; + case OpTypeImage: *hasResult = true; *hasResultType = false; break; + case OpTypeSampler: *hasResult = true; *hasResultType = false; break; + case OpTypeSampledImage: *hasResult = true; *hasResultType = false; break; + case OpTypeArray: *hasResult = true; *hasResultType = false; break; + case OpTypeRuntimeArray: *hasResult = true; *hasResultType = false; break; + case OpTypeStruct: *hasResult = true; *hasResultType = false; break; + case OpTypeOpaque: *hasResult = true; *hasResultType = false; break; + case OpTypePointer: *hasResult = true; *hasResultType = false; break; + case OpTypeFunction: *hasResult = true; *hasResultType = false; break; + case OpTypeEvent: *hasResult = true; *hasResultType = false; break; + case OpTypeDeviceEvent: *hasResult = true; *hasResultType = false; break; + case OpTypeReserveId: *hasResult = true; *hasResultType = false; break; + case OpTypeQueue: *hasResult = true; *hasResultType = false; break; + case OpTypePipe: *hasResult = true; *hasResultType = false; break; + case OpTypeForwardPointer: *hasResult = false; *hasResultType = false; break; + case OpConstantTrue: *hasResult = true; *hasResultType = true; break; + case OpConstantFalse: *hasResult = true; *hasResultType = true; break; + case OpConstant: *hasResult = true; *hasResultType = true; break; + case OpConstantComposite: *hasResult = true; *hasResultType = true; break; + case OpConstantSampler: *hasResult = true; *hasResultType = true; break; + case OpConstantNull: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantTrue: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantFalse: *hasResult = true; *hasResultType = true; break; + case OpSpecConstant: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantComposite: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantOp: *hasResult = true; *hasResultType = true; break; + case OpFunction: *hasResult = true; *hasResultType = true; break; + case OpFunctionParameter: *hasResult = true; *hasResultType = true; break; + case OpFunctionEnd: *hasResult = false; *hasResultType = false; break; + case OpFunctionCall: *hasResult = true; *hasResultType = true; break; + case OpVariable: *hasResult = true; *hasResultType = true; break; + case OpImageTexelPointer: *hasResult = true; *hasResultType = true; break; + case OpLoad: *hasResult = true; *hasResultType = true; break; + case OpStore: *hasResult = false; *hasResultType = false; break; + case OpCopyMemory: *hasResult = false; *hasResultType = false; break; + case OpCopyMemorySized: *hasResult = false; *hasResultType = false; break; + case OpAccessChain: *hasResult = true; *hasResultType = true; break; + case OpInBoundsAccessChain: *hasResult = true; *hasResultType = true; break; + case OpPtrAccessChain: *hasResult = true; *hasResultType = true; break; + case OpArrayLength: *hasResult = true; *hasResultType = true; break; + case OpGenericPtrMemSemantics: *hasResult = true; *hasResultType = true; break; + case OpInBoundsPtrAccessChain: *hasResult = true; *hasResultType = true; break; + case OpDecorate: *hasResult = false; *hasResultType = false; break; + case OpMemberDecorate: *hasResult = false; *hasResultType = false; break; + case OpDecorationGroup: *hasResult = true; *hasResultType = false; break; + case OpGroupDecorate: *hasResult = false; *hasResultType = false; break; + case OpGroupMemberDecorate: *hasResult = false; *hasResultType = false; break; + case OpVectorExtractDynamic: *hasResult = true; *hasResultType = true; break; + case OpVectorInsertDynamic: *hasResult = true; *hasResultType = true; break; + case OpVectorShuffle: *hasResult = true; *hasResultType = true; break; + case OpCompositeConstruct: *hasResult = true; *hasResultType = true; break; + case OpCompositeExtract: *hasResult = true; *hasResultType = true; break; + case OpCompositeInsert: *hasResult = true; *hasResultType = true; break; + case OpCopyObject: *hasResult = true; *hasResultType = true; break; + case OpTranspose: *hasResult = true; *hasResultType = true; break; + case OpSampledImage: *hasResult = true; *hasResultType = true; break; + case OpImageSampleImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageFetch: *hasResult = true; *hasResultType = true; break; + case OpImageGather: *hasResult = true; *hasResultType = true; break; + case OpImageDrefGather: *hasResult = true; *hasResultType = true; break; + case OpImageRead: *hasResult = true; *hasResultType = true; break; + case OpImageWrite: *hasResult = false; *hasResultType = false; break; + case OpImage: *hasResult = true; *hasResultType = true; break; + case OpImageQueryFormat: *hasResult = true; *hasResultType = true; break; + case OpImageQueryOrder: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySizeLod: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySize: *hasResult = true; *hasResultType = true; break; + case OpImageQueryLod: *hasResult = true; *hasResultType = true; break; + case OpImageQueryLevels: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySamples: *hasResult = true; *hasResultType = true; break; + case OpConvertFToU: *hasResult = true; *hasResultType = true; break; + case OpConvertFToS: *hasResult = true; *hasResultType = true; break; + case OpConvertSToF: *hasResult = true; *hasResultType = true; break; + case OpConvertUToF: *hasResult = true; *hasResultType = true; break; + case OpUConvert: *hasResult = true; *hasResultType = true; break; + case OpSConvert: *hasResult = true; *hasResultType = true; break; + case OpFConvert: *hasResult = true; *hasResultType = true; break; + case OpQuantizeToF16: *hasResult = true; *hasResultType = true; break; + case OpConvertPtrToU: *hasResult = true; *hasResultType = true; break; + case OpSatConvertSToU: *hasResult = true; *hasResultType = true; break; + case OpSatConvertUToS: *hasResult = true; *hasResultType = true; break; + case OpConvertUToPtr: *hasResult = true; *hasResultType = true; break; + case OpPtrCastToGeneric: *hasResult = true; *hasResultType = true; break; + case OpGenericCastToPtr: *hasResult = true; *hasResultType = true; break; + case OpGenericCastToPtrExplicit: *hasResult = true; *hasResultType = true; break; + case OpBitcast: *hasResult = true; *hasResultType = true; break; + case OpSNegate: *hasResult = true; *hasResultType = true; break; + case OpFNegate: *hasResult = true; *hasResultType = true; break; + case OpIAdd: *hasResult = true; *hasResultType = true; break; + case OpFAdd: *hasResult = true; *hasResultType = true; break; + case OpISub: *hasResult = true; *hasResultType = true; break; + case OpFSub: *hasResult = true; *hasResultType = true; break; + case OpIMul: *hasResult = true; *hasResultType = true; break; + case OpFMul: *hasResult = true; *hasResultType = true; break; + case OpUDiv: *hasResult = true; *hasResultType = true; break; + case OpSDiv: *hasResult = true; *hasResultType = true; break; + case OpFDiv: *hasResult = true; *hasResultType = true; break; + case OpUMod: *hasResult = true; *hasResultType = true; break; + case OpSRem: *hasResult = true; *hasResultType = true; break; + case OpSMod: *hasResult = true; *hasResultType = true; break; + case OpFRem: *hasResult = true; *hasResultType = true; break; + case OpFMod: *hasResult = true; *hasResultType = true; break; + case OpVectorTimesScalar: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesScalar: *hasResult = true; *hasResultType = true; break; + case OpVectorTimesMatrix: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesVector: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesMatrix: *hasResult = true; *hasResultType = true; break; + case OpOuterProduct: *hasResult = true; *hasResultType = true; break; + case OpDot: *hasResult = true; *hasResultType = true; break; + case OpIAddCarry: *hasResult = true; *hasResultType = true; break; + case OpISubBorrow: *hasResult = true; *hasResultType = true; break; + case OpUMulExtended: *hasResult = true; *hasResultType = true; break; + case OpSMulExtended: *hasResult = true; *hasResultType = true; break; + case OpAny: *hasResult = true; *hasResultType = true; break; + case OpAll: *hasResult = true; *hasResultType = true; break; + case OpIsNan: *hasResult = true; *hasResultType = true; break; + case OpIsInf: *hasResult = true; *hasResultType = true; break; + case OpIsFinite: *hasResult = true; *hasResultType = true; break; + case OpIsNormal: *hasResult = true; *hasResultType = true; break; + case OpSignBitSet: *hasResult = true; *hasResultType = true; break; + case OpLessOrGreater: *hasResult = true; *hasResultType = true; break; + case OpOrdered: *hasResult = true; *hasResultType = true; break; + case OpUnordered: *hasResult = true; *hasResultType = true; break; + case OpLogicalEqual: *hasResult = true; *hasResultType = true; break; + case OpLogicalNotEqual: *hasResult = true; *hasResultType = true; break; + case OpLogicalOr: *hasResult = true; *hasResultType = true; break; + case OpLogicalAnd: *hasResult = true; *hasResultType = true; break; + case OpLogicalNot: *hasResult = true; *hasResultType = true; break; + case OpSelect: *hasResult = true; *hasResultType = true; break; + case OpIEqual: *hasResult = true; *hasResultType = true; break; + case OpINotEqual: *hasResult = true; *hasResultType = true; break; + case OpUGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpSGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpUGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpSGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpULessThan: *hasResult = true; *hasResultType = true; break; + case OpSLessThan: *hasResult = true; *hasResultType = true; break; + case OpULessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpSLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdNotEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordNotEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdLessThan: *hasResult = true; *hasResultType = true; break; + case OpFUnordLessThan: *hasResult = true; *hasResultType = true; break; + case OpFOrdGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpFUnordGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpFOrdLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpShiftRightLogical: *hasResult = true; *hasResultType = true; break; + case OpShiftRightArithmetic: *hasResult = true; *hasResultType = true; break; + case OpShiftLeftLogical: *hasResult = true; *hasResultType = true; break; + case OpBitwiseOr: *hasResult = true; *hasResultType = true; break; + case OpBitwiseXor: *hasResult = true; *hasResultType = true; break; + case OpBitwiseAnd: *hasResult = true; *hasResultType = true; break; + case OpNot: *hasResult = true; *hasResultType = true; break; + case OpBitFieldInsert: *hasResult = true; *hasResultType = true; break; + case OpBitFieldSExtract: *hasResult = true; *hasResultType = true; break; + case OpBitFieldUExtract: *hasResult = true; *hasResultType = true; break; + case OpBitReverse: *hasResult = true; *hasResultType = true; break; + case OpBitCount: *hasResult = true; *hasResultType = true; break; + case OpDPdx: *hasResult = true; *hasResultType = true; break; + case OpDPdy: *hasResult = true; *hasResultType = true; break; + case OpFwidth: *hasResult = true; *hasResultType = true; break; + case OpDPdxFine: *hasResult = true; *hasResultType = true; break; + case OpDPdyFine: *hasResult = true; *hasResultType = true; break; + case OpFwidthFine: *hasResult = true; *hasResultType = true; break; + case OpDPdxCoarse: *hasResult = true; *hasResultType = true; break; + case OpDPdyCoarse: *hasResult = true; *hasResultType = true; break; + case OpFwidthCoarse: *hasResult = true; *hasResultType = true; break; + case OpEmitVertex: *hasResult = false; *hasResultType = false; break; + case OpEndPrimitive: *hasResult = false; *hasResultType = false; break; + case OpEmitStreamVertex: *hasResult = false; *hasResultType = false; break; + case OpEndStreamPrimitive: *hasResult = false; *hasResultType = false; break; + case OpControlBarrier: *hasResult = false; *hasResultType = false; break; + case OpMemoryBarrier: *hasResult = false; *hasResultType = false; break; + case OpAtomicLoad: *hasResult = true; *hasResultType = true; break; + case OpAtomicStore: *hasResult = false; *hasResultType = false; break; + case OpAtomicExchange: *hasResult = true; *hasResultType = true; break; + case OpAtomicCompareExchange: *hasResult = true; *hasResultType = true; break; + case OpAtomicCompareExchangeWeak: *hasResult = true; *hasResultType = true; break; + case OpAtomicIIncrement: *hasResult = true; *hasResultType = true; break; + case OpAtomicIDecrement: *hasResult = true; *hasResultType = true; break; + case OpAtomicIAdd: *hasResult = true; *hasResultType = true; break; + case OpAtomicISub: *hasResult = true; *hasResultType = true; break; + case OpAtomicSMin: *hasResult = true; *hasResultType = true; break; + case OpAtomicUMin: *hasResult = true; *hasResultType = true; break; + case OpAtomicSMax: *hasResult = true; *hasResultType = true; break; + case OpAtomicUMax: *hasResult = true; *hasResultType = true; break; + case OpAtomicAnd: *hasResult = true; *hasResultType = true; break; + case OpAtomicOr: *hasResult = true; *hasResultType = true; break; + case OpAtomicXor: *hasResult = true; *hasResultType = true; break; + case OpPhi: *hasResult = true; *hasResultType = true; break; + case OpLoopMerge: *hasResult = false; *hasResultType = false; break; + case OpSelectionMerge: *hasResult = false; *hasResultType = false; break; + case OpLabel: *hasResult = true; *hasResultType = false; break; + case OpBranch: *hasResult = false; *hasResultType = false; break; + case OpBranchConditional: *hasResult = false; *hasResultType = false; break; + case OpSwitch: *hasResult = false; *hasResultType = false; break; + case OpKill: *hasResult = false; *hasResultType = false; break; + case OpReturn: *hasResult = false; *hasResultType = false; break; + case OpReturnValue: *hasResult = false; *hasResultType = false; break; + case OpUnreachable: *hasResult = false; *hasResultType = false; break; + case OpLifetimeStart: *hasResult = false; *hasResultType = false; break; + case OpLifetimeStop: *hasResult = false; *hasResultType = false; break; + case OpGroupAsyncCopy: *hasResult = true; *hasResultType = true; break; + case OpGroupWaitEvents: *hasResult = false; *hasResultType = false; break; + case OpGroupAll: *hasResult = true; *hasResultType = true; break; + case OpGroupAny: *hasResult = true; *hasResultType = true; break; + case OpGroupBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupIAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupFAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupFMin: *hasResult = true; *hasResultType = true; break; + case OpGroupUMin: *hasResult = true; *hasResultType = true; break; + case OpGroupSMin: *hasResult = true; *hasResultType = true; break; + case OpGroupFMax: *hasResult = true; *hasResultType = true; break; + case OpGroupUMax: *hasResult = true; *hasResultType = true; break; + case OpGroupSMax: *hasResult = true; *hasResultType = true; break; + case OpReadPipe: *hasResult = true; *hasResultType = true; break; + case OpWritePipe: *hasResult = true; *hasResultType = true; break; + case OpReservedReadPipe: *hasResult = true; *hasResultType = true; break; + case OpReservedWritePipe: *hasResult = true; *hasResultType = true; break; + case OpReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; + case OpReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; + case OpCommitReadPipe: *hasResult = false; *hasResultType = false; break; + case OpCommitWritePipe: *hasResult = false; *hasResultType = false; break; + case OpIsValidReserveId: *hasResult = true; *hasResultType = true; break; + case OpGetNumPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGetMaxPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupCommitReadPipe: *hasResult = false; *hasResultType = false; break; + case OpGroupCommitWritePipe: *hasResult = false; *hasResultType = false; break; + case OpEnqueueMarker: *hasResult = true; *hasResultType = true; break; + case OpEnqueueKernel: *hasResult = true; *hasResultType = true; break; + case OpGetKernelNDrangeSubGroupCount: *hasResult = true; *hasResultType = true; break; + case OpGetKernelNDrangeMaxSubGroupSize: *hasResult = true; *hasResultType = true; break; + case OpGetKernelWorkGroupSize: *hasResult = true; *hasResultType = true; break; + case OpGetKernelPreferredWorkGroupSizeMultiple: *hasResult = true; *hasResultType = true; break; + case OpRetainEvent: *hasResult = false; *hasResultType = false; break; + case OpReleaseEvent: *hasResult = false; *hasResultType = false; break; + case OpCreateUserEvent: *hasResult = true; *hasResultType = true; break; + case OpIsValidEvent: *hasResult = true; *hasResultType = true; break; + case OpSetUserEventStatus: *hasResult = false; *hasResultType = false; break; + case OpCaptureEventProfilingInfo: *hasResult = false; *hasResultType = false; break; + case OpGetDefaultQueue: *hasResult = true; *hasResultType = true; break; + case OpBuildNDRange: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseFetch: *hasResult = true; *hasResultType = true; break; + case OpImageSparseGather: *hasResult = true; *hasResultType = true; break; + case OpImageSparseDrefGather: *hasResult = true; *hasResultType = true; break; + case OpImageSparseTexelsResident: *hasResult = true; *hasResultType = true; break; + case OpNoLine: *hasResult = false; *hasResultType = false; break; + case OpAtomicFlagTestAndSet: *hasResult = true; *hasResultType = true; break; + case OpAtomicFlagClear: *hasResult = false; *hasResultType = false; break; + case OpImageSparseRead: *hasResult = true; *hasResultType = true; break; + case OpSizeOf: *hasResult = true; *hasResultType = true; break; + case OpTypePipeStorage: *hasResult = true; *hasResultType = false; break; + case OpConstantPipeStorage: *hasResult = true; *hasResultType = true; break; + case OpCreatePipeFromPipeStorage: *hasResult = true; *hasResultType = true; break; + case OpGetKernelLocalSizeForSubgroupCount: *hasResult = true; *hasResultType = true; break; + case OpGetKernelMaxNumSubgroups: *hasResult = true; *hasResultType = true; break; + case OpTypeNamedBarrier: *hasResult = true; *hasResultType = false; break; + case OpNamedBarrierInitialize: *hasResult = true; *hasResultType = true; break; + case OpMemoryNamedBarrier: *hasResult = false; *hasResultType = false; break; + case OpModuleProcessed: *hasResult = false; *hasResultType = false; break; + case OpExecutionModeId: *hasResult = false; *hasResultType = false; break; + case OpDecorateId: *hasResult = false; *hasResultType = false; break; + case OpGroupNonUniformElect: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAll: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAny: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAllEqual: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBroadcastFirst: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallot: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformInverseBallot: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotBitExtract: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotBitCount: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotFindLSB: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotFindMSB: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffle: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleUp: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleDown: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformIAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformIMul: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMul: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformSMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformUMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformSMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformUMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseAnd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseOr: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalAnd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalOr: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformQuadBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformQuadSwap: *hasResult = true; *hasResultType = true; break; + case OpCopyLogical: *hasResult = true; *hasResultType = true; break; + case OpPtrEqual: *hasResult = true; *hasResultType = true; break; + case OpPtrNotEqual: *hasResult = true; *hasResultType = true; break; + case OpPtrDiff: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break; + case OpTypeRayQueryProvisionalKHR: *hasResult = true; *hasResultType = false; break; + case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break; + case OpGroupIAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupUMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupSMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupUMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupSMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpFragmentMaskFetchAMD: *hasResult = true; *hasResultType = true; break; + case OpFragmentFetchAMD: *hasResult = true; *hasResultType = true; break; + case OpReadClockKHR: *hasResult = true; *hasResultType = true; break; + case OpImageSampleFootprintNV: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformPartitionNV: *hasResult = true; *hasResultType = true; break; + case OpWritePackedPrimitiveIndices4x8NV: *hasResult = false; *hasResultType = false; break; + case OpReportIntersectionNV: *hasResult = true; *hasResultType = true; break; + case OpIgnoreIntersectionNV: *hasResult = false; *hasResultType = false; break; + case OpTerminateRayNV: *hasResult = false; *hasResultType = false; break; + case OpTraceNV: *hasResult = false; *hasResultType = false; break; + case OpTypeAccelerationStructureNV: *hasResult = true; *hasResultType = false; break; + case OpExecuteCallableNV: *hasResult = false; *hasResultType = false; break; + case OpTypeCooperativeMatrixNV: *hasResult = true; *hasResultType = false; break; + case OpCooperativeMatrixLoadNV: *hasResult = true; *hasResultType = true; break; + case OpCooperativeMatrixStoreNV: *hasResult = false; *hasResultType = false; break; + case OpCooperativeMatrixMulAddNV: *hasResult = true; *hasResultType = true; break; + case OpCooperativeMatrixLengthNV: *hasResult = true; *hasResultType = true; break; + case OpBeginInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; + case OpEndInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; + case OpDemoteToHelperInvocationEXT: *hasResult = false; *hasResultType = false; break; + case OpIsHelperInvocationEXT: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleDownINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleUpINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleXorINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpSubgroupImageBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupImageBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpSubgroupImageMediaBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupImageMediaBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpUCountLeadingZerosINTEL: *hasResult = true; *hasResultType = true; break; + case OpUCountTrailingZerosINTEL: *hasResult = true; *hasResultType = true; break; + case OpAbsISubINTEL: *hasResult = true; *hasResultType = true; break; + case OpAbsUSubINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAddSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAddSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAverageINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAverageINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; + case OpISubSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break; + case OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break; + case OpDecorateString: *hasResult = false; *hasResultType = false; break; + case OpMemberDecorateString: *hasResult = false; *hasResultType = false; break; + case OpVmeImageINTEL: *hasResult = true; *hasResultType = true; break; + case OpTypeVmeImageINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImePayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcRefPayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcSicPayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcMcePayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcMceResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcRefResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcSicResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetAcOnlyHaarINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToImePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToImeResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToRefPayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToRefResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToSicPayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToSicResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetBestInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMajorShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMinorShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterDirectionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeRefWindowSizeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeAdjustRefOffsetINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetMaxMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetWeightedSadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeStripDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetBorderReachedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcFmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcBmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefSetBidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureSkcINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureIpeLumaINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureIpeLumaChromaINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetMotionVectorMaskINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateIpeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetIpeLumaShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedIpeLumaModesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetIpeChromaModeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetRayTMinKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetRayFlagsKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionTKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceCustomIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceIdKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionGeometryIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionPrimitiveIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionBarycentricsKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionFrontFaceKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetWorldRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetWorldRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break; + } +} +#endif /* SPV_ENABLE_UTILITY_CODE */ + +// Overload operator| for mask bit combining + +inline ImageOperandsMask operator|(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) | unsigned(b)); } +inline FPFastMathModeMask operator|(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) | unsigned(b)); } +inline SelectionControlMask operator|(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) | unsigned(b)); } +inline LoopControlMask operator|(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) | unsigned(b)); } +inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) | unsigned(b)); } +inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); } +inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); } +inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); } +inline RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); } + +} // end namespace spv + +#endif // #ifndef spirv_HPP + diff --git a/mac/include/glslang/SPIRV/spvIR.h b/mac/include/glslang/SPIRV/spvIR.h new file mode 100644 index 00000000..6523035e --- /dev/null +++ b/mac/include/glslang/SPIRV/spvIR.h @@ -0,0 +1,485 @@ +// +// Copyright (C) 2014 LunarG, Inc. +// Copyright (C) 2015-2018 Google, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// Neither the name of 3Dlabs Inc. Ltd. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// SPIRV-IR +// +// Simple in-memory representation (IR) of SPIRV. Just for holding +// Each function's CFG of blocks. Has this hierarchy: +// - Module, which is a list of +// - Function, which is a list of +// - Block, which is a list of +// - Instruction +// + +#pragma once +#ifndef spvIR_H +#define spvIR_H + +#include "spirv.hpp" + +#include +#include +#include +#include +#include +#include + +namespace spv { + +class Block; +class Function; +class Module; + +const Id NoResult = 0; +const Id NoType = 0; + +const Decoration NoPrecision = DecorationMax; + +#ifdef __GNUC__ +# define POTENTIALLY_UNUSED __attribute__((unused)) +#else +# define POTENTIALLY_UNUSED +#endif + +POTENTIALLY_UNUSED +const MemorySemanticsMask MemorySemanticsAllMemory = + (MemorySemanticsMask)(MemorySemanticsUniformMemoryMask | + MemorySemanticsWorkgroupMemoryMask | + MemorySemanticsAtomicCounterMemoryMask | + MemorySemanticsImageMemoryMask); + +struct IdImmediate { + bool isId; // true if word is an Id, false if word is an immediate + unsigned word; + IdImmediate(bool i, unsigned w) : isId(i), word(w) {} +}; + +// +// SPIR-V IR instruction. +// + +class Instruction { +public: + Instruction(Id resultId, Id typeId, Op opCode) : resultId(resultId), typeId(typeId), opCode(opCode), block(nullptr) { } + explicit Instruction(Op opCode) : resultId(NoResult), typeId(NoType), opCode(opCode), block(nullptr) { } + virtual ~Instruction() {} + void addIdOperand(Id id) { + operands.push_back(id); + idOperand.push_back(true); + } + void addImmediateOperand(unsigned int immediate) { + operands.push_back(immediate); + idOperand.push_back(false); + } + void setImmediateOperand(unsigned idx, unsigned int immediate) { + assert(!idOperand[idx]); + operands[idx] = immediate; + } + + void addStringOperand(const char* str) + { + unsigned int word; + char* wordString = (char*)&word; + char* wordPtr = wordString; + int charCount = 0; + char c; + do { + c = *(str++); + *(wordPtr++) = c; + ++charCount; + if (charCount == 4) { + addImmediateOperand(word); + wordPtr = wordString; + charCount = 0; + } + } while (c != 0); + + // deal with partial last word + if (charCount > 0) { + // pad with 0s + for (; charCount < 4; ++charCount) + *(wordPtr++) = 0; + addImmediateOperand(word); + } + } + bool isIdOperand(int op) const { return idOperand[op]; } + void setBlock(Block* b) { block = b; } + Block* getBlock() const { return block; } + Op getOpCode() const { return opCode; } + int getNumOperands() const + { + assert(operands.size() == idOperand.size()); + return (int)operands.size(); + } + Id getResultId() const { return resultId; } + Id getTypeId() const { return typeId; } + Id getIdOperand(int op) const { + assert(idOperand[op]); + return operands[op]; + } + unsigned int getImmediateOperand(int op) const { + assert(!idOperand[op]); + return operands[op]; + } + + // Write out the binary form. + void dump(std::vector& out) const + { + // Compute the wordCount + unsigned int wordCount = 1; + if (typeId) + ++wordCount; + if (resultId) + ++wordCount; + wordCount += (unsigned int)operands.size(); + + // Write out the beginning of the instruction + out.push_back(((wordCount) << WordCountShift) | opCode); + if (typeId) + out.push_back(typeId); + if (resultId) + out.push_back(resultId); + + // Write out the operands + for (int op = 0; op < (int)operands.size(); ++op) + out.push_back(operands[op]); + } + +protected: + Instruction(const Instruction&); + Id resultId; + Id typeId; + Op opCode; + std::vector operands; // operands, both and immediates (both are unsigned int) + std::vector idOperand; // true for operands that are , false for immediates + Block* block; +}; + +// +// SPIR-V IR block. +// + +class Block { +public: + Block(Id id, Function& parent); + virtual ~Block() + { + } + + Id getId() { return instructions.front()->getResultId(); } + + Function& getParent() const { return parent; } + void addInstruction(std::unique_ptr inst); + void addPredecessor(Block* pred) { predecessors.push_back(pred); pred->successors.push_back(this);} + void addLocalVariable(std::unique_ptr inst) { localVariables.push_back(std::move(inst)); } + const std::vector& getPredecessors() const { return predecessors; } + const std::vector& getSuccessors() const { return successors; } + const std::vector >& getInstructions() const { + return instructions; + } + const std::vector >& getLocalVariables() const { return localVariables; } + void setUnreachable() { unreachable = true; } + bool isUnreachable() const { return unreachable; } + // Returns the block's merge instruction, if one exists (otherwise null). + const Instruction* getMergeInstruction() const { + if (instructions.size() < 2) return nullptr; + const Instruction* nextToLast = (instructions.cend() - 2)->get(); + switch (nextToLast->getOpCode()) { + case OpSelectionMerge: + case OpLoopMerge: + return nextToLast; + default: + return nullptr; + } + return nullptr; + } + + // Change this block into a canonical dead merge block. Delete instructions + // as necessary. A canonical dead merge block has only an OpLabel and an + // OpUnreachable. + void rewriteAsCanonicalUnreachableMerge() { + assert(localVariables.empty()); + // Delete all instructions except for the label. + assert(instructions.size() > 0); + instructions.resize(1); + successors.clear(); + addInstruction(std::unique_ptr(new Instruction(OpUnreachable))); + } + // Change this block into a canonical dead continue target branching to the + // given header ID. Delete instructions as necessary. A canonical dead continue + // target has only an OpLabel and an unconditional branch back to the corresponding + // header. + void rewriteAsCanonicalUnreachableContinue(Block* header) { + assert(localVariables.empty()); + // Delete all instructions except for the label. + assert(instructions.size() > 0); + instructions.resize(1); + successors.clear(); + // Add OpBranch back to the header. + assert(header != nullptr); + Instruction* branch = new Instruction(OpBranch); + branch->addIdOperand(header->getId()); + addInstruction(std::unique_ptr(branch)); + successors.push_back(header); + } + + bool isTerminated() const + { + switch (instructions.back()->getOpCode()) { + case OpBranch: + case OpBranchConditional: + case OpSwitch: + case OpKill: + case OpReturn: + case OpReturnValue: + case OpUnreachable: + return true; + default: + return false; + } + } + + void dump(std::vector& out) const + { + instructions[0]->dump(out); + for (int i = 0; i < (int)localVariables.size(); ++i) + localVariables[i]->dump(out); + for (int i = 1; i < (int)instructions.size(); ++i) + instructions[i]->dump(out); + } + +protected: + Block(const Block&); + Block& operator=(Block&); + + // To enforce keeping parent and ownership in sync: + friend Function; + + std::vector > instructions; + std::vector predecessors, successors; + std::vector > localVariables; + Function& parent; + + // track whether this block is known to be uncreachable (not necessarily + // true for all unreachable blocks, but should be set at least + // for the extraneous ones introduced by the builder). + bool unreachable; +}; + +// The different reasons for reaching a block in the inReadableOrder traversal. +enum ReachReason { + // Reachable from the entry block via transfers of control, i.e. branches. + ReachViaControlFlow = 0, + // A continue target that is not reachable via control flow. + ReachDeadContinue, + // A merge block that is not reachable via control flow. + ReachDeadMerge +}; + +// Traverses the control-flow graph rooted at root in an order suited for +// readable code generation. Invokes callback at every node in the traversal +// order. The callback arguments are: +// - the block, +// - the reason we reached the block, +// - if the reason was that block is an unreachable continue or unreachable merge block +// then the last parameter is the corresponding header block. +void inReadableOrder(Block* root, std::function callback); + +// +// SPIR-V IR Function. +// + +class Function { +public: + Function(Id id, Id resultType, Id functionType, Id firstParam, Module& parent); + virtual ~Function() + { + for (int i = 0; i < (int)parameterInstructions.size(); ++i) + delete parameterInstructions[i]; + + for (int i = 0; i < (int)blocks.size(); ++i) + delete blocks[i]; + } + Id getId() const { return functionInstruction.getResultId(); } + Id getParamId(int p) const { return parameterInstructions[p]->getResultId(); } + Id getParamType(int p) const { return parameterInstructions[p]->getTypeId(); } + + void addBlock(Block* block) { blocks.push_back(block); } + void removeBlock(Block* block) + { + auto found = find(blocks.begin(), blocks.end(), block); + assert(found != blocks.end()); + blocks.erase(found); + delete block; + } + + Module& getParent() const { return parent; } + Block* getEntryBlock() const { return blocks.front(); } + Block* getLastBlock() const { return blocks.back(); } + const std::vector& getBlocks() const { return blocks; } + void addLocalVariable(std::unique_ptr inst); + Id getReturnType() const { return functionInstruction.getTypeId(); } + + void setImplicitThis() { implicitThis = true; } + bool hasImplicitThis() const { return implicitThis; } + + void dump(std::vector& out) const + { + // OpFunction + functionInstruction.dump(out); + + // OpFunctionParameter + for (int p = 0; p < (int)parameterInstructions.size(); ++p) + parameterInstructions[p]->dump(out); + + // Blocks + inReadableOrder(blocks[0], [&out](const Block* b, ReachReason, Block*) { b->dump(out); }); + Instruction end(0, 0, OpFunctionEnd); + end.dump(out); + } + +protected: + Function(const Function&); + Function& operator=(Function&); + + Module& parent; + Instruction functionInstruction; + std::vector parameterInstructions; + std::vector blocks; + bool implicitThis; // true if this is a member function expecting to be passed a 'this' as the first argument +}; + +// +// SPIR-V IR Module. +// + +class Module { +public: + Module() {} + virtual ~Module() + { + // TODO delete things + } + + void addFunction(Function *fun) { functions.push_back(fun); } + + void mapInstruction(Instruction *instruction) + { + spv::Id resultId = instruction->getResultId(); + // map the instruction's result id + if (resultId >= idToInstruction.size()) + idToInstruction.resize(resultId + 16); + idToInstruction[resultId] = instruction; + } + + Instruction* getInstruction(Id id) const { return idToInstruction[id]; } + const std::vector& getFunctions() const { return functions; } + spv::Id getTypeId(Id resultId) const { + return idToInstruction[resultId] == nullptr ? NoType : idToInstruction[resultId]->getTypeId(); + } + StorageClass getStorageClass(Id typeId) const + { + assert(idToInstruction[typeId]->getOpCode() == spv::OpTypePointer); + return (StorageClass)idToInstruction[typeId]->getImmediateOperand(0); + } + + void dump(std::vector& out) const + { + for (int f = 0; f < (int)functions.size(); ++f) + functions[f]->dump(out); + } + +protected: + Module(const Module&); + std::vector functions; + + // map from result id to instruction having that result id + std::vector idToInstruction; + + // map from a result id to its type id +}; + +// +// Implementation (it's here due to circular type definitions). +// + +// Add both +// - the OpFunction instruction +// - all the OpFunctionParameter instructions +__inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, Module& parent) + : parent(parent), functionInstruction(id, resultType, OpFunction), implicitThis(false) +{ + // OpFunction + functionInstruction.addImmediateOperand(FunctionControlMaskNone); + functionInstruction.addIdOperand(functionType); + parent.mapInstruction(&functionInstruction); + parent.addFunction(this); + + // OpFunctionParameter + Instruction* typeInst = parent.getInstruction(functionType); + int numParams = typeInst->getNumOperands() - 1; + for (int p = 0; p < numParams; ++p) { + Instruction* param = new Instruction(firstParamId + p, typeInst->getIdOperand(p + 1), OpFunctionParameter); + parent.mapInstruction(param); + parameterInstructions.push_back(param); + } +} + +__inline void Function::addLocalVariable(std::unique_ptr inst) +{ + Instruction* raw_instruction = inst.get(); + blocks[0]->addLocalVariable(std::move(inst)); + parent.mapInstruction(raw_instruction); +} + +__inline Block::Block(Id id, Function& parent) : parent(parent), unreachable(false) +{ + instructions.push_back(std::unique_ptr(new Instruction(id, NoType, OpLabel))); + instructions.back()->setBlock(this); + parent.getParent().mapInstruction(instructions.back().get()); +} + +__inline void Block::addInstruction(std::unique_ptr inst) +{ + Instruction* raw_instruction = inst.get(); + instructions.push_back(std::move(inst)); + raw_instruction->setBlock(this); + if (raw_instruction->getResultId()) + parent.getParent().mapInstruction(raw_instruction); +} + +} // end spv namespace + +#endif // spvIR_H diff --git a/mac/include/spirv_cross/GLSL.std.450.h b/mac/include/spirv_cross/GLSL.std.450.h new file mode 100644 index 00000000..54cc00e9 --- /dev/null +++ b/mac/include/spirv_cross/GLSL.std.450.h @@ -0,0 +1,131 @@ +/* +** Copyright (c) 2014-2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +#ifndef GLSLstd450_H +#define GLSLstd450_H + +static const int GLSLstd450Version = 100; +static const int GLSLstd450Revision = 3; + +enum GLSLstd450 { + GLSLstd450Bad = 0, // Don't use + + GLSLstd450Round = 1, + GLSLstd450RoundEven = 2, + GLSLstd450Trunc = 3, + GLSLstd450FAbs = 4, + GLSLstd450SAbs = 5, + GLSLstd450FSign = 6, + GLSLstd450SSign = 7, + GLSLstd450Floor = 8, + GLSLstd450Ceil = 9, + GLSLstd450Fract = 10, + + GLSLstd450Radians = 11, + GLSLstd450Degrees = 12, + GLSLstd450Sin = 13, + GLSLstd450Cos = 14, + GLSLstd450Tan = 15, + GLSLstd450Asin = 16, + GLSLstd450Acos = 17, + GLSLstd450Atan = 18, + GLSLstd450Sinh = 19, + GLSLstd450Cosh = 20, + GLSLstd450Tanh = 21, + GLSLstd450Asinh = 22, + GLSLstd450Acosh = 23, + GLSLstd450Atanh = 24, + GLSLstd450Atan2 = 25, + + GLSLstd450Pow = 26, + GLSLstd450Exp = 27, + GLSLstd450Log = 28, + GLSLstd450Exp2 = 29, + GLSLstd450Log2 = 30, + GLSLstd450Sqrt = 31, + GLSLstd450InverseSqrt = 32, + + GLSLstd450Determinant = 33, + GLSLstd450MatrixInverse = 34, + + GLSLstd450Modf = 35, // second operand needs an OpVariable to write to + GLSLstd450ModfStruct = 36, // no OpVariable operand + GLSLstd450FMin = 37, + GLSLstd450UMin = 38, + GLSLstd450SMin = 39, + GLSLstd450FMax = 40, + GLSLstd450UMax = 41, + GLSLstd450SMax = 42, + GLSLstd450FClamp = 43, + GLSLstd450UClamp = 44, + GLSLstd450SClamp = 45, + GLSLstd450FMix = 46, + GLSLstd450IMix = 47, // Reserved + GLSLstd450Step = 48, + GLSLstd450SmoothStep = 49, + + GLSLstd450Fma = 50, + GLSLstd450Frexp = 51, // second operand needs an OpVariable to write to + GLSLstd450FrexpStruct = 52, // no OpVariable operand + GLSLstd450Ldexp = 53, + + GLSLstd450PackSnorm4x8 = 54, + GLSLstd450PackUnorm4x8 = 55, + GLSLstd450PackSnorm2x16 = 56, + GLSLstd450PackUnorm2x16 = 57, + GLSLstd450PackHalf2x16 = 58, + GLSLstd450PackDouble2x32 = 59, + GLSLstd450UnpackSnorm2x16 = 60, + GLSLstd450UnpackUnorm2x16 = 61, + GLSLstd450UnpackHalf2x16 = 62, + GLSLstd450UnpackSnorm4x8 = 63, + GLSLstd450UnpackUnorm4x8 = 64, + GLSLstd450UnpackDouble2x32 = 65, + + GLSLstd450Length = 66, + GLSLstd450Distance = 67, + GLSLstd450Cross = 68, + GLSLstd450Normalize = 69, + GLSLstd450FaceForward = 70, + GLSLstd450Reflect = 71, + GLSLstd450Refract = 72, + + GLSLstd450FindILsb = 73, + GLSLstd450FindSMsb = 74, + GLSLstd450FindUMsb = 75, + + GLSLstd450InterpolateAtCentroid = 76, + GLSLstd450InterpolateAtSample = 77, + GLSLstd450InterpolateAtOffset = 78, + + GLSLstd450NMin = 79, + GLSLstd450NMax = 80, + GLSLstd450NClamp = 81, + + GLSLstd450Count +}; + +#endif // #ifndef GLSLstd450_H diff --git a/mac/include/spirv_cross/spirv.h b/mac/include/spirv_cross/spirv.h new file mode 100644 index 00000000..92b34c38 --- /dev/null +++ b/mac/include/spirv_cross/spirv.h @@ -0,0 +1,2104 @@ +/* +** Copyright (c) 2014-2020 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and/or associated documentation files (the "Materials"), +** to deal in the Materials without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Materials, and to permit persons to whom the +** Materials are furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Materials. +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +** IN THE MATERIALS. +*/ + +/* +** This header is automatically generated by the same tool that creates +** the Binary Section of the SPIR-V specification. +*/ + +/* +** Enumeration tokens for SPIR-V, in various styles: +** C, C++, C++11, JSON, Lua, Python, C#, D +** +** - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL +** - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL +** - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL +** - Lua will use tables, e.g.: spv.SourceLanguage.GLSL +** - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] +** - C# will use enum classes in the Specification class located in the "Spv" namespace, +** e.g.: Spv.Specification.SourceLanguage.GLSL +** - D will have tokens under the "spv" module, e.g: spv.SourceLanguage.GLSL +** +** Some tokens act like mask values, which can be OR'd together, +** while others are mutually exclusive. The mask-like ones have +** "Mask" in their name, and a parallel enum that has the shift +** amount (1 << x) for each corresponding enumerant. +*/ + +#ifndef spirv_H +#define spirv_H + +typedef unsigned int SpvId; + +#define SPV_VERSION 0x10500 +#define SPV_REVISION 1 + +static const unsigned int SpvMagicNumber = 0x07230203; +static const unsigned int SpvVersion = 0x00010500; +static const unsigned int SpvRevision = 1; +static const unsigned int SpvOpCodeMask = 0xffff; +static const unsigned int SpvWordCountShift = 16; + +typedef enum SpvSourceLanguage_ { + SpvSourceLanguageUnknown = 0, + SpvSourceLanguageESSL = 1, + SpvSourceLanguageGLSL = 2, + SpvSourceLanguageOpenCL_C = 3, + SpvSourceLanguageOpenCL_CPP = 4, + SpvSourceLanguageHLSL = 5, + SpvSourceLanguageMax = 0x7fffffff, +} SpvSourceLanguage; + +typedef enum SpvExecutionModel_ { + SpvExecutionModelVertex = 0, + SpvExecutionModelTessellationControl = 1, + SpvExecutionModelTessellationEvaluation = 2, + SpvExecutionModelGeometry = 3, + SpvExecutionModelFragment = 4, + SpvExecutionModelGLCompute = 5, + SpvExecutionModelKernel = 6, + SpvExecutionModelTaskNV = 5267, + SpvExecutionModelMeshNV = 5268, + SpvExecutionModelRayGenerationKHR = 5313, + SpvExecutionModelRayGenerationNV = 5313, + SpvExecutionModelIntersectionKHR = 5314, + SpvExecutionModelIntersectionNV = 5314, + SpvExecutionModelAnyHitKHR = 5315, + SpvExecutionModelAnyHitNV = 5315, + SpvExecutionModelClosestHitKHR = 5316, + SpvExecutionModelClosestHitNV = 5316, + SpvExecutionModelMissKHR = 5317, + SpvExecutionModelMissNV = 5317, + SpvExecutionModelCallableKHR = 5318, + SpvExecutionModelCallableNV = 5318, + SpvExecutionModelMax = 0x7fffffff, +} SpvExecutionModel; + +typedef enum SpvAddressingModel_ { + SpvAddressingModelLogical = 0, + SpvAddressingModelPhysical32 = 1, + SpvAddressingModelPhysical64 = 2, + SpvAddressingModelPhysicalStorageBuffer64 = 5348, + SpvAddressingModelPhysicalStorageBuffer64EXT = 5348, + SpvAddressingModelMax = 0x7fffffff, +} SpvAddressingModel; + +typedef enum SpvMemoryModel_ { + SpvMemoryModelSimple = 0, + SpvMemoryModelGLSL450 = 1, + SpvMemoryModelOpenCL = 2, + SpvMemoryModelVulkan = 3, + SpvMemoryModelVulkanKHR = 3, + SpvMemoryModelMax = 0x7fffffff, +} SpvMemoryModel; + +typedef enum SpvExecutionMode_ { + SpvExecutionModeInvocations = 0, + SpvExecutionModeSpacingEqual = 1, + SpvExecutionModeSpacingFractionalEven = 2, + SpvExecutionModeSpacingFractionalOdd = 3, + SpvExecutionModeVertexOrderCw = 4, + SpvExecutionModeVertexOrderCcw = 5, + SpvExecutionModePixelCenterInteger = 6, + SpvExecutionModeOriginUpperLeft = 7, + SpvExecutionModeOriginLowerLeft = 8, + SpvExecutionModeEarlyFragmentTests = 9, + SpvExecutionModePointMode = 10, + SpvExecutionModeXfb = 11, + SpvExecutionModeDepthReplacing = 12, + SpvExecutionModeDepthGreater = 14, + SpvExecutionModeDepthLess = 15, + SpvExecutionModeDepthUnchanged = 16, + SpvExecutionModeLocalSize = 17, + SpvExecutionModeLocalSizeHint = 18, + SpvExecutionModeInputPoints = 19, + SpvExecutionModeInputLines = 20, + SpvExecutionModeInputLinesAdjacency = 21, + SpvExecutionModeTriangles = 22, + SpvExecutionModeInputTrianglesAdjacency = 23, + SpvExecutionModeQuads = 24, + SpvExecutionModeIsolines = 25, + SpvExecutionModeOutputVertices = 26, + SpvExecutionModeOutputPoints = 27, + SpvExecutionModeOutputLineStrip = 28, + SpvExecutionModeOutputTriangleStrip = 29, + SpvExecutionModeVecTypeHint = 30, + SpvExecutionModeContractionOff = 31, + SpvExecutionModeInitializer = 33, + SpvExecutionModeFinalizer = 34, + SpvExecutionModeSubgroupSize = 35, + SpvExecutionModeSubgroupsPerWorkgroup = 36, + SpvExecutionModeSubgroupsPerWorkgroupId = 37, + SpvExecutionModeLocalSizeId = 38, + SpvExecutionModeLocalSizeHintId = 39, + SpvExecutionModePostDepthCoverage = 4446, + SpvExecutionModeDenormPreserve = 4459, + SpvExecutionModeDenormFlushToZero = 4460, + SpvExecutionModeSignedZeroInfNanPreserve = 4461, + SpvExecutionModeRoundingModeRTE = 4462, + SpvExecutionModeRoundingModeRTZ = 4463, + SpvExecutionModeStencilRefReplacingEXT = 5027, + SpvExecutionModeOutputLinesNV = 5269, + SpvExecutionModeOutputPrimitivesNV = 5270, + SpvExecutionModeDerivativeGroupQuadsNV = 5289, + SpvExecutionModeDerivativeGroupLinearNV = 5290, + SpvExecutionModeOutputTrianglesNV = 5298, + SpvExecutionModePixelInterlockOrderedEXT = 5366, + SpvExecutionModePixelInterlockUnorderedEXT = 5367, + SpvExecutionModeSampleInterlockOrderedEXT = 5368, + SpvExecutionModeSampleInterlockUnorderedEXT = 5369, + SpvExecutionModeShadingRateInterlockOrderedEXT = 5370, + SpvExecutionModeShadingRateInterlockUnorderedEXT = 5371, + SpvExecutionModeMax = 0x7fffffff, +} SpvExecutionMode; + +typedef enum SpvStorageClass_ { + SpvStorageClassUniformConstant = 0, + SpvStorageClassInput = 1, + SpvStorageClassUniform = 2, + SpvStorageClassOutput = 3, + SpvStorageClassWorkgroup = 4, + SpvStorageClassCrossWorkgroup = 5, + SpvStorageClassPrivate = 6, + SpvStorageClassFunction = 7, + SpvStorageClassGeneric = 8, + SpvStorageClassPushConstant = 9, + SpvStorageClassAtomicCounter = 10, + SpvStorageClassImage = 11, + SpvStorageClassStorageBuffer = 12, + SpvStorageClassCallableDataKHR = 5328, + SpvStorageClassCallableDataNV = 5328, + SpvStorageClassIncomingCallableDataKHR = 5329, + SpvStorageClassIncomingCallableDataNV = 5329, + SpvStorageClassRayPayloadKHR = 5338, + SpvStorageClassRayPayloadNV = 5338, + SpvStorageClassHitAttributeKHR = 5339, + SpvStorageClassHitAttributeNV = 5339, + SpvStorageClassIncomingRayPayloadKHR = 5342, + SpvStorageClassIncomingRayPayloadNV = 5342, + SpvStorageClassShaderRecordBufferKHR = 5343, + SpvStorageClassShaderRecordBufferNV = 5343, + SpvStorageClassPhysicalStorageBuffer = 5349, + SpvStorageClassPhysicalStorageBufferEXT = 5349, + SpvStorageClassMax = 0x7fffffff, +} SpvStorageClass; + +typedef enum SpvDim_ { + SpvDim1D = 0, + SpvDim2D = 1, + SpvDim3D = 2, + SpvDimCube = 3, + SpvDimRect = 4, + SpvDimBuffer = 5, + SpvDimSubpassData = 6, + SpvDimMax = 0x7fffffff, +} SpvDim; + +typedef enum SpvSamplerAddressingMode_ { + SpvSamplerAddressingModeNone = 0, + SpvSamplerAddressingModeClampToEdge = 1, + SpvSamplerAddressingModeClamp = 2, + SpvSamplerAddressingModeRepeat = 3, + SpvSamplerAddressingModeRepeatMirrored = 4, + SpvSamplerAddressingModeMax = 0x7fffffff, +} SpvSamplerAddressingMode; + +typedef enum SpvSamplerFilterMode_ { + SpvSamplerFilterModeNearest = 0, + SpvSamplerFilterModeLinear = 1, + SpvSamplerFilterModeMax = 0x7fffffff, +} SpvSamplerFilterMode; + +typedef enum SpvImageFormat_ { + SpvImageFormatUnknown = 0, + SpvImageFormatRgba32f = 1, + SpvImageFormatRgba16f = 2, + SpvImageFormatR32f = 3, + SpvImageFormatRgba8 = 4, + SpvImageFormatRgba8Snorm = 5, + SpvImageFormatRg32f = 6, + SpvImageFormatRg16f = 7, + SpvImageFormatR11fG11fB10f = 8, + SpvImageFormatR16f = 9, + SpvImageFormatRgba16 = 10, + SpvImageFormatRgb10A2 = 11, + SpvImageFormatRg16 = 12, + SpvImageFormatRg8 = 13, + SpvImageFormatR16 = 14, + SpvImageFormatR8 = 15, + SpvImageFormatRgba16Snorm = 16, + SpvImageFormatRg16Snorm = 17, + SpvImageFormatRg8Snorm = 18, + SpvImageFormatR16Snorm = 19, + SpvImageFormatR8Snorm = 20, + SpvImageFormatRgba32i = 21, + SpvImageFormatRgba16i = 22, + SpvImageFormatRgba8i = 23, + SpvImageFormatR32i = 24, + SpvImageFormatRg32i = 25, + SpvImageFormatRg16i = 26, + SpvImageFormatRg8i = 27, + SpvImageFormatR16i = 28, + SpvImageFormatR8i = 29, + SpvImageFormatRgba32ui = 30, + SpvImageFormatRgba16ui = 31, + SpvImageFormatRgba8ui = 32, + SpvImageFormatR32ui = 33, + SpvImageFormatRgb10a2ui = 34, + SpvImageFormatRg32ui = 35, + SpvImageFormatRg16ui = 36, + SpvImageFormatRg8ui = 37, + SpvImageFormatR16ui = 38, + SpvImageFormatR8ui = 39, + SpvImageFormatMax = 0x7fffffff, +} SpvImageFormat; + +typedef enum SpvImageChannelOrder_ { + SpvImageChannelOrderR = 0, + SpvImageChannelOrderA = 1, + SpvImageChannelOrderRG = 2, + SpvImageChannelOrderRA = 3, + SpvImageChannelOrderRGB = 4, + SpvImageChannelOrderRGBA = 5, + SpvImageChannelOrderBGRA = 6, + SpvImageChannelOrderARGB = 7, + SpvImageChannelOrderIntensity = 8, + SpvImageChannelOrderLuminance = 9, + SpvImageChannelOrderRx = 10, + SpvImageChannelOrderRGx = 11, + SpvImageChannelOrderRGBx = 12, + SpvImageChannelOrderDepth = 13, + SpvImageChannelOrderDepthStencil = 14, + SpvImageChannelOrdersRGB = 15, + SpvImageChannelOrdersRGBx = 16, + SpvImageChannelOrdersRGBA = 17, + SpvImageChannelOrdersBGRA = 18, + SpvImageChannelOrderABGR = 19, + SpvImageChannelOrderMax = 0x7fffffff, +} SpvImageChannelOrder; + +typedef enum SpvImageChannelDataType_ { + SpvImageChannelDataTypeSnormInt8 = 0, + SpvImageChannelDataTypeSnormInt16 = 1, + SpvImageChannelDataTypeUnormInt8 = 2, + SpvImageChannelDataTypeUnormInt16 = 3, + SpvImageChannelDataTypeUnormShort565 = 4, + SpvImageChannelDataTypeUnormShort555 = 5, + SpvImageChannelDataTypeUnormInt101010 = 6, + SpvImageChannelDataTypeSignedInt8 = 7, + SpvImageChannelDataTypeSignedInt16 = 8, + SpvImageChannelDataTypeSignedInt32 = 9, + SpvImageChannelDataTypeUnsignedInt8 = 10, + SpvImageChannelDataTypeUnsignedInt16 = 11, + SpvImageChannelDataTypeUnsignedInt32 = 12, + SpvImageChannelDataTypeHalfFloat = 13, + SpvImageChannelDataTypeFloat = 14, + SpvImageChannelDataTypeUnormInt24 = 15, + SpvImageChannelDataTypeUnormInt101010_2 = 16, + SpvImageChannelDataTypeMax = 0x7fffffff, +} SpvImageChannelDataType; + +typedef enum SpvImageOperandsShift_ { + SpvImageOperandsBiasShift = 0, + SpvImageOperandsLodShift = 1, + SpvImageOperandsGradShift = 2, + SpvImageOperandsConstOffsetShift = 3, + SpvImageOperandsOffsetShift = 4, + SpvImageOperandsConstOffsetsShift = 5, + SpvImageOperandsSampleShift = 6, + SpvImageOperandsMinLodShift = 7, + SpvImageOperandsMakeTexelAvailableShift = 8, + SpvImageOperandsMakeTexelAvailableKHRShift = 8, + SpvImageOperandsMakeTexelVisibleShift = 9, + SpvImageOperandsMakeTexelVisibleKHRShift = 9, + SpvImageOperandsNonPrivateTexelShift = 10, + SpvImageOperandsNonPrivateTexelKHRShift = 10, + SpvImageOperandsVolatileTexelShift = 11, + SpvImageOperandsVolatileTexelKHRShift = 11, + SpvImageOperandsSignExtendShift = 12, + SpvImageOperandsZeroExtendShift = 13, + SpvImageOperandsMax = 0x7fffffff, +} SpvImageOperandsShift; + +typedef enum SpvImageOperandsMask_ { + SpvImageOperandsMaskNone = 0, + SpvImageOperandsBiasMask = 0x00000001, + SpvImageOperandsLodMask = 0x00000002, + SpvImageOperandsGradMask = 0x00000004, + SpvImageOperandsConstOffsetMask = 0x00000008, + SpvImageOperandsOffsetMask = 0x00000010, + SpvImageOperandsConstOffsetsMask = 0x00000020, + SpvImageOperandsSampleMask = 0x00000040, + SpvImageOperandsMinLodMask = 0x00000080, + SpvImageOperandsMakeTexelAvailableMask = 0x00000100, + SpvImageOperandsMakeTexelAvailableKHRMask = 0x00000100, + SpvImageOperandsMakeTexelVisibleMask = 0x00000200, + SpvImageOperandsMakeTexelVisibleKHRMask = 0x00000200, + SpvImageOperandsNonPrivateTexelMask = 0x00000400, + SpvImageOperandsNonPrivateTexelKHRMask = 0x00000400, + SpvImageOperandsVolatileTexelMask = 0x00000800, + SpvImageOperandsVolatileTexelKHRMask = 0x00000800, + SpvImageOperandsSignExtendMask = 0x00001000, + SpvImageOperandsZeroExtendMask = 0x00002000, +} SpvImageOperandsMask; + +typedef enum SpvFPFastMathModeShift_ { + SpvFPFastMathModeNotNaNShift = 0, + SpvFPFastMathModeNotInfShift = 1, + SpvFPFastMathModeNSZShift = 2, + SpvFPFastMathModeAllowRecipShift = 3, + SpvFPFastMathModeFastShift = 4, + SpvFPFastMathModeMax = 0x7fffffff, +} SpvFPFastMathModeShift; + +typedef enum SpvFPFastMathModeMask_ { + SpvFPFastMathModeMaskNone = 0, + SpvFPFastMathModeNotNaNMask = 0x00000001, + SpvFPFastMathModeNotInfMask = 0x00000002, + SpvFPFastMathModeNSZMask = 0x00000004, + SpvFPFastMathModeAllowRecipMask = 0x00000008, + SpvFPFastMathModeFastMask = 0x00000010, +} SpvFPFastMathModeMask; + +typedef enum SpvFPRoundingMode_ { + SpvFPRoundingModeRTE = 0, + SpvFPRoundingModeRTZ = 1, + SpvFPRoundingModeRTP = 2, + SpvFPRoundingModeRTN = 3, + SpvFPRoundingModeMax = 0x7fffffff, +} SpvFPRoundingMode; + +typedef enum SpvLinkageType_ { + SpvLinkageTypeExport = 0, + SpvLinkageTypeImport = 1, + SpvLinkageTypeMax = 0x7fffffff, +} SpvLinkageType; + +typedef enum SpvAccessQualifier_ { + SpvAccessQualifierReadOnly = 0, + SpvAccessQualifierWriteOnly = 1, + SpvAccessQualifierReadWrite = 2, + SpvAccessQualifierMax = 0x7fffffff, +} SpvAccessQualifier; + +typedef enum SpvFunctionParameterAttribute_ { + SpvFunctionParameterAttributeZext = 0, + SpvFunctionParameterAttributeSext = 1, + SpvFunctionParameterAttributeByVal = 2, + SpvFunctionParameterAttributeSret = 3, + SpvFunctionParameterAttributeNoAlias = 4, + SpvFunctionParameterAttributeNoCapture = 5, + SpvFunctionParameterAttributeNoWrite = 6, + SpvFunctionParameterAttributeNoReadWrite = 7, + SpvFunctionParameterAttributeMax = 0x7fffffff, +} SpvFunctionParameterAttribute; + +typedef enum SpvDecoration_ { + SpvDecorationRelaxedPrecision = 0, + SpvDecorationSpecId = 1, + SpvDecorationBlock = 2, + SpvDecorationBufferBlock = 3, + SpvDecorationRowMajor = 4, + SpvDecorationColMajor = 5, + SpvDecorationArrayStride = 6, + SpvDecorationMatrixStride = 7, + SpvDecorationGLSLShared = 8, + SpvDecorationGLSLPacked = 9, + SpvDecorationCPacked = 10, + SpvDecorationBuiltIn = 11, + SpvDecorationNoPerspective = 13, + SpvDecorationFlat = 14, + SpvDecorationPatch = 15, + SpvDecorationCentroid = 16, + SpvDecorationSample = 17, + SpvDecorationInvariant = 18, + SpvDecorationRestrict = 19, + SpvDecorationAliased = 20, + SpvDecorationVolatile = 21, + SpvDecorationConstant = 22, + SpvDecorationCoherent = 23, + SpvDecorationNonWritable = 24, + SpvDecorationNonReadable = 25, + SpvDecorationUniform = 26, + SpvDecorationUniformId = 27, + SpvDecorationSaturatedConversion = 28, + SpvDecorationStream = 29, + SpvDecorationLocation = 30, + SpvDecorationComponent = 31, + SpvDecorationIndex = 32, + SpvDecorationBinding = 33, + SpvDecorationDescriptorSet = 34, + SpvDecorationOffset = 35, + SpvDecorationXfbBuffer = 36, + SpvDecorationXfbStride = 37, + SpvDecorationFuncParamAttr = 38, + SpvDecorationFPRoundingMode = 39, + SpvDecorationFPFastMathMode = 40, + SpvDecorationLinkageAttributes = 41, + SpvDecorationNoContraction = 42, + SpvDecorationInputAttachmentIndex = 43, + SpvDecorationAlignment = 44, + SpvDecorationMaxByteOffset = 45, + SpvDecorationAlignmentId = 46, + SpvDecorationMaxByteOffsetId = 47, + SpvDecorationNoSignedWrap = 4469, + SpvDecorationNoUnsignedWrap = 4470, + SpvDecorationExplicitInterpAMD = 4999, + SpvDecorationOverrideCoverageNV = 5248, + SpvDecorationPassthroughNV = 5250, + SpvDecorationViewportRelativeNV = 5252, + SpvDecorationSecondaryViewportRelativeNV = 5256, + SpvDecorationPerPrimitiveNV = 5271, + SpvDecorationPerViewNV = 5272, + SpvDecorationPerTaskNV = 5273, + SpvDecorationPerVertexNV = 5285, + SpvDecorationNonUniform = 5300, + SpvDecorationNonUniformEXT = 5300, + SpvDecorationRestrictPointer = 5355, + SpvDecorationRestrictPointerEXT = 5355, + SpvDecorationAliasedPointer = 5356, + SpvDecorationAliasedPointerEXT = 5356, + SpvDecorationCounterBuffer = 5634, + SpvDecorationHlslCounterBufferGOOGLE = 5634, + SpvDecorationHlslSemanticGOOGLE = 5635, + SpvDecorationUserSemantic = 5635, + SpvDecorationUserTypeGOOGLE = 5636, + SpvDecorationMax = 0x7fffffff, +} SpvDecoration; + +typedef enum SpvBuiltIn_ { + SpvBuiltInPosition = 0, + SpvBuiltInPointSize = 1, + SpvBuiltInClipDistance = 3, + SpvBuiltInCullDistance = 4, + SpvBuiltInVertexId = 5, + SpvBuiltInInstanceId = 6, + SpvBuiltInPrimitiveId = 7, + SpvBuiltInInvocationId = 8, + SpvBuiltInLayer = 9, + SpvBuiltInViewportIndex = 10, + SpvBuiltInTessLevelOuter = 11, + SpvBuiltInTessLevelInner = 12, + SpvBuiltInTessCoord = 13, + SpvBuiltInPatchVertices = 14, + SpvBuiltInFragCoord = 15, + SpvBuiltInPointCoord = 16, + SpvBuiltInFrontFacing = 17, + SpvBuiltInSampleId = 18, + SpvBuiltInSamplePosition = 19, + SpvBuiltInSampleMask = 20, + SpvBuiltInFragDepth = 22, + SpvBuiltInHelperInvocation = 23, + SpvBuiltInNumWorkgroups = 24, + SpvBuiltInWorkgroupSize = 25, + SpvBuiltInWorkgroupId = 26, + SpvBuiltInLocalInvocationId = 27, + SpvBuiltInGlobalInvocationId = 28, + SpvBuiltInLocalInvocationIndex = 29, + SpvBuiltInWorkDim = 30, + SpvBuiltInGlobalSize = 31, + SpvBuiltInEnqueuedWorkgroupSize = 32, + SpvBuiltInGlobalOffset = 33, + SpvBuiltInGlobalLinearId = 34, + SpvBuiltInSubgroupSize = 36, + SpvBuiltInSubgroupMaxSize = 37, + SpvBuiltInNumSubgroups = 38, + SpvBuiltInNumEnqueuedSubgroups = 39, + SpvBuiltInSubgroupId = 40, + SpvBuiltInSubgroupLocalInvocationId = 41, + SpvBuiltInVertexIndex = 42, + SpvBuiltInInstanceIndex = 43, + SpvBuiltInSubgroupEqMask = 4416, + SpvBuiltInSubgroupEqMaskKHR = 4416, + SpvBuiltInSubgroupGeMask = 4417, + SpvBuiltInSubgroupGeMaskKHR = 4417, + SpvBuiltInSubgroupGtMask = 4418, + SpvBuiltInSubgroupGtMaskKHR = 4418, + SpvBuiltInSubgroupLeMask = 4419, + SpvBuiltInSubgroupLeMaskKHR = 4419, + SpvBuiltInSubgroupLtMask = 4420, + SpvBuiltInSubgroupLtMaskKHR = 4420, + SpvBuiltInBaseVertex = 4424, + SpvBuiltInBaseInstance = 4425, + SpvBuiltInDrawIndex = 4426, + SpvBuiltInDeviceIndex = 4438, + SpvBuiltInViewIndex = 4440, + SpvBuiltInBaryCoordNoPerspAMD = 4992, + SpvBuiltInBaryCoordNoPerspCentroidAMD = 4993, + SpvBuiltInBaryCoordNoPerspSampleAMD = 4994, + SpvBuiltInBaryCoordSmoothAMD = 4995, + SpvBuiltInBaryCoordSmoothCentroidAMD = 4996, + SpvBuiltInBaryCoordSmoothSampleAMD = 4997, + SpvBuiltInBaryCoordPullModelAMD = 4998, + SpvBuiltInFragStencilRefEXT = 5014, + SpvBuiltInViewportMaskNV = 5253, + SpvBuiltInSecondaryPositionNV = 5257, + SpvBuiltInSecondaryViewportMaskNV = 5258, + SpvBuiltInPositionPerViewNV = 5261, + SpvBuiltInViewportMaskPerViewNV = 5262, + SpvBuiltInFullyCoveredEXT = 5264, + SpvBuiltInTaskCountNV = 5274, + SpvBuiltInPrimitiveCountNV = 5275, + SpvBuiltInPrimitiveIndicesNV = 5276, + SpvBuiltInClipDistancePerViewNV = 5277, + SpvBuiltInCullDistancePerViewNV = 5278, + SpvBuiltInLayerPerViewNV = 5279, + SpvBuiltInMeshViewCountNV = 5280, + SpvBuiltInMeshViewIndicesNV = 5281, + SpvBuiltInBaryCoordNV = 5286, + SpvBuiltInBaryCoordNoPerspNV = 5287, + SpvBuiltInFragSizeEXT = 5292, + SpvBuiltInFragmentSizeNV = 5292, + SpvBuiltInFragInvocationCountEXT = 5293, + SpvBuiltInInvocationsPerPixelNV = 5293, + SpvBuiltInLaunchIdKHR = 5319, + SpvBuiltInLaunchIdNV = 5319, + SpvBuiltInLaunchSizeKHR = 5320, + SpvBuiltInLaunchSizeNV = 5320, + SpvBuiltInWorldRayOriginKHR = 5321, + SpvBuiltInWorldRayOriginNV = 5321, + SpvBuiltInWorldRayDirectionKHR = 5322, + SpvBuiltInWorldRayDirectionNV = 5322, + SpvBuiltInObjectRayOriginKHR = 5323, + SpvBuiltInObjectRayOriginNV = 5323, + SpvBuiltInObjectRayDirectionKHR = 5324, + SpvBuiltInObjectRayDirectionNV = 5324, + SpvBuiltInRayTminKHR = 5325, + SpvBuiltInRayTminNV = 5325, + SpvBuiltInRayTmaxKHR = 5326, + SpvBuiltInRayTmaxNV = 5326, + SpvBuiltInInstanceCustomIndexKHR = 5327, + SpvBuiltInInstanceCustomIndexNV = 5327, + SpvBuiltInObjectToWorldKHR = 5330, + SpvBuiltInObjectToWorldNV = 5330, + SpvBuiltInWorldToObjectKHR = 5331, + SpvBuiltInWorldToObjectNV = 5331, + SpvBuiltInHitTKHR = 5332, + SpvBuiltInHitTNV = 5332, + SpvBuiltInHitKindKHR = 5333, + SpvBuiltInHitKindNV = 5333, + SpvBuiltInIncomingRayFlagsKHR = 5351, + SpvBuiltInIncomingRayFlagsNV = 5351, + SpvBuiltInRayGeometryIndexKHR = 5352, + SpvBuiltInWarpsPerSMNV = 5374, + SpvBuiltInSMCountNV = 5375, + SpvBuiltInWarpIDNV = 5376, + SpvBuiltInSMIDNV = 5377, + SpvBuiltInMax = 0x7fffffff, +} SpvBuiltIn; + +typedef enum SpvSelectionControlShift_ { + SpvSelectionControlFlattenShift = 0, + SpvSelectionControlDontFlattenShift = 1, + SpvSelectionControlMax = 0x7fffffff, +} SpvSelectionControlShift; + +typedef enum SpvSelectionControlMask_ { + SpvSelectionControlMaskNone = 0, + SpvSelectionControlFlattenMask = 0x00000001, + SpvSelectionControlDontFlattenMask = 0x00000002, +} SpvSelectionControlMask; + +typedef enum SpvLoopControlShift_ { + SpvLoopControlUnrollShift = 0, + SpvLoopControlDontUnrollShift = 1, + SpvLoopControlDependencyInfiniteShift = 2, + SpvLoopControlDependencyLengthShift = 3, + SpvLoopControlMinIterationsShift = 4, + SpvLoopControlMaxIterationsShift = 5, + SpvLoopControlIterationMultipleShift = 6, + SpvLoopControlPeelCountShift = 7, + SpvLoopControlPartialCountShift = 8, + SpvLoopControlMax = 0x7fffffff, +} SpvLoopControlShift; + +typedef enum SpvLoopControlMask_ { + SpvLoopControlMaskNone = 0, + SpvLoopControlUnrollMask = 0x00000001, + SpvLoopControlDontUnrollMask = 0x00000002, + SpvLoopControlDependencyInfiniteMask = 0x00000004, + SpvLoopControlDependencyLengthMask = 0x00000008, + SpvLoopControlMinIterationsMask = 0x00000010, + SpvLoopControlMaxIterationsMask = 0x00000020, + SpvLoopControlIterationMultipleMask = 0x00000040, + SpvLoopControlPeelCountMask = 0x00000080, + SpvLoopControlPartialCountMask = 0x00000100, +} SpvLoopControlMask; + +typedef enum SpvFunctionControlShift_ { + SpvFunctionControlInlineShift = 0, + SpvFunctionControlDontInlineShift = 1, + SpvFunctionControlPureShift = 2, + SpvFunctionControlConstShift = 3, + SpvFunctionControlMax = 0x7fffffff, +} SpvFunctionControlShift; + +typedef enum SpvFunctionControlMask_ { + SpvFunctionControlMaskNone = 0, + SpvFunctionControlInlineMask = 0x00000001, + SpvFunctionControlDontInlineMask = 0x00000002, + SpvFunctionControlPureMask = 0x00000004, + SpvFunctionControlConstMask = 0x00000008, +} SpvFunctionControlMask; + +typedef enum SpvMemorySemanticsShift_ { + SpvMemorySemanticsAcquireShift = 1, + SpvMemorySemanticsReleaseShift = 2, + SpvMemorySemanticsAcquireReleaseShift = 3, + SpvMemorySemanticsSequentiallyConsistentShift = 4, + SpvMemorySemanticsUniformMemoryShift = 6, + SpvMemorySemanticsSubgroupMemoryShift = 7, + SpvMemorySemanticsWorkgroupMemoryShift = 8, + SpvMemorySemanticsCrossWorkgroupMemoryShift = 9, + SpvMemorySemanticsAtomicCounterMemoryShift = 10, + SpvMemorySemanticsImageMemoryShift = 11, + SpvMemorySemanticsOutputMemoryShift = 12, + SpvMemorySemanticsOutputMemoryKHRShift = 12, + SpvMemorySemanticsMakeAvailableShift = 13, + SpvMemorySemanticsMakeAvailableKHRShift = 13, + SpvMemorySemanticsMakeVisibleShift = 14, + SpvMemorySemanticsMakeVisibleKHRShift = 14, + SpvMemorySemanticsVolatileShift = 15, + SpvMemorySemanticsMax = 0x7fffffff, +} SpvMemorySemanticsShift; + +typedef enum SpvMemorySemanticsMask_ { + SpvMemorySemanticsMaskNone = 0, + SpvMemorySemanticsAcquireMask = 0x00000002, + SpvMemorySemanticsReleaseMask = 0x00000004, + SpvMemorySemanticsAcquireReleaseMask = 0x00000008, + SpvMemorySemanticsSequentiallyConsistentMask = 0x00000010, + SpvMemorySemanticsUniformMemoryMask = 0x00000040, + SpvMemorySemanticsSubgroupMemoryMask = 0x00000080, + SpvMemorySemanticsWorkgroupMemoryMask = 0x00000100, + SpvMemorySemanticsCrossWorkgroupMemoryMask = 0x00000200, + SpvMemorySemanticsAtomicCounterMemoryMask = 0x00000400, + SpvMemorySemanticsImageMemoryMask = 0x00000800, + SpvMemorySemanticsOutputMemoryMask = 0x00001000, + SpvMemorySemanticsOutputMemoryKHRMask = 0x00001000, + SpvMemorySemanticsMakeAvailableMask = 0x00002000, + SpvMemorySemanticsMakeAvailableKHRMask = 0x00002000, + SpvMemorySemanticsMakeVisibleMask = 0x00004000, + SpvMemorySemanticsMakeVisibleKHRMask = 0x00004000, + SpvMemorySemanticsVolatileMask = 0x00008000, +} SpvMemorySemanticsMask; + +typedef enum SpvMemoryAccessShift_ { + SpvMemoryAccessVolatileShift = 0, + SpvMemoryAccessAlignedShift = 1, + SpvMemoryAccessNontemporalShift = 2, + SpvMemoryAccessMakePointerAvailableShift = 3, + SpvMemoryAccessMakePointerAvailableKHRShift = 3, + SpvMemoryAccessMakePointerVisibleShift = 4, + SpvMemoryAccessMakePointerVisibleKHRShift = 4, + SpvMemoryAccessNonPrivatePointerShift = 5, + SpvMemoryAccessNonPrivatePointerKHRShift = 5, + SpvMemoryAccessMax = 0x7fffffff, +} SpvMemoryAccessShift; + +typedef enum SpvMemoryAccessMask_ { + SpvMemoryAccessMaskNone = 0, + SpvMemoryAccessVolatileMask = 0x00000001, + SpvMemoryAccessAlignedMask = 0x00000002, + SpvMemoryAccessNontemporalMask = 0x00000004, + SpvMemoryAccessMakePointerAvailableMask = 0x00000008, + SpvMemoryAccessMakePointerAvailableKHRMask = 0x00000008, + SpvMemoryAccessMakePointerVisibleMask = 0x00000010, + SpvMemoryAccessMakePointerVisibleKHRMask = 0x00000010, + SpvMemoryAccessNonPrivatePointerMask = 0x00000020, + SpvMemoryAccessNonPrivatePointerKHRMask = 0x00000020, +} SpvMemoryAccessMask; + +typedef enum SpvScope_ { + SpvScopeCrossDevice = 0, + SpvScopeDevice = 1, + SpvScopeWorkgroup = 2, + SpvScopeSubgroup = 3, + SpvScopeInvocation = 4, + SpvScopeQueueFamily = 5, + SpvScopeQueueFamilyKHR = 5, + SpvScopeShaderCallKHR = 6, + SpvScopeMax = 0x7fffffff, +} SpvScope; + +typedef enum SpvGroupOperation_ { + SpvGroupOperationReduce = 0, + SpvGroupOperationInclusiveScan = 1, + SpvGroupOperationExclusiveScan = 2, + SpvGroupOperationClusteredReduce = 3, + SpvGroupOperationPartitionedReduceNV = 6, + SpvGroupOperationPartitionedInclusiveScanNV = 7, + SpvGroupOperationPartitionedExclusiveScanNV = 8, + SpvGroupOperationMax = 0x7fffffff, +} SpvGroupOperation; + +typedef enum SpvKernelEnqueueFlags_ { + SpvKernelEnqueueFlagsNoWait = 0, + SpvKernelEnqueueFlagsWaitKernel = 1, + SpvKernelEnqueueFlagsWaitWorkGroup = 2, + SpvKernelEnqueueFlagsMax = 0x7fffffff, +} SpvKernelEnqueueFlags; + +typedef enum SpvKernelProfilingInfoShift_ { + SpvKernelProfilingInfoCmdExecTimeShift = 0, + SpvKernelProfilingInfoMax = 0x7fffffff, +} SpvKernelProfilingInfoShift; + +typedef enum SpvKernelProfilingInfoMask_ { + SpvKernelProfilingInfoMaskNone = 0, + SpvKernelProfilingInfoCmdExecTimeMask = 0x00000001, +} SpvKernelProfilingInfoMask; + +typedef enum SpvCapability_ { + SpvCapabilityMatrix = 0, + SpvCapabilityShader = 1, + SpvCapabilityGeometry = 2, + SpvCapabilityTessellation = 3, + SpvCapabilityAddresses = 4, + SpvCapabilityLinkage = 5, + SpvCapabilityKernel = 6, + SpvCapabilityVector16 = 7, + SpvCapabilityFloat16Buffer = 8, + SpvCapabilityFloat16 = 9, + SpvCapabilityFloat64 = 10, + SpvCapabilityInt64 = 11, + SpvCapabilityInt64Atomics = 12, + SpvCapabilityImageBasic = 13, + SpvCapabilityImageReadWrite = 14, + SpvCapabilityImageMipmap = 15, + SpvCapabilityPipes = 17, + SpvCapabilityGroups = 18, + SpvCapabilityDeviceEnqueue = 19, + SpvCapabilityLiteralSampler = 20, + SpvCapabilityAtomicStorage = 21, + SpvCapabilityInt16 = 22, + SpvCapabilityTessellationPointSize = 23, + SpvCapabilityGeometryPointSize = 24, + SpvCapabilityImageGatherExtended = 25, + SpvCapabilityStorageImageMultisample = 27, + SpvCapabilityUniformBufferArrayDynamicIndexing = 28, + SpvCapabilitySampledImageArrayDynamicIndexing = 29, + SpvCapabilityStorageBufferArrayDynamicIndexing = 30, + SpvCapabilityStorageImageArrayDynamicIndexing = 31, + SpvCapabilityClipDistance = 32, + SpvCapabilityCullDistance = 33, + SpvCapabilityImageCubeArray = 34, + SpvCapabilitySampleRateShading = 35, + SpvCapabilityImageRect = 36, + SpvCapabilitySampledRect = 37, + SpvCapabilityGenericPointer = 38, + SpvCapabilityInt8 = 39, + SpvCapabilityInputAttachment = 40, + SpvCapabilitySparseResidency = 41, + SpvCapabilityMinLod = 42, + SpvCapabilitySampled1D = 43, + SpvCapabilityImage1D = 44, + SpvCapabilitySampledCubeArray = 45, + SpvCapabilitySampledBuffer = 46, + SpvCapabilityImageBuffer = 47, + SpvCapabilityImageMSArray = 48, + SpvCapabilityStorageImageExtendedFormats = 49, + SpvCapabilityImageQuery = 50, + SpvCapabilityDerivativeControl = 51, + SpvCapabilityInterpolationFunction = 52, + SpvCapabilityTransformFeedback = 53, + SpvCapabilityGeometryStreams = 54, + SpvCapabilityStorageImageReadWithoutFormat = 55, + SpvCapabilityStorageImageWriteWithoutFormat = 56, + SpvCapabilityMultiViewport = 57, + SpvCapabilitySubgroupDispatch = 58, + SpvCapabilityNamedBarrier = 59, + SpvCapabilityPipeStorage = 60, + SpvCapabilityGroupNonUniform = 61, + SpvCapabilityGroupNonUniformVote = 62, + SpvCapabilityGroupNonUniformArithmetic = 63, + SpvCapabilityGroupNonUniformBallot = 64, + SpvCapabilityGroupNonUniformShuffle = 65, + SpvCapabilityGroupNonUniformShuffleRelative = 66, + SpvCapabilityGroupNonUniformClustered = 67, + SpvCapabilityGroupNonUniformQuad = 68, + SpvCapabilityShaderLayer = 69, + SpvCapabilityShaderViewportIndex = 70, + SpvCapabilitySubgroupBallotKHR = 4423, + SpvCapabilityDrawParameters = 4427, + SpvCapabilitySubgroupVoteKHR = 4431, + SpvCapabilityStorageBuffer16BitAccess = 4433, + SpvCapabilityStorageUniformBufferBlock16 = 4433, + SpvCapabilityStorageUniform16 = 4434, + SpvCapabilityUniformAndStorageBuffer16BitAccess = 4434, + SpvCapabilityStoragePushConstant16 = 4435, + SpvCapabilityStorageInputOutput16 = 4436, + SpvCapabilityDeviceGroup = 4437, + SpvCapabilityMultiView = 4439, + SpvCapabilityVariablePointersStorageBuffer = 4441, + SpvCapabilityVariablePointers = 4442, + SpvCapabilityAtomicStorageOps = 4445, + SpvCapabilitySampleMaskPostDepthCoverage = 4447, + SpvCapabilityStorageBuffer8BitAccess = 4448, + SpvCapabilityUniformAndStorageBuffer8BitAccess = 4449, + SpvCapabilityStoragePushConstant8 = 4450, + SpvCapabilityDenormPreserve = 4464, + SpvCapabilityDenormFlushToZero = 4465, + SpvCapabilitySignedZeroInfNanPreserve = 4466, + SpvCapabilityRoundingModeRTE = 4467, + SpvCapabilityRoundingModeRTZ = 4468, + SpvCapabilityRayQueryProvisionalKHR = 4471, + SpvCapabilityRayTraversalPrimitiveCullingProvisionalKHR = 4478, + SpvCapabilityFloat16ImageAMD = 5008, + SpvCapabilityImageGatherBiasLodAMD = 5009, + SpvCapabilityFragmentMaskAMD = 5010, + SpvCapabilityStencilExportEXT = 5013, + SpvCapabilityImageReadWriteLodAMD = 5015, + SpvCapabilityShaderClockKHR = 5055, + SpvCapabilitySampleMaskOverrideCoverageNV = 5249, + SpvCapabilityGeometryShaderPassthroughNV = 5251, + SpvCapabilityShaderViewportIndexLayerEXT = 5254, + SpvCapabilityShaderViewportIndexLayerNV = 5254, + SpvCapabilityShaderViewportMaskNV = 5255, + SpvCapabilityShaderStereoViewNV = 5259, + SpvCapabilityPerViewAttributesNV = 5260, + SpvCapabilityFragmentFullyCoveredEXT = 5265, + SpvCapabilityMeshShadingNV = 5266, + SpvCapabilityImageFootprintNV = 5282, + SpvCapabilityFragmentBarycentricNV = 5284, + SpvCapabilityComputeDerivativeGroupQuadsNV = 5288, + SpvCapabilityFragmentDensityEXT = 5291, + SpvCapabilityShadingRateNV = 5291, + SpvCapabilityGroupNonUniformPartitionedNV = 5297, + SpvCapabilityShaderNonUniform = 5301, + SpvCapabilityShaderNonUniformEXT = 5301, + SpvCapabilityRuntimeDescriptorArray = 5302, + SpvCapabilityRuntimeDescriptorArrayEXT = 5302, + SpvCapabilityInputAttachmentArrayDynamicIndexing = 5303, + SpvCapabilityInputAttachmentArrayDynamicIndexingEXT = 5303, + SpvCapabilityUniformTexelBufferArrayDynamicIndexing = 5304, + SpvCapabilityUniformTexelBufferArrayDynamicIndexingEXT = 5304, + SpvCapabilityStorageTexelBufferArrayDynamicIndexing = 5305, + SpvCapabilityStorageTexelBufferArrayDynamicIndexingEXT = 5305, + SpvCapabilityUniformBufferArrayNonUniformIndexing = 5306, + SpvCapabilityUniformBufferArrayNonUniformIndexingEXT = 5306, + SpvCapabilitySampledImageArrayNonUniformIndexing = 5307, + SpvCapabilitySampledImageArrayNonUniformIndexingEXT = 5307, + SpvCapabilityStorageBufferArrayNonUniformIndexing = 5308, + SpvCapabilityStorageBufferArrayNonUniformIndexingEXT = 5308, + SpvCapabilityStorageImageArrayNonUniformIndexing = 5309, + SpvCapabilityStorageImageArrayNonUniformIndexingEXT = 5309, + SpvCapabilityInputAttachmentArrayNonUniformIndexing = 5310, + SpvCapabilityInputAttachmentArrayNonUniformIndexingEXT = 5310, + SpvCapabilityUniformTexelBufferArrayNonUniformIndexing = 5311, + SpvCapabilityUniformTexelBufferArrayNonUniformIndexingEXT = 5311, + SpvCapabilityStorageTexelBufferArrayNonUniformIndexing = 5312, + SpvCapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312, + SpvCapabilityRayTracingNV = 5340, + SpvCapabilityVulkanMemoryModel = 5345, + SpvCapabilityVulkanMemoryModelKHR = 5345, + SpvCapabilityVulkanMemoryModelDeviceScope = 5346, + SpvCapabilityVulkanMemoryModelDeviceScopeKHR = 5346, + SpvCapabilityPhysicalStorageBufferAddresses = 5347, + SpvCapabilityPhysicalStorageBufferAddressesEXT = 5347, + SpvCapabilityComputeDerivativeGroupLinearNV = 5350, + SpvCapabilityRayTracingProvisionalKHR = 5353, + SpvCapabilityCooperativeMatrixNV = 5357, + SpvCapabilityFragmentShaderSampleInterlockEXT = 5363, + SpvCapabilityFragmentShaderShadingRateInterlockEXT = 5372, + SpvCapabilityShaderSMBuiltinsNV = 5373, + SpvCapabilityFragmentShaderPixelInterlockEXT = 5378, + SpvCapabilityDemoteToHelperInvocationEXT = 5379, + SpvCapabilitySubgroupShuffleINTEL = 5568, + SpvCapabilitySubgroupBufferBlockIOINTEL = 5569, + SpvCapabilitySubgroupImageBlockIOINTEL = 5570, + SpvCapabilitySubgroupImageMediaBlockIOINTEL = 5579, + SpvCapabilityIntegerFunctions2INTEL = 5584, + SpvCapabilitySubgroupAvcMotionEstimationINTEL = 5696, + SpvCapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697, + SpvCapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698, + SpvCapabilityMax = 0x7fffffff, +} SpvCapability; + +typedef enum SpvRayFlagsShift_ { + SpvRayFlagsOpaqueKHRShift = 0, + SpvRayFlagsNoOpaqueKHRShift = 1, + SpvRayFlagsTerminateOnFirstHitKHRShift = 2, + SpvRayFlagsSkipClosestHitShaderKHRShift = 3, + SpvRayFlagsCullBackFacingTrianglesKHRShift = 4, + SpvRayFlagsCullFrontFacingTrianglesKHRShift = 5, + SpvRayFlagsCullOpaqueKHRShift = 6, + SpvRayFlagsCullNoOpaqueKHRShift = 7, + SpvRayFlagsSkipTrianglesKHRShift = 8, + SpvRayFlagsSkipAABBsKHRShift = 9, + SpvRayFlagsMax = 0x7fffffff, +} SpvRayFlagsShift; + +typedef enum SpvRayFlagsMask_ { + SpvRayFlagsMaskNone = 0, + SpvRayFlagsOpaqueKHRMask = 0x00000001, + SpvRayFlagsNoOpaqueKHRMask = 0x00000002, + SpvRayFlagsTerminateOnFirstHitKHRMask = 0x00000004, + SpvRayFlagsSkipClosestHitShaderKHRMask = 0x00000008, + SpvRayFlagsCullBackFacingTrianglesKHRMask = 0x00000010, + SpvRayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020, + SpvRayFlagsCullOpaqueKHRMask = 0x00000040, + SpvRayFlagsCullNoOpaqueKHRMask = 0x00000080, + SpvRayFlagsSkipTrianglesKHRMask = 0x00000100, + SpvRayFlagsSkipAABBsKHRMask = 0x00000200, +} SpvRayFlagsMask; + +typedef enum SpvRayQueryIntersection_ { + SpvRayQueryIntersectionRayQueryCandidateIntersectionKHR = 0, + SpvRayQueryIntersectionRayQueryCommittedIntersectionKHR = 1, + SpvRayQueryIntersectionMax = 0x7fffffff, +} SpvRayQueryIntersection; + +typedef enum SpvRayQueryCommittedIntersectionType_ { + SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR = 0, + SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR = 1, + SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR = 2, + SpvRayQueryCommittedIntersectionTypeMax = 0x7fffffff, +} SpvRayQueryCommittedIntersectionType; + +typedef enum SpvRayQueryCandidateIntersectionType_ { + SpvRayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR = 0, + SpvRayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR = 1, + SpvRayQueryCandidateIntersectionTypeMax = 0x7fffffff, +} SpvRayQueryCandidateIntersectionType; + +typedef enum SpvOp_ { + SpvOpNop = 0, + SpvOpUndef = 1, + SpvOpSourceContinued = 2, + SpvOpSource = 3, + SpvOpSourceExtension = 4, + SpvOpName = 5, + SpvOpMemberName = 6, + SpvOpString = 7, + SpvOpLine = 8, + SpvOpExtension = 10, + SpvOpExtInstImport = 11, + SpvOpExtInst = 12, + SpvOpMemoryModel = 14, + SpvOpEntryPoint = 15, + SpvOpExecutionMode = 16, + SpvOpCapability = 17, + SpvOpTypeVoid = 19, + SpvOpTypeBool = 20, + SpvOpTypeInt = 21, + SpvOpTypeFloat = 22, + SpvOpTypeVector = 23, + SpvOpTypeMatrix = 24, + SpvOpTypeImage = 25, + SpvOpTypeSampler = 26, + SpvOpTypeSampledImage = 27, + SpvOpTypeArray = 28, + SpvOpTypeRuntimeArray = 29, + SpvOpTypeStruct = 30, + SpvOpTypeOpaque = 31, + SpvOpTypePointer = 32, + SpvOpTypeFunction = 33, + SpvOpTypeEvent = 34, + SpvOpTypeDeviceEvent = 35, + SpvOpTypeReserveId = 36, + SpvOpTypeQueue = 37, + SpvOpTypePipe = 38, + SpvOpTypeForwardPointer = 39, + SpvOpConstantTrue = 41, + SpvOpConstantFalse = 42, + SpvOpConstant = 43, + SpvOpConstantComposite = 44, + SpvOpConstantSampler = 45, + SpvOpConstantNull = 46, + SpvOpSpecConstantTrue = 48, + SpvOpSpecConstantFalse = 49, + SpvOpSpecConstant = 50, + SpvOpSpecConstantComposite = 51, + SpvOpSpecConstantOp = 52, + SpvOpFunction = 54, + SpvOpFunctionParameter = 55, + SpvOpFunctionEnd = 56, + SpvOpFunctionCall = 57, + SpvOpVariable = 59, + SpvOpImageTexelPointer = 60, + SpvOpLoad = 61, + SpvOpStore = 62, + SpvOpCopyMemory = 63, + SpvOpCopyMemorySized = 64, + SpvOpAccessChain = 65, + SpvOpInBoundsAccessChain = 66, + SpvOpPtrAccessChain = 67, + SpvOpArrayLength = 68, + SpvOpGenericPtrMemSemantics = 69, + SpvOpInBoundsPtrAccessChain = 70, + SpvOpDecorate = 71, + SpvOpMemberDecorate = 72, + SpvOpDecorationGroup = 73, + SpvOpGroupDecorate = 74, + SpvOpGroupMemberDecorate = 75, + SpvOpVectorExtractDynamic = 77, + SpvOpVectorInsertDynamic = 78, + SpvOpVectorShuffle = 79, + SpvOpCompositeConstruct = 80, + SpvOpCompositeExtract = 81, + SpvOpCompositeInsert = 82, + SpvOpCopyObject = 83, + SpvOpTranspose = 84, + SpvOpSampledImage = 86, + SpvOpImageSampleImplicitLod = 87, + SpvOpImageSampleExplicitLod = 88, + SpvOpImageSampleDrefImplicitLod = 89, + SpvOpImageSampleDrefExplicitLod = 90, + SpvOpImageSampleProjImplicitLod = 91, + SpvOpImageSampleProjExplicitLod = 92, + SpvOpImageSampleProjDrefImplicitLod = 93, + SpvOpImageSampleProjDrefExplicitLod = 94, + SpvOpImageFetch = 95, + SpvOpImageGather = 96, + SpvOpImageDrefGather = 97, + SpvOpImageRead = 98, + SpvOpImageWrite = 99, + SpvOpImage = 100, + SpvOpImageQueryFormat = 101, + SpvOpImageQueryOrder = 102, + SpvOpImageQuerySizeLod = 103, + SpvOpImageQuerySize = 104, + SpvOpImageQueryLod = 105, + SpvOpImageQueryLevels = 106, + SpvOpImageQuerySamples = 107, + SpvOpConvertFToU = 109, + SpvOpConvertFToS = 110, + SpvOpConvertSToF = 111, + SpvOpConvertUToF = 112, + SpvOpUConvert = 113, + SpvOpSConvert = 114, + SpvOpFConvert = 115, + SpvOpQuantizeToF16 = 116, + SpvOpConvertPtrToU = 117, + SpvOpSatConvertSToU = 118, + SpvOpSatConvertUToS = 119, + SpvOpConvertUToPtr = 120, + SpvOpPtrCastToGeneric = 121, + SpvOpGenericCastToPtr = 122, + SpvOpGenericCastToPtrExplicit = 123, + SpvOpBitcast = 124, + SpvOpSNegate = 126, + SpvOpFNegate = 127, + SpvOpIAdd = 128, + SpvOpFAdd = 129, + SpvOpISub = 130, + SpvOpFSub = 131, + SpvOpIMul = 132, + SpvOpFMul = 133, + SpvOpUDiv = 134, + SpvOpSDiv = 135, + SpvOpFDiv = 136, + SpvOpUMod = 137, + SpvOpSRem = 138, + SpvOpSMod = 139, + SpvOpFRem = 140, + SpvOpFMod = 141, + SpvOpVectorTimesScalar = 142, + SpvOpMatrixTimesScalar = 143, + SpvOpVectorTimesMatrix = 144, + SpvOpMatrixTimesVector = 145, + SpvOpMatrixTimesMatrix = 146, + SpvOpOuterProduct = 147, + SpvOpDot = 148, + SpvOpIAddCarry = 149, + SpvOpISubBorrow = 150, + SpvOpUMulExtended = 151, + SpvOpSMulExtended = 152, + SpvOpAny = 154, + SpvOpAll = 155, + SpvOpIsNan = 156, + SpvOpIsInf = 157, + SpvOpIsFinite = 158, + SpvOpIsNormal = 159, + SpvOpSignBitSet = 160, + SpvOpLessOrGreater = 161, + SpvOpOrdered = 162, + SpvOpUnordered = 163, + SpvOpLogicalEqual = 164, + SpvOpLogicalNotEqual = 165, + SpvOpLogicalOr = 166, + SpvOpLogicalAnd = 167, + SpvOpLogicalNot = 168, + SpvOpSelect = 169, + SpvOpIEqual = 170, + SpvOpINotEqual = 171, + SpvOpUGreaterThan = 172, + SpvOpSGreaterThan = 173, + SpvOpUGreaterThanEqual = 174, + SpvOpSGreaterThanEqual = 175, + SpvOpULessThan = 176, + SpvOpSLessThan = 177, + SpvOpULessThanEqual = 178, + SpvOpSLessThanEqual = 179, + SpvOpFOrdEqual = 180, + SpvOpFUnordEqual = 181, + SpvOpFOrdNotEqual = 182, + SpvOpFUnordNotEqual = 183, + SpvOpFOrdLessThan = 184, + SpvOpFUnordLessThan = 185, + SpvOpFOrdGreaterThan = 186, + SpvOpFUnordGreaterThan = 187, + SpvOpFOrdLessThanEqual = 188, + SpvOpFUnordLessThanEqual = 189, + SpvOpFOrdGreaterThanEqual = 190, + SpvOpFUnordGreaterThanEqual = 191, + SpvOpShiftRightLogical = 194, + SpvOpShiftRightArithmetic = 195, + SpvOpShiftLeftLogical = 196, + SpvOpBitwiseOr = 197, + SpvOpBitwiseXor = 198, + SpvOpBitwiseAnd = 199, + SpvOpNot = 200, + SpvOpBitFieldInsert = 201, + SpvOpBitFieldSExtract = 202, + SpvOpBitFieldUExtract = 203, + SpvOpBitReverse = 204, + SpvOpBitCount = 205, + SpvOpDPdx = 207, + SpvOpDPdy = 208, + SpvOpFwidth = 209, + SpvOpDPdxFine = 210, + SpvOpDPdyFine = 211, + SpvOpFwidthFine = 212, + SpvOpDPdxCoarse = 213, + SpvOpDPdyCoarse = 214, + SpvOpFwidthCoarse = 215, + SpvOpEmitVertex = 218, + SpvOpEndPrimitive = 219, + SpvOpEmitStreamVertex = 220, + SpvOpEndStreamPrimitive = 221, + SpvOpControlBarrier = 224, + SpvOpMemoryBarrier = 225, + SpvOpAtomicLoad = 227, + SpvOpAtomicStore = 228, + SpvOpAtomicExchange = 229, + SpvOpAtomicCompareExchange = 230, + SpvOpAtomicCompareExchangeWeak = 231, + SpvOpAtomicIIncrement = 232, + SpvOpAtomicIDecrement = 233, + SpvOpAtomicIAdd = 234, + SpvOpAtomicISub = 235, + SpvOpAtomicSMin = 236, + SpvOpAtomicUMin = 237, + SpvOpAtomicSMax = 238, + SpvOpAtomicUMax = 239, + SpvOpAtomicAnd = 240, + SpvOpAtomicOr = 241, + SpvOpAtomicXor = 242, + SpvOpPhi = 245, + SpvOpLoopMerge = 246, + SpvOpSelectionMerge = 247, + SpvOpLabel = 248, + SpvOpBranch = 249, + SpvOpBranchConditional = 250, + SpvOpSwitch = 251, + SpvOpKill = 252, + SpvOpReturn = 253, + SpvOpReturnValue = 254, + SpvOpUnreachable = 255, + SpvOpLifetimeStart = 256, + SpvOpLifetimeStop = 257, + SpvOpGroupAsyncCopy = 259, + SpvOpGroupWaitEvents = 260, + SpvOpGroupAll = 261, + SpvOpGroupAny = 262, + SpvOpGroupBroadcast = 263, + SpvOpGroupIAdd = 264, + SpvOpGroupFAdd = 265, + SpvOpGroupFMin = 266, + SpvOpGroupUMin = 267, + SpvOpGroupSMin = 268, + SpvOpGroupFMax = 269, + SpvOpGroupUMax = 270, + SpvOpGroupSMax = 271, + SpvOpReadPipe = 274, + SpvOpWritePipe = 275, + SpvOpReservedReadPipe = 276, + SpvOpReservedWritePipe = 277, + SpvOpReserveReadPipePackets = 278, + SpvOpReserveWritePipePackets = 279, + SpvOpCommitReadPipe = 280, + SpvOpCommitWritePipe = 281, + SpvOpIsValidReserveId = 282, + SpvOpGetNumPipePackets = 283, + SpvOpGetMaxPipePackets = 284, + SpvOpGroupReserveReadPipePackets = 285, + SpvOpGroupReserveWritePipePackets = 286, + SpvOpGroupCommitReadPipe = 287, + SpvOpGroupCommitWritePipe = 288, + SpvOpEnqueueMarker = 291, + SpvOpEnqueueKernel = 292, + SpvOpGetKernelNDrangeSubGroupCount = 293, + SpvOpGetKernelNDrangeMaxSubGroupSize = 294, + SpvOpGetKernelWorkGroupSize = 295, + SpvOpGetKernelPreferredWorkGroupSizeMultiple = 296, + SpvOpRetainEvent = 297, + SpvOpReleaseEvent = 298, + SpvOpCreateUserEvent = 299, + SpvOpIsValidEvent = 300, + SpvOpSetUserEventStatus = 301, + SpvOpCaptureEventProfilingInfo = 302, + SpvOpGetDefaultQueue = 303, + SpvOpBuildNDRange = 304, + SpvOpImageSparseSampleImplicitLod = 305, + SpvOpImageSparseSampleExplicitLod = 306, + SpvOpImageSparseSampleDrefImplicitLod = 307, + SpvOpImageSparseSampleDrefExplicitLod = 308, + SpvOpImageSparseSampleProjImplicitLod = 309, + SpvOpImageSparseSampleProjExplicitLod = 310, + SpvOpImageSparseSampleProjDrefImplicitLod = 311, + SpvOpImageSparseSampleProjDrefExplicitLod = 312, + SpvOpImageSparseFetch = 313, + SpvOpImageSparseGather = 314, + SpvOpImageSparseDrefGather = 315, + SpvOpImageSparseTexelsResident = 316, + SpvOpNoLine = 317, + SpvOpAtomicFlagTestAndSet = 318, + SpvOpAtomicFlagClear = 319, + SpvOpImageSparseRead = 320, + SpvOpSizeOf = 321, + SpvOpTypePipeStorage = 322, + SpvOpConstantPipeStorage = 323, + SpvOpCreatePipeFromPipeStorage = 324, + SpvOpGetKernelLocalSizeForSubgroupCount = 325, + SpvOpGetKernelMaxNumSubgroups = 326, + SpvOpTypeNamedBarrier = 327, + SpvOpNamedBarrierInitialize = 328, + SpvOpMemoryNamedBarrier = 329, + SpvOpModuleProcessed = 330, + SpvOpExecutionModeId = 331, + SpvOpDecorateId = 332, + SpvOpGroupNonUniformElect = 333, + SpvOpGroupNonUniformAll = 334, + SpvOpGroupNonUniformAny = 335, + SpvOpGroupNonUniformAllEqual = 336, + SpvOpGroupNonUniformBroadcast = 337, + SpvOpGroupNonUniformBroadcastFirst = 338, + SpvOpGroupNonUniformBallot = 339, + SpvOpGroupNonUniformInverseBallot = 340, + SpvOpGroupNonUniformBallotBitExtract = 341, + SpvOpGroupNonUniformBallotBitCount = 342, + SpvOpGroupNonUniformBallotFindLSB = 343, + SpvOpGroupNonUniformBallotFindMSB = 344, + SpvOpGroupNonUniformShuffle = 345, + SpvOpGroupNonUniformShuffleXor = 346, + SpvOpGroupNonUniformShuffleUp = 347, + SpvOpGroupNonUniformShuffleDown = 348, + SpvOpGroupNonUniformIAdd = 349, + SpvOpGroupNonUniformFAdd = 350, + SpvOpGroupNonUniformIMul = 351, + SpvOpGroupNonUniformFMul = 352, + SpvOpGroupNonUniformSMin = 353, + SpvOpGroupNonUniformUMin = 354, + SpvOpGroupNonUniformFMin = 355, + SpvOpGroupNonUniformSMax = 356, + SpvOpGroupNonUniformUMax = 357, + SpvOpGroupNonUniformFMax = 358, + SpvOpGroupNonUniformBitwiseAnd = 359, + SpvOpGroupNonUniformBitwiseOr = 360, + SpvOpGroupNonUniformBitwiseXor = 361, + SpvOpGroupNonUniformLogicalAnd = 362, + SpvOpGroupNonUniformLogicalOr = 363, + SpvOpGroupNonUniformLogicalXor = 364, + SpvOpGroupNonUniformQuadBroadcast = 365, + SpvOpGroupNonUniformQuadSwap = 366, + SpvOpCopyLogical = 400, + SpvOpPtrEqual = 401, + SpvOpPtrNotEqual = 402, + SpvOpPtrDiff = 403, + SpvOpSubgroupBallotKHR = 4421, + SpvOpSubgroupFirstInvocationKHR = 4422, + SpvOpSubgroupAllKHR = 4428, + SpvOpSubgroupAnyKHR = 4429, + SpvOpSubgroupAllEqualKHR = 4430, + SpvOpSubgroupReadInvocationKHR = 4432, + SpvOpTypeRayQueryProvisionalKHR = 4472, + SpvOpRayQueryInitializeKHR = 4473, + SpvOpRayQueryTerminateKHR = 4474, + SpvOpRayQueryGenerateIntersectionKHR = 4475, + SpvOpRayQueryConfirmIntersectionKHR = 4476, + SpvOpRayQueryProceedKHR = 4477, + SpvOpRayQueryGetIntersectionTypeKHR = 4479, + SpvOpGroupIAddNonUniformAMD = 5000, + SpvOpGroupFAddNonUniformAMD = 5001, + SpvOpGroupFMinNonUniformAMD = 5002, + SpvOpGroupUMinNonUniformAMD = 5003, + SpvOpGroupSMinNonUniformAMD = 5004, + SpvOpGroupFMaxNonUniformAMD = 5005, + SpvOpGroupUMaxNonUniformAMD = 5006, + SpvOpGroupSMaxNonUniformAMD = 5007, + SpvOpFragmentMaskFetchAMD = 5011, + SpvOpFragmentFetchAMD = 5012, + SpvOpReadClockKHR = 5056, + SpvOpImageSampleFootprintNV = 5283, + SpvOpGroupNonUniformPartitionNV = 5296, + SpvOpWritePackedPrimitiveIndices4x8NV = 5299, + SpvOpReportIntersectionKHR = 5334, + SpvOpReportIntersectionNV = 5334, + SpvOpIgnoreIntersectionKHR = 5335, + SpvOpIgnoreIntersectionNV = 5335, + SpvOpTerminateRayKHR = 5336, + SpvOpTerminateRayNV = 5336, + SpvOpTraceNV = 5337, + SpvOpTraceRayKHR = 5337, + SpvOpTypeAccelerationStructureKHR = 5341, + SpvOpTypeAccelerationStructureNV = 5341, + SpvOpExecuteCallableKHR = 5344, + SpvOpExecuteCallableNV = 5344, + SpvOpTypeCooperativeMatrixNV = 5358, + SpvOpCooperativeMatrixLoadNV = 5359, + SpvOpCooperativeMatrixStoreNV = 5360, + SpvOpCooperativeMatrixMulAddNV = 5361, + SpvOpCooperativeMatrixLengthNV = 5362, + SpvOpBeginInvocationInterlockEXT = 5364, + SpvOpEndInvocationInterlockEXT = 5365, + SpvOpDemoteToHelperInvocationEXT = 5380, + SpvOpIsHelperInvocationEXT = 5381, + SpvOpSubgroupShuffleINTEL = 5571, + SpvOpSubgroupShuffleDownINTEL = 5572, + SpvOpSubgroupShuffleUpINTEL = 5573, + SpvOpSubgroupShuffleXorINTEL = 5574, + SpvOpSubgroupBlockReadINTEL = 5575, + SpvOpSubgroupBlockWriteINTEL = 5576, + SpvOpSubgroupImageBlockReadINTEL = 5577, + SpvOpSubgroupImageBlockWriteINTEL = 5578, + SpvOpSubgroupImageMediaBlockReadINTEL = 5580, + SpvOpSubgroupImageMediaBlockWriteINTEL = 5581, + SpvOpUCountLeadingZerosINTEL = 5585, + SpvOpUCountTrailingZerosINTEL = 5586, + SpvOpAbsISubINTEL = 5587, + SpvOpAbsUSubINTEL = 5588, + SpvOpIAddSatINTEL = 5589, + SpvOpUAddSatINTEL = 5590, + SpvOpIAverageINTEL = 5591, + SpvOpUAverageINTEL = 5592, + SpvOpIAverageRoundedINTEL = 5593, + SpvOpUAverageRoundedINTEL = 5594, + SpvOpISubSatINTEL = 5595, + SpvOpUSubSatINTEL = 5596, + SpvOpIMul32x16INTEL = 5597, + SpvOpUMul32x16INTEL = 5598, + SpvOpDecorateString = 5632, + SpvOpDecorateStringGOOGLE = 5632, + SpvOpMemberDecorateString = 5633, + SpvOpMemberDecorateStringGOOGLE = 5633, + SpvOpVmeImageINTEL = 5699, + SpvOpTypeVmeImageINTEL = 5700, + SpvOpTypeAvcImePayloadINTEL = 5701, + SpvOpTypeAvcRefPayloadINTEL = 5702, + SpvOpTypeAvcSicPayloadINTEL = 5703, + SpvOpTypeAvcMcePayloadINTEL = 5704, + SpvOpTypeAvcMceResultINTEL = 5705, + SpvOpTypeAvcImeResultINTEL = 5706, + SpvOpTypeAvcImeResultSingleReferenceStreamoutINTEL = 5707, + SpvOpTypeAvcImeResultDualReferenceStreamoutINTEL = 5708, + SpvOpTypeAvcImeSingleReferenceStreaminINTEL = 5709, + SpvOpTypeAvcImeDualReferenceStreaminINTEL = 5710, + SpvOpTypeAvcRefResultINTEL = 5711, + SpvOpTypeAvcSicResultINTEL = 5712, + SpvOpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL = 5713, + SpvOpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL = 5714, + SpvOpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL = 5715, + SpvOpSubgroupAvcMceSetInterShapePenaltyINTEL = 5716, + SpvOpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL = 5717, + SpvOpSubgroupAvcMceSetInterDirectionPenaltyINTEL = 5718, + SpvOpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL = 5719, + SpvOpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL = 5720, + SpvOpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL = 5721, + SpvOpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL = 5722, + SpvOpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL = 5723, + SpvOpSubgroupAvcMceSetMotionVectorCostFunctionINTEL = 5724, + SpvOpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL = 5725, + SpvOpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL = 5726, + SpvOpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL = 5727, + SpvOpSubgroupAvcMceSetAcOnlyHaarINTEL = 5728, + SpvOpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL = 5729, + SpvOpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL = 5730, + SpvOpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL = 5731, + SpvOpSubgroupAvcMceConvertToImePayloadINTEL = 5732, + SpvOpSubgroupAvcMceConvertToImeResultINTEL = 5733, + SpvOpSubgroupAvcMceConvertToRefPayloadINTEL = 5734, + SpvOpSubgroupAvcMceConvertToRefResultINTEL = 5735, + SpvOpSubgroupAvcMceConvertToSicPayloadINTEL = 5736, + SpvOpSubgroupAvcMceConvertToSicResultINTEL = 5737, + SpvOpSubgroupAvcMceGetMotionVectorsINTEL = 5738, + SpvOpSubgroupAvcMceGetInterDistortionsINTEL = 5739, + SpvOpSubgroupAvcMceGetBestInterDistortionsINTEL = 5740, + SpvOpSubgroupAvcMceGetInterMajorShapeINTEL = 5741, + SpvOpSubgroupAvcMceGetInterMinorShapeINTEL = 5742, + SpvOpSubgroupAvcMceGetInterDirectionsINTEL = 5743, + SpvOpSubgroupAvcMceGetInterMotionVectorCountINTEL = 5744, + SpvOpSubgroupAvcMceGetInterReferenceIdsINTEL = 5745, + SpvOpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL = 5746, + SpvOpSubgroupAvcImeInitializeINTEL = 5747, + SpvOpSubgroupAvcImeSetSingleReferenceINTEL = 5748, + SpvOpSubgroupAvcImeSetDualReferenceINTEL = 5749, + SpvOpSubgroupAvcImeRefWindowSizeINTEL = 5750, + SpvOpSubgroupAvcImeAdjustRefOffsetINTEL = 5751, + SpvOpSubgroupAvcImeConvertToMcePayloadINTEL = 5752, + SpvOpSubgroupAvcImeSetMaxMotionVectorCountINTEL = 5753, + SpvOpSubgroupAvcImeSetUnidirectionalMixDisableINTEL = 5754, + SpvOpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL = 5755, + SpvOpSubgroupAvcImeSetWeightedSadINTEL = 5756, + SpvOpSubgroupAvcImeEvaluateWithSingleReferenceINTEL = 5757, + SpvOpSubgroupAvcImeEvaluateWithDualReferenceINTEL = 5758, + SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL = 5759, + SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL = 5760, + SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL = 5761, + SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL = 5762, + SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL = 5763, + SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL = 5764, + SpvOpSubgroupAvcImeConvertToMceResultINTEL = 5765, + SpvOpSubgroupAvcImeGetSingleReferenceStreaminINTEL = 5766, + SpvOpSubgroupAvcImeGetDualReferenceStreaminINTEL = 5767, + SpvOpSubgroupAvcImeStripSingleReferenceStreamoutINTEL = 5768, + SpvOpSubgroupAvcImeStripDualReferenceStreamoutINTEL = 5769, + SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL = 5770, + SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL = 5771, + SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL = 5772, + SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL = 5773, + SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL = 5774, + SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL = 5775, + SpvOpSubgroupAvcImeGetBorderReachedINTEL = 5776, + SpvOpSubgroupAvcImeGetTruncatedSearchIndicationINTEL = 5777, + SpvOpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL = 5778, + SpvOpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL = 5779, + SpvOpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL = 5780, + SpvOpSubgroupAvcFmeInitializeINTEL = 5781, + SpvOpSubgroupAvcBmeInitializeINTEL = 5782, + SpvOpSubgroupAvcRefConvertToMcePayloadINTEL = 5783, + SpvOpSubgroupAvcRefSetBidirectionalMixDisableINTEL = 5784, + SpvOpSubgroupAvcRefSetBilinearFilterEnableINTEL = 5785, + SpvOpSubgroupAvcRefEvaluateWithSingleReferenceINTEL = 5786, + SpvOpSubgroupAvcRefEvaluateWithDualReferenceINTEL = 5787, + SpvOpSubgroupAvcRefEvaluateWithMultiReferenceINTEL = 5788, + SpvOpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL = 5789, + SpvOpSubgroupAvcRefConvertToMceResultINTEL = 5790, + SpvOpSubgroupAvcSicInitializeINTEL = 5791, + SpvOpSubgroupAvcSicConfigureSkcINTEL = 5792, + SpvOpSubgroupAvcSicConfigureIpeLumaINTEL = 5793, + SpvOpSubgroupAvcSicConfigureIpeLumaChromaINTEL = 5794, + SpvOpSubgroupAvcSicGetMotionVectorMaskINTEL = 5795, + SpvOpSubgroupAvcSicConvertToMcePayloadINTEL = 5796, + SpvOpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL = 5797, + SpvOpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL = 5798, + SpvOpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL = 5799, + SpvOpSubgroupAvcSicSetBilinearFilterEnableINTEL = 5800, + SpvOpSubgroupAvcSicSetSkcForwardTransformEnableINTEL = 5801, + SpvOpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL = 5802, + SpvOpSubgroupAvcSicEvaluateIpeINTEL = 5803, + SpvOpSubgroupAvcSicEvaluateWithSingleReferenceINTEL = 5804, + SpvOpSubgroupAvcSicEvaluateWithDualReferenceINTEL = 5805, + SpvOpSubgroupAvcSicEvaluateWithMultiReferenceINTEL = 5806, + SpvOpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL = 5807, + SpvOpSubgroupAvcSicConvertToMceResultINTEL = 5808, + SpvOpSubgroupAvcSicGetIpeLumaShapeINTEL = 5809, + SpvOpSubgroupAvcSicGetBestIpeLumaDistortionINTEL = 5810, + SpvOpSubgroupAvcSicGetBestIpeChromaDistortionINTEL = 5811, + SpvOpSubgroupAvcSicGetPackedIpeLumaModesINTEL = 5812, + SpvOpSubgroupAvcSicGetIpeChromaModeINTEL = 5813, + SpvOpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, + SpvOpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, + SpvOpSubgroupAvcSicGetInterRawSadsINTEL = 5816, + SpvOpRayQueryGetRayTMinKHR = 6016, + SpvOpRayQueryGetRayFlagsKHR = 6017, + SpvOpRayQueryGetIntersectionTKHR = 6018, + SpvOpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019, + SpvOpRayQueryGetIntersectionInstanceIdKHR = 6020, + SpvOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021, + SpvOpRayQueryGetIntersectionGeometryIndexKHR = 6022, + SpvOpRayQueryGetIntersectionPrimitiveIndexKHR = 6023, + SpvOpRayQueryGetIntersectionBarycentricsKHR = 6024, + SpvOpRayQueryGetIntersectionFrontFaceKHR = 6025, + SpvOpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026, + SpvOpRayQueryGetIntersectionObjectRayDirectionKHR = 6027, + SpvOpRayQueryGetIntersectionObjectRayOriginKHR = 6028, + SpvOpRayQueryGetWorldRayDirectionKHR = 6029, + SpvOpRayQueryGetWorldRayOriginKHR = 6030, + SpvOpRayQueryGetIntersectionObjectToWorldKHR = 6031, + SpvOpRayQueryGetIntersectionWorldToObjectKHR = 6032, + SpvOpMax = 0x7fffffff, +} SpvOp; + +#ifdef SPV_ENABLE_UTILITY_CODE +inline void SpvHasResultAndType(SpvOp opcode, bool *hasResult, bool *hasResultType) { + *hasResult = *hasResultType = false; + switch (opcode) { + default: /* unknown opcode */ break; + case SpvOpNop: *hasResult = false; *hasResultType = false; break; + case SpvOpUndef: *hasResult = true; *hasResultType = true; break; + case SpvOpSourceContinued: *hasResult = false; *hasResultType = false; break; + case SpvOpSource: *hasResult = false; *hasResultType = false; break; + case SpvOpSourceExtension: *hasResult = false; *hasResultType = false; break; + case SpvOpName: *hasResult = false; *hasResultType = false; break; + case SpvOpMemberName: *hasResult = false; *hasResultType = false; break; + case SpvOpString: *hasResult = true; *hasResultType = false; break; + case SpvOpLine: *hasResult = false; *hasResultType = false; break; + case SpvOpExtension: *hasResult = false; *hasResultType = false; break; + case SpvOpExtInstImport: *hasResult = true; *hasResultType = false; break; + case SpvOpExtInst: *hasResult = true; *hasResultType = true; break; + case SpvOpMemoryModel: *hasResult = false; *hasResultType = false; break; + case SpvOpEntryPoint: *hasResult = false; *hasResultType = false; break; + case SpvOpExecutionMode: *hasResult = false; *hasResultType = false; break; + case SpvOpCapability: *hasResult = false; *hasResultType = false; break; + case SpvOpTypeVoid: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeBool: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeInt: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeFloat: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeVector: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeMatrix: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeImage: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeSampler: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeSampledImage: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeArray: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeRuntimeArray: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeStruct: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeOpaque: *hasResult = true; *hasResultType = false; break; + case SpvOpTypePointer: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeFunction: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeEvent: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeDeviceEvent: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeReserveId: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeQueue: *hasResult = true; *hasResultType = false; break; + case SpvOpTypePipe: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeForwardPointer: *hasResult = false; *hasResultType = false; break; + case SpvOpConstantTrue: *hasResult = true; *hasResultType = true; break; + case SpvOpConstantFalse: *hasResult = true; *hasResultType = true; break; + case SpvOpConstant: *hasResult = true; *hasResultType = true; break; + case SpvOpConstantComposite: *hasResult = true; *hasResultType = true; break; + case SpvOpConstantSampler: *hasResult = true; *hasResultType = true; break; + case SpvOpConstantNull: *hasResult = true; *hasResultType = true; break; + case SpvOpSpecConstantTrue: *hasResult = true; *hasResultType = true; break; + case SpvOpSpecConstantFalse: *hasResult = true; *hasResultType = true; break; + case SpvOpSpecConstant: *hasResult = true; *hasResultType = true; break; + case SpvOpSpecConstantComposite: *hasResult = true; *hasResultType = true; break; + case SpvOpSpecConstantOp: *hasResult = true; *hasResultType = true; break; + case SpvOpFunction: *hasResult = true; *hasResultType = true; break; + case SpvOpFunctionParameter: *hasResult = true; *hasResultType = true; break; + case SpvOpFunctionEnd: *hasResult = false; *hasResultType = false; break; + case SpvOpFunctionCall: *hasResult = true; *hasResultType = true; break; + case SpvOpVariable: *hasResult = true; *hasResultType = true; break; + case SpvOpImageTexelPointer: *hasResult = true; *hasResultType = true; break; + case SpvOpLoad: *hasResult = true; *hasResultType = true; break; + case SpvOpStore: *hasResult = false; *hasResultType = false; break; + case SpvOpCopyMemory: *hasResult = false; *hasResultType = false; break; + case SpvOpCopyMemorySized: *hasResult = false; *hasResultType = false; break; + case SpvOpAccessChain: *hasResult = true; *hasResultType = true; break; + case SpvOpInBoundsAccessChain: *hasResult = true; *hasResultType = true; break; + case SpvOpPtrAccessChain: *hasResult = true; *hasResultType = true; break; + case SpvOpArrayLength: *hasResult = true; *hasResultType = true; break; + case SpvOpGenericPtrMemSemantics: *hasResult = true; *hasResultType = true; break; + case SpvOpInBoundsPtrAccessChain: *hasResult = true; *hasResultType = true; break; + case SpvOpDecorate: *hasResult = false; *hasResultType = false; break; + case SpvOpMemberDecorate: *hasResult = false; *hasResultType = false; break; + case SpvOpDecorationGroup: *hasResult = true; *hasResultType = false; break; + case SpvOpGroupDecorate: *hasResult = false; *hasResultType = false; break; + case SpvOpGroupMemberDecorate: *hasResult = false; *hasResultType = false; break; + case SpvOpVectorExtractDynamic: *hasResult = true; *hasResultType = true; break; + case SpvOpVectorInsertDynamic: *hasResult = true; *hasResultType = true; break; + case SpvOpVectorShuffle: *hasResult = true; *hasResultType = true; break; + case SpvOpCompositeConstruct: *hasResult = true; *hasResultType = true; break; + case SpvOpCompositeExtract: *hasResult = true; *hasResultType = true; break; + case SpvOpCompositeInsert: *hasResult = true; *hasResultType = true; break; + case SpvOpCopyObject: *hasResult = true; *hasResultType = true; break; + case SpvOpTranspose: *hasResult = true; *hasResultType = true; break; + case SpvOpSampledImage: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSampleImplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSampleExplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageFetch: *hasResult = true; *hasResultType = true; break; + case SpvOpImageGather: *hasResult = true; *hasResultType = true; break; + case SpvOpImageDrefGather: *hasResult = true; *hasResultType = true; break; + case SpvOpImageRead: *hasResult = true; *hasResultType = true; break; + case SpvOpImageWrite: *hasResult = false; *hasResultType = false; break; + case SpvOpImage: *hasResult = true; *hasResultType = true; break; + case SpvOpImageQueryFormat: *hasResult = true; *hasResultType = true; break; + case SpvOpImageQueryOrder: *hasResult = true; *hasResultType = true; break; + case SpvOpImageQuerySizeLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageQuerySize: *hasResult = true; *hasResultType = true; break; + case SpvOpImageQueryLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageQueryLevels: *hasResult = true; *hasResultType = true; break; + case SpvOpImageQuerySamples: *hasResult = true; *hasResultType = true; break; + case SpvOpConvertFToU: *hasResult = true; *hasResultType = true; break; + case SpvOpConvertFToS: *hasResult = true; *hasResultType = true; break; + case SpvOpConvertSToF: *hasResult = true; *hasResultType = true; break; + case SpvOpConvertUToF: *hasResult = true; *hasResultType = true; break; + case SpvOpUConvert: *hasResult = true; *hasResultType = true; break; + case SpvOpSConvert: *hasResult = true; *hasResultType = true; break; + case SpvOpFConvert: *hasResult = true; *hasResultType = true; break; + case SpvOpQuantizeToF16: *hasResult = true; *hasResultType = true; break; + case SpvOpConvertPtrToU: *hasResult = true; *hasResultType = true; break; + case SpvOpSatConvertSToU: *hasResult = true; *hasResultType = true; break; + case SpvOpSatConvertUToS: *hasResult = true; *hasResultType = true; break; + case SpvOpConvertUToPtr: *hasResult = true; *hasResultType = true; break; + case SpvOpPtrCastToGeneric: *hasResult = true; *hasResultType = true; break; + case SpvOpGenericCastToPtr: *hasResult = true; *hasResultType = true; break; + case SpvOpGenericCastToPtrExplicit: *hasResult = true; *hasResultType = true; break; + case SpvOpBitcast: *hasResult = true; *hasResultType = true; break; + case SpvOpSNegate: *hasResult = true; *hasResultType = true; break; + case SpvOpFNegate: *hasResult = true; *hasResultType = true; break; + case SpvOpIAdd: *hasResult = true; *hasResultType = true; break; + case SpvOpFAdd: *hasResult = true; *hasResultType = true; break; + case SpvOpISub: *hasResult = true; *hasResultType = true; break; + case SpvOpFSub: *hasResult = true; *hasResultType = true; break; + case SpvOpIMul: *hasResult = true; *hasResultType = true; break; + case SpvOpFMul: *hasResult = true; *hasResultType = true; break; + case SpvOpUDiv: *hasResult = true; *hasResultType = true; break; + case SpvOpSDiv: *hasResult = true; *hasResultType = true; break; + case SpvOpFDiv: *hasResult = true; *hasResultType = true; break; + case SpvOpUMod: *hasResult = true; *hasResultType = true; break; + case SpvOpSRem: *hasResult = true; *hasResultType = true; break; + case SpvOpSMod: *hasResult = true; *hasResultType = true; break; + case SpvOpFRem: *hasResult = true; *hasResultType = true; break; + case SpvOpFMod: *hasResult = true; *hasResultType = true; break; + case SpvOpVectorTimesScalar: *hasResult = true; *hasResultType = true; break; + case SpvOpMatrixTimesScalar: *hasResult = true; *hasResultType = true; break; + case SpvOpVectorTimesMatrix: *hasResult = true; *hasResultType = true; break; + case SpvOpMatrixTimesVector: *hasResult = true; *hasResultType = true; break; + case SpvOpMatrixTimesMatrix: *hasResult = true; *hasResultType = true; break; + case SpvOpOuterProduct: *hasResult = true; *hasResultType = true; break; + case SpvOpDot: *hasResult = true; *hasResultType = true; break; + case SpvOpIAddCarry: *hasResult = true; *hasResultType = true; break; + case SpvOpISubBorrow: *hasResult = true; *hasResultType = true; break; + case SpvOpUMulExtended: *hasResult = true; *hasResultType = true; break; + case SpvOpSMulExtended: *hasResult = true; *hasResultType = true; break; + case SpvOpAny: *hasResult = true; *hasResultType = true; break; + case SpvOpAll: *hasResult = true; *hasResultType = true; break; + case SpvOpIsNan: *hasResult = true; *hasResultType = true; break; + case SpvOpIsInf: *hasResult = true; *hasResultType = true; break; + case SpvOpIsFinite: *hasResult = true; *hasResultType = true; break; + case SpvOpIsNormal: *hasResult = true; *hasResultType = true; break; + case SpvOpSignBitSet: *hasResult = true; *hasResultType = true; break; + case SpvOpLessOrGreater: *hasResult = true; *hasResultType = true; break; + case SpvOpOrdered: *hasResult = true; *hasResultType = true; break; + case SpvOpUnordered: *hasResult = true; *hasResultType = true; break; + case SpvOpLogicalEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpLogicalNotEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpLogicalOr: *hasResult = true; *hasResultType = true; break; + case SpvOpLogicalAnd: *hasResult = true; *hasResultType = true; break; + case SpvOpLogicalNot: *hasResult = true; *hasResultType = true; break; + case SpvOpSelect: *hasResult = true; *hasResultType = true; break; + case SpvOpIEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpINotEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpUGreaterThan: *hasResult = true; *hasResultType = true; break; + case SpvOpSGreaterThan: *hasResult = true; *hasResultType = true; break; + case SpvOpUGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpSGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpULessThan: *hasResult = true; *hasResultType = true; break; + case SpvOpSLessThan: *hasResult = true; *hasResultType = true; break; + case SpvOpULessThanEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpSLessThanEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpFOrdEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpFUnordEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpFOrdNotEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpFUnordNotEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpFOrdLessThan: *hasResult = true; *hasResultType = true; break; + case SpvOpFUnordLessThan: *hasResult = true; *hasResultType = true; break; + case SpvOpFOrdGreaterThan: *hasResult = true; *hasResultType = true; break; + case SpvOpFUnordGreaterThan: *hasResult = true; *hasResultType = true; break; + case SpvOpFOrdLessThanEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpFUnordLessThanEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpFOrdGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpFUnordGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpShiftRightLogical: *hasResult = true; *hasResultType = true; break; + case SpvOpShiftRightArithmetic: *hasResult = true; *hasResultType = true; break; + case SpvOpShiftLeftLogical: *hasResult = true; *hasResultType = true; break; + case SpvOpBitwiseOr: *hasResult = true; *hasResultType = true; break; + case SpvOpBitwiseXor: *hasResult = true; *hasResultType = true; break; + case SpvOpBitwiseAnd: *hasResult = true; *hasResultType = true; break; + case SpvOpNot: *hasResult = true; *hasResultType = true; break; + case SpvOpBitFieldInsert: *hasResult = true; *hasResultType = true; break; + case SpvOpBitFieldSExtract: *hasResult = true; *hasResultType = true; break; + case SpvOpBitFieldUExtract: *hasResult = true; *hasResultType = true; break; + case SpvOpBitReverse: *hasResult = true; *hasResultType = true; break; + case SpvOpBitCount: *hasResult = true; *hasResultType = true; break; + case SpvOpDPdx: *hasResult = true; *hasResultType = true; break; + case SpvOpDPdy: *hasResult = true; *hasResultType = true; break; + case SpvOpFwidth: *hasResult = true; *hasResultType = true; break; + case SpvOpDPdxFine: *hasResult = true; *hasResultType = true; break; + case SpvOpDPdyFine: *hasResult = true; *hasResultType = true; break; + case SpvOpFwidthFine: *hasResult = true; *hasResultType = true; break; + case SpvOpDPdxCoarse: *hasResult = true; *hasResultType = true; break; + case SpvOpDPdyCoarse: *hasResult = true; *hasResultType = true; break; + case SpvOpFwidthCoarse: *hasResult = true; *hasResultType = true; break; + case SpvOpEmitVertex: *hasResult = false; *hasResultType = false; break; + case SpvOpEndPrimitive: *hasResult = false; *hasResultType = false; break; + case SpvOpEmitStreamVertex: *hasResult = false; *hasResultType = false; break; + case SpvOpEndStreamPrimitive: *hasResult = false; *hasResultType = false; break; + case SpvOpControlBarrier: *hasResult = false; *hasResultType = false; break; + case SpvOpMemoryBarrier: *hasResult = false; *hasResultType = false; break; + case SpvOpAtomicLoad: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicStore: *hasResult = false; *hasResultType = false; break; + case SpvOpAtomicExchange: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicCompareExchange: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicCompareExchangeWeak: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicIIncrement: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicIDecrement: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicIAdd: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicISub: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicSMin: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicUMin: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicSMax: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicUMax: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicAnd: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicOr: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicXor: *hasResult = true; *hasResultType = true; break; + case SpvOpPhi: *hasResult = true; *hasResultType = true; break; + case SpvOpLoopMerge: *hasResult = false; *hasResultType = false; break; + case SpvOpSelectionMerge: *hasResult = false; *hasResultType = false; break; + case SpvOpLabel: *hasResult = true; *hasResultType = false; break; + case SpvOpBranch: *hasResult = false; *hasResultType = false; break; + case SpvOpBranchConditional: *hasResult = false; *hasResultType = false; break; + case SpvOpSwitch: *hasResult = false; *hasResultType = false; break; + case SpvOpKill: *hasResult = false; *hasResultType = false; break; + case SpvOpReturn: *hasResult = false; *hasResultType = false; break; + case SpvOpReturnValue: *hasResult = false; *hasResultType = false; break; + case SpvOpUnreachable: *hasResult = false; *hasResultType = false; break; + case SpvOpLifetimeStart: *hasResult = false; *hasResultType = false; break; + case SpvOpLifetimeStop: *hasResult = false; *hasResultType = false; break; + case SpvOpGroupAsyncCopy: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupWaitEvents: *hasResult = false; *hasResultType = false; break; + case SpvOpGroupAll: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupAny: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupBroadcast: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupIAdd: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupFAdd: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupFMin: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupUMin: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupSMin: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupFMax: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupUMax: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupSMax: *hasResult = true; *hasResultType = true; break; + case SpvOpReadPipe: *hasResult = true; *hasResultType = true; break; + case SpvOpWritePipe: *hasResult = true; *hasResultType = true; break; + case SpvOpReservedReadPipe: *hasResult = true; *hasResultType = true; break; + case SpvOpReservedWritePipe: *hasResult = true; *hasResultType = true; break; + case SpvOpReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; + case SpvOpReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; + case SpvOpCommitReadPipe: *hasResult = false; *hasResultType = false; break; + case SpvOpCommitWritePipe: *hasResult = false; *hasResultType = false; break; + case SpvOpIsValidReserveId: *hasResult = true; *hasResultType = true; break; + case SpvOpGetNumPipePackets: *hasResult = true; *hasResultType = true; break; + case SpvOpGetMaxPipePackets: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupCommitReadPipe: *hasResult = false; *hasResultType = false; break; + case SpvOpGroupCommitWritePipe: *hasResult = false; *hasResultType = false; break; + case SpvOpEnqueueMarker: *hasResult = true; *hasResultType = true; break; + case SpvOpEnqueueKernel: *hasResult = true; *hasResultType = true; break; + case SpvOpGetKernelNDrangeSubGroupCount: *hasResult = true; *hasResultType = true; break; + case SpvOpGetKernelNDrangeMaxSubGroupSize: *hasResult = true; *hasResultType = true; break; + case SpvOpGetKernelWorkGroupSize: *hasResult = true; *hasResultType = true; break; + case SpvOpGetKernelPreferredWorkGroupSizeMultiple: *hasResult = true; *hasResultType = true; break; + case SpvOpRetainEvent: *hasResult = false; *hasResultType = false; break; + case SpvOpReleaseEvent: *hasResult = false; *hasResultType = false; break; + case SpvOpCreateUserEvent: *hasResult = true; *hasResultType = true; break; + case SpvOpIsValidEvent: *hasResult = true; *hasResultType = true; break; + case SpvOpSetUserEventStatus: *hasResult = false; *hasResultType = false; break; + case SpvOpCaptureEventProfilingInfo: *hasResult = false; *hasResultType = false; break; + case SpvOpGetDefaultQueue: *hasResult = true; *hasResultType = true; break; + case SpvOpBuildNDRange: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseSampleImplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseSampleExplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseFetch: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseGather: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseDrefGather: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseTexelsResident: *hasResult = true; *hasResultType = true; break; + case SpvOpNoLine: *hasResult = false; *hasResultType = false; break; + case SpvOpAtomicFlagTestAndSet: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicFlagClear: *hasResult = false; *hasResultType = false; break; + case SpvOpImageSparseRead: *hasResult = true; *hasResultType = true; break; + case SpvOpSizeOf: *hasResult = true; *hasResultType = true; break; + case SpvOpTypePipeStorage: *hasResult = true; *hasResultType = false; break; + case SpvOpConstantPipeStorage: *hasResult = true; *hasResultType = true; break; + case SpvOpCreatePipeFromPipeStorage: *hasResult = true; *hasResultType = true; break; + case SpvOpGetKernelLocalSizeForSubgroupCount: *hasResult = true; *hasResultType = true; break; + case SpvOpGetKernelMaxNumSubgroups: *hasResult = true; *hasResultType = true; break; + case SpvOpTypeNamedBarrier: *hasResult = true; *hasResultType = false; break; + case SpvOpNamedBarrierInitialize: *hasResult = true; *hasResultType = true; break; + case SpvOpMemoryNamedBarrier: *hasResult = false; *hasResultType = false; break; + case SpvOpModuleProcessed: *hasResult = false; *hasResultType = false; break; + case SpvOpExecutionModeId: *hasResult = false; *hasResultType = false; break; + case SpvOpDecorateId: *hasResult = false; *hasResultType = false; break; + case SpvOpGroupNonUniformElect: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformAll: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformAny: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformAllEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBroadcast: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBroadcastFirst: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBallot: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformInverseBallot: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBallotBitExtract: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBallotBitCount: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBallotFindLSB: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBallotFindMSB: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformShuffle: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformShuffleXor: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformShuffleUp: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformShuffleDown: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformIAdd: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformFAdd: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformIMul: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformFMul: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformSMin: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformUMin: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformFMin: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformSMax: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformUMax: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformFMax: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBitwiseAnd: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBitwiseOr: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBitwiseXor: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformLogicalAnd: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformLogicalOr: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformLogicalXor: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformQuadBroadcast: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformQuadSwap: *hasResult = true; *hasResultType = true; break; + case SpvOpCopyLogical: *hasResult = true; *hasResultType = true; break; + case SpvOpPtrEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpPtrNotEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpPtrDiff: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupIAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupFAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupFMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupUMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupSMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupFMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupUMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupSMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpFragmentMaskFetchAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpFragmentFetchAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpReadClockKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSampleFootprintNV: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformPartitionNV: *hasResult = true; *hasResultType = true; break; + case SpvOpWritePackedPrimitiveIndices4x8NV: *hasResult = false; *hasResultType = false; break; + case SpvOpReportIntersectionNV: *hasResult = true; *hasResultType = true; break; + case SpvOpIgnoreIntersectionNV: *hasResult = false; *hasResultType = false; break; + case SpvOpTerminateRayNV: *hasResult = false; *hasResultType = false; break; + case SpvOpTraceNV: *hasResult = false; *hasResultType = false; break; + case SpvOpTypeAccelerationStructureNV: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeRayQueryProvisionalKHR: *hasResult = true; *hasResultType = false; break; + case SpvOpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break; + case SpvOpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break; + case SpvOpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case SpvOpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case SpvOpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetRayTMinKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetRayFlagsKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionTKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionInstanceCustomIndexKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionInstanceIdKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionGeometryIndexKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionPrimitiveIndexKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionBarycentricsKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionFrontFaceKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionCandidateAABBOpaqueKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionObjectRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionObjectRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetWorldRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetWorldRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpExecuteCallableNV: *hasResult = false; *hasResultType = false; break; + case SpvOpTypeCooperativeMatrixNV: *hasResult = true; *hasResultType = false; break; + case SpvOpCooperativeMatrixLoadNV: *hasResult = true; *hasResultType = true; break; + case SpvOpCooperativeMatrixStoreNV: *hasResult = false; *hasResultType = false; break; + case SpvOpCooperativeMatrixMulAddNV: *hasResult = true; *hasResultType = true; break; + case SpvOpCooperativeMatrixLengthNV: *hasResult = true; *hasResultType = true; break; + case SpvOpBeginInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; + case SpvOpEndInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; + case SpvOpDemoteToHelperInvocationEXT: *hasResult = false; *hasResultType = false; break; + case SpvOpIsHelperInvocationEXT: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupShuffleINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupShuffleDownINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupShuffleUpINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupShuffleXorINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case SpvOpSubgroupImageBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupImageBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case SpvOpSubgroupImageMediaBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupImageMediaBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case SpvOpUCountLeadingZerosINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpUCountTrailingZerosINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpAbsISubINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpAbsUSubINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpIAddSatINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpUAddSatINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpIAverageINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpUAverageINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpIAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpUAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpISubSatINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpUSubSatINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpDecorateString: *hasResult = false; *hasResultType = false; break; + case SpvOpMemberDecorateString: *hasResult = false; *hasResultType = false; break; + case SpvOpVmeImageINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpTypeVmeImageINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcImePayloadINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcRefPayloadINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcSicPayloadINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcMcePayloadINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcMceResultINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcImeResultINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcImeResultSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcImeResultDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcImeSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcImeDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcRefResultINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcSicResultINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceSetInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceSetInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceSetMotionVectorCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceSetAcOnlyHaarINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceConvertToImePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceConvertToImeResultINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceConvertToRefPayloadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceConvertToRefResultINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceConvertToSicPayloadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceConvertToSicResultINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetBestInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetInterMajorShapeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetInterMinorShapeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetInterDirectionsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetInterMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetInterReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeSetSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeSetDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeRefWindowSizeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeAdjustRefOffsetINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeSetMaxMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeSetUnidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeSetWeightedSadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeStripSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeStripDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetBorderReachedINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetTruncatedSearchIndicationINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcFmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcBmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcRefConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcRefSetBidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcRefSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcRefEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcRefEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcRefEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcRefConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicConfigureSkcINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicConfigureIpeLumaINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicConfigureIpeLumaChromaINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicGetMotionVectorMaskINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicSetSkcForwardTransformEnableINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicEvaluateIpeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicGetIpeLumaShapeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicGetBestIpeLumaDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicGetBestIpeChromaDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicGetPackedIpeLumaModesINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicGetIpeChromaModeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break; + } +} +#endif /* SPV_ENABLE_UTILITY_CODE */ + +#endif + diff --git a/mac/include/spirv_cross/spirv.hpp b/mac/include/spirv_cross/spirv.hpp new file mode 100644 index 00000000..9f98683d --- /dev/null +++ b/mac/include/spirv_cross/spirv.hpp @@ -0,0 +1,2114 @@ +// Copyright (c) 2014-2020 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and/or associated documentation files (the "Materials"), +// to deal in the Materials without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Materials, and to permit persons to whom the +// Materials are furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS +// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND +// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS +// IN THE MATERIALS. + +// This header is automatically generated by the same tool that creates +// the Binary Section of the SPIR-V specification. + +// Enumeration tokens for SPIR-V, in various styles: +// C, C++, C++11, JSON, Lua, Python, C#, D +// +// - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL +// - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL +// - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL +// - Lua will use tables, e.g.: spv.SourceLanguage.GLSL +// - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] +// - C# will use enum classes in the Specification class located in the "Spv" namespace, +// e.g.: Spv.Specification.SourceLanguage.GLSL +// - D will have tokens under the "spv" module, e.g: spv.SourceLanguage.GLSL +// +// Some tokens act like mask values, which can be OR'd together, +// while others are mutually exclusive. The mask-like ones have +// "Mask" in their name, and a parallel enum that has the shift +// amount (1 << x) for each corresponding enumerant. + +#ifndef spirv_HPP +#define spirv_HPP + +namespace spv { + +typedef unsigned int Id; + +#define SPV_VERSION 0x10500 +#define SPV_REVISION 1 + +static const unsigned int MagicNumber = 0x07230203; +static const unsigned int Version = 0x00010500; +static const unsigned int Revision = 1; +static const unsigned int OpCodeMask = 0xffff; +static const unsigned int WordCountShift = 16; + +enum SourceLanguage { + SourceLanguageUnknown = 0, + SourceLanguageESSL = 1, + SourceLanguageGLSL = 2, + SourceLanguageOpenCL_C = 3, + SourceLanguageOpenCL_CPP = 4, + SourceLanguageHLSL = 5, + SourceLanguageMax = 0x7fffffff, +}; + +enum ExecutionModel { + ExecutionModelVertex = 0, + ExecutionModelTessellationControl = 1, + ExecutionModelTessellationEvaluation = 2, + ExecutionModelGeometry = 3, + ExecutionModelFragment = 4, + ExecutionModelGLCompute = 5, + ExecutionModelKernel = 6, + ExecutionModelTaskNV = 5267, + ExecutionModelMeshNV = 5268, + ExecutionModelRayGenerationKHR = 5313, + ExecutionModelRayGenerationNV = 5313, + ExecutionModelIntersectionKHR = 5314, + ExecutionModelIntersectionNV = 5314, + ExecutionModelAnyHitKHR = 5315, + ExecutionModelAnyHitNV = 5315, + ExecutionModelClosestHitKHR = 5316, + ExecutionModelClosestHitNV = 5316, + ExecutionModelMissKHR = 5317, + ExecutionModelMissNV = 5317, + ExecutionModelCallableKHR = 5318, + ExecutionModelCallableNV = 5318, + ExecutionModelMax = 0x7fffffff, +}; + +enum AddressingModel { + AddressingModelLogical = 0, + AddressingModelPhysical32 = 1, + AddressingModelPhysical64 = 2, + AddressingModelPhysicalStorageBuffer64 = 5348, + AddressingModelPhysicalStorageBuffer64EXT = 5348, + AddressingModelMax = 0x7fffffff, +}; + +enum MemoryModel { + MemoryModelSimple = 0, + MemoryModelGLSL450 = 1, + MemoryModelOpenCL = 2, + MemoryModelVulkan = 3, + MemoryModelVulkanKHR = 3, + MemoryModelMax = 0x7fffffff, +}; + +enum ExecutionMode { + ExecutionModeInvocations = 0, + ExecutionModeSpacingEqual = 1, + ExecutionModeSpacingFractionalEven = 2, + ExecutionModeSpacingFractionalOdd = 3, + ExecutionModeVertexOrderCw = 4, + ExecutionModeVertexOrderCcw = 5, + ExecutionModePixelCenterInteger = 6, + ExecutionModeOriginUpperLeft = 7, + ExecutionModeOriginLowerLeft = 8, + ExecutionModeEarlyFragmentTests = 9, + ExecutionModePointMode = 10, + ExecutionModeXfb = 11, + ExecutionModeDepthReplacing = 12, + ExecutionModeDepthGreater = 14, + ExecutionModeDepthLess = 15, + ExecutionModeDepthUnchanged = 16, + ExecutionModeLocalSize = 17, + ExecutionModeLocalSizeHint = 18, + ExecutionModeInputPoints = 19, + ExecutionModeInputLines = 20, + ExecutionModeInputLinesAdjacency = 21, + ExecutionModeTriangles = 22, + ExecutionModeInputTrianglesAdjacency = 23, + ExecutionModeQuads = 24, + ExecutionModeIsolines = 25, + ExecutionModeOutputVertices = 26, + ExecutionModeOutputPoints = 27, + ExecutionModeOutputLineStrip = 28, + ExecutionModeOutputTriangleStrip = 29, + ExecutionModeVecTypeHint = 30, + ExecutionModeContractionOff = 31, + ExecutionModeInitializer = 33, + ExecutionModeFinalizer = 34, + ExecutionModeSubgroupSize = 35, + ExecutionModeSubgroupsPerWorkgroup = 36, + ExecutionModeSubgroupsPerWorkgroupId = 37, + ExecutionModeLocalSizeId = 38, + ExecutionModeLocalSizeHintId = 39, + ExecutionModePostDepthCoverage = 4446, + ExecutionModeDenormPreserve = 4459, + ExecutionModeDenormFlushToZero = 4460, + ExecutionModeSignedZeroInfNanPreserve = 4461, + ExecutionModeRoundingModeRTE = 4462, + ExecutionModeRoundingModeRTZ = 4463, + ExecutionModeStencilRefReplacingEXT = 5027, + ExecutionModeOutputLinesNV = 5269, + ExecutionModeOutputPrimitivesNV = 5270, + ExecutionModeDerivativeGroupQuadsNV = 5289, + ExecutionModeDerivativeGroupLinearNV = 5290, + ExecutionModeOutputTrianglesNV = 5298, + ExecutionModePixelInterlockOrderedEXT = 5366, + ExecutionModePixelInterlockUnorderedEXT = 5367, + ExecutionModeSampleInterlockOrderedEXT = 5368, + ExecutionModeSampleInterlockUnorderedEXT = 5369, + ExecutionModeShadingRateInterlockOrderedEXT = 5370, + ExecutionModeShadingRateInterlockUnorderedEXT = 5371, + ExecutionModeMax = 0x7fffffff, +}; + +enum StorageClass { + StorageClassUniformConstant = 0, + StorageClassInput = 1, + StorageClassUniform = 2, + StorageClassOutput = 3, + StorageClassWorkgroup = 4, + StorageClassCrossWorkgroup = 5, + StorageClassPrivate = 6, + StorageClassFunction = 7, + StorageClassGeneric = 8, + StorageClassPushConstant = 9, + StorageClassAtomicCounter = 10, + StorageClassImage = 11, + StorageClassStorageBuffer = 12, + StorageClassCallableDataKHR = 5328, + StorageClassCallableDataNV = 5328, + StorageClassIncomingCallableDataKHR = 5329, + StorageClassIncomingCallableDataNV = 5329, + StorageClassRayPayloadKHR = 5338, + StorageClassRayPayloadNV = 5338, + StorageClassHitAttributeKHR = 5339, + StorageClassHitAttributeNV = 5339, + StorageClassIncomingRayPayloadKHR = 5342, + StorageClassIncomingRayPayloadNV = 5342, + StorageClassShaderRecordBufferKHR = 5343, + StorageClassShaderRecordBufferNV = 5343, + StorageClassPhysicalStorageBuffer = 5349, + StorageClassPhysicalStorageBufferEXT = 5349, + StorageClassMax = 0x7fffffff, +}; + +enum Dim { + Dim1D = 0, + Dim2D = 1, + Dim3D = 2, + DimCube = 3, + DimRect = 4, + DimBuffer = 5, + DimSubpassData = 6, + DimMax = 0x7fffffff, +}; + +enum SamplerAddressingMode { + SamplerAddressingModeNone = 0, + SamplerAddressingModeClampToEdge = 1, + SamplerAddressingModeClamp = 2, + SamplerAddressingModeRepeat = 3, + SamplerAddressingModeRepeatMirrored = 4, + SamplerAddressingModeMax = 0x7fffffff, +}; + +enum SamplerFilterMode { + SamplerFilterModeNearest = 0, + SamplerFilterModeLinear = 1, + SamplerFilterModeMax = 0x7fffffff, +}; + +enum ImageFormat { + ImageFormatUnknown = 0, + ImageFormatRgba32f = 1, + ImageFormatRgba16f = 2, + ImageFormatR32f = 3, + ImageFormatRgba8 = 4, + ImageFormatRgba8Snorm = 5, + ImageFormatRg32f = 6, + ImageFormatRg16f = 7, + ImageFormatR11fG11fB10f = 8, + ImageFormatR16f = 9, + ImageFormatRgba16 = 10, + ImageFormatRgb10A2 = 11, + ImageFormatRg16 = 12, + ImageFormatRg8 = 13, + ImageFormatR16 = 14, + ImageFormatR8 = 15, + ImageFormatRgba16Snorm = 16, + ImageFormatRg16Snorm = 17, + ImageFormatRg8Snorm = 18, + ImageFormatR16Snorm = 19, + ImageFormatR8Snorm = 20, + ImageFormatRgba32i = 21, + ImageFormatRgba16i = 22, + ImageFormatRgba8i = 23, + ImageFormatR32i = 24, + ImageFormatRg32i = 25, + ImageFormatRg16i = 26, + ImageFormatRg8i = 27, + ImageFormatR16i = 28, + ImageFormatR8i = 29, + ImageFormatRgba32ui = 30, + ImageFormatRgba16ui = 31, + ImageFormatRgba8ui = 32, + ImageFormatR32ui = 33, + ImageFormatRgb10a2ui = 34, + ImageFormatRg32ui = 35, + ImageFormatRg16ui = 36, + ImageFormatRg8ui = 37, + ImageFormatR16ui = 38, + ImageFormatR8ui = 39, + ImageFormatMax = 0x7fffffff, +}; + +enum ImageChannelOrder { + ImageChannelOrderR = 0, + ImageChannelOrderA = 1, + ImageChannelOrderRG = 2, + ImageChannelOrderRA = 3, + ImageChannelOrderRGB = 4, + ImageChannelOrderRGBA = 5, + ImageChannelOrderBGRA = 6, + ImageChannelOrderARGB = 7, + ImageChannelOrderIntensity = 8, + ImageChannelOrderLuminance = 9, + ImageChannelOrderRx = 10, + ImageChannelOrderRGx = 11, + ImageChannelOrderRGBx = 12, + ImageChannelOrderDepth = 13, + ImageChannelOrderDepthStencil = 14, + ImageChannelOrdersRGB = 15, + ImageChannelOrdersRGBx = 16, + ImageChannelOrdersRGBA = 17, + ImageChannelOrdersBGRA = 18, + ImageChannelOrderABGR = 19, + ImageChannelOrderMax = 0x7fffffff, +}; + +enum ImageChannelDataType { + ImageChannelDataTypeSnormInt8 = 0, + ImageChannelDataTypeSnormInt16 = 1, + ImageChannelDataTypeUnormInt8 = 2, + ImageChannelDataTypeUnormInt16 = 3, + ImageChannelDataTypeUnormShort565 = 4, + ImageChannelDataTypeUnormShort555 = 5, + ImageChannelDataTypeUnormInt101010 = 6, + ImageChannelDataTypeSignedInt8 = 7, + ImageChannelDataTypeSignedInt16 = 8, + ImageChannelDataTypeSignedInt32 = 9, + ImageChannelDataTypeUnsignedInt8 = 10, + ImageChannelDataTypeUnsignedInt16 = 11, + ImageChannelDataTypeUnsignedInt32 = 12, + ImageChannelDataTypeHalfFloat = 13, + ImageChannelDataTypeFloat = 14, + ImageChannelDataTypeUnormInt24 = 15, + ImageChannelDataTypeUnormInt101010_2 = 16, + ImageChannelDataTypeMax = 0x7fffffff, +}; + +enum ImageOperandsShift { + ImageOperandsBiasShift = 0, + ImageOperandsLodShift = 1, + ImageOperandsGradShift = 2, + ImageOperandsConstOffsetShift = 3, + ImageOperandsOffsetShift = 4, + ImageOperandsConstOffsetsShift = 5, + ImageOperandsSampleShift = 6, + ImageOperandsMinLodShift = 7, + ImageOperandsMakeTexelAvailableShift = 8, + ImageOperandsMakeTexelAvailableKHRShift = 8, + ImageOperandsMakeTexelVisibleShift = 9, + ImageOperandsMakeTexelVisibleKHRShift = 9, + ImageOperandsNonPrivateTexelShift = 10, + ImageOperandsNonPrivateTexelKHRShift = 10, + ImageOperandsVolatileTexelShift = 11, + ImageOperandsVolatileTexelKHRShift = 11, + ImageOperandsSignExtendShift = 12, + ImageOperandsZeroExtendShift = 13, + ImageOperandsMax = 0x7fffffff, +}; + +enum ImageOperandsMask { + ImageOperandsMaskNone = 0, + ImageOperandsBiasMask = 0x00000001, + ImageOperandsLodMask = 0x00000002, + ImageOperandsGradMask = 0x00000004, + ImageOperandsConstOffsetMask = 0x00000008, + ImageOperandsOffsetMask = 0x00000010, + ImageOperandsConstOffsetsMask = 0x00000020, + ImageOperandsSampleMask = 0x00000040, + ImageOperandsMinLodMask = 0x00000080, + ImageOperandsMakeTexelAvailableMask = 0x00000100, + ImageOperandsMakeTexelAvailableKHRMask = 0x00000100, + ImageOperandsMakeTexelVisibleMask = 0x00000200, + ImageOperandsMakeTexelVisibleKHRMask = 0x00000200, + ImageOperandsNonPrivateTexelMask = 0x00000400, + ImageOperandsNonPrivateTexelKHRMask = 0x00000400, + ImageOperandsVolatileTexelMask = 0x00000800, + ImageOperandsVolatileTexelKHRMask = 0x00000800, + ImageOperandsSignExtendMask = 0x00001000, + ImageOperandsZeroExtendMask = 0x00002000, +}; + +enum FPFastMathModeShift { + FPFastMathModeNotNaNShift = 0, + FPFastMathModeNotInfShift = 1, + FPFastMathModeNSZShift = 2, + FPFastMathModeAllowRecipShift = 3, + FPFastMathModeFastShift = 4, + FPFastMathModeMax = 0x7fffffff, +}; + +enum FPFastMathModeMask { + FPFastMathModeMaskNone = 0, + FPFastMathModeNotNaNMask = 0x00000001, + FPFastMathModeNotInfMask = 0x00000002, + FPFastMathModeNSZMask = 0x00000004, + FPFastMathModeAllowRecipMask = 0x00000008, + FPFastMathModeFastMask = 0x00000010, +}; + +enum FPRoundingMode { + FPRoundingModeRTE = 0, + FPRoundingModeRTZ = 1, + FPRoundingModeRTP = 2, + FPRoundingModeRTN = 3, + FPRoundingModeMax = 0x7fffffff, +}; + +enum LinkageType { + LinkageTypeExport = 0, + LinkageTypeImport = 1, + LinkageTypeMax = 0x7fffffff, +}; + +enum AccessQualifier { + AccessQualifierReadOnly = 0, + AccessQualifierWriteOnly = 1, + AccessQualifierReadWrite = 2, + AccessQualifierMax = 0x7fffffff, +}; + +enum FunctionParameterAttribute { + FunctionParameterAttributeZext = 0, + FunctionParameterAttributeSext = 1, + FunctionParameterAttributeByVal = 2, + FunctionParameterAttributeSret = 3, + FunctionParameterAttributeNoAlias = 4, + FunctionParameterAttributeNoCapture = 5, + FunctionParameterAttributeNoWrite = 6, + FunctionParameterAttributeNoReadWrite = 7, + FunctionParameterAttributeMax = 0x7fffffff, +}; + +enum Decoration { + DecorationRelaxedPrecision = 0, + DecorationSpecId = 1, + DecorationBlock = 2, + DecorationBufferBlock = 3, + DecorationRowMajor = 4, + DecorationColMajor = 5, + DecorationArrayStride = 6, + DecorationMatrixStride = 7, + DecorationGLSLShared = 8, + DecorationGLSLPacked = 9, + DecorationCPacked = 10, + DecorationBuiltIn = 11, + DecorationNoPerspective = 13, + DecorationFlat = 14, + DecorationPatch = 15, + DecorationCentroid = 16, + DecorationSample = 17, + DecorationInvariant = 18, + DecorationRestrict = 19, + DecorationAliased = 20, + DecorationVolatile = 21, + DecorationConstant = 22, + DecorationCoherent = 23, + DecorationNonWritable = 24, + DecorationNonReadable = 25, + DecorationUniform = 26, + DecorationUniformId = 27, + DecorationSaturatedConversion = 28, + DecorationStream = 29, + DecorationLocation = 30, + DecorationComponent = 31, + DecorationIndex = 32, + DecorationBinding = 33, + DecorationDescriptorSet = 34, + DecorationOffset = 35, + DecorationXfbBuffer = 36, + DecorationXfbStride = 37, + DecorationFuncParamAttr = 38, + DecorationFPRoundingMode = 39, + DecorationFPFastMathMode = 40, + DecorationLinkageAttributes = 41, + DecorationNoContraction = 42, + DecorationInputAttachmentIndex = 43, + DecorationAlignment = 44, + DecorationMaxByteOffset = 45, + DecorationAlignmentId = 46, + DecorationMaxByteOffsetId = 47, + DecorationNoSignedWrap = 4469, + DecorationNoUnsignedWrap = 4470, + DecorationExplicitInterpAMD = 4999, + DecorationOverrideCoverageNV = 5248, + DecorationPassthroughNV = 5250, + DecorationViewportRelativeNV = 5252, + DecorationSecondaryViewportRelativeNV = 5256, + DecorationPerPrimitiveNV = 5271, + DecorationPerViewNV = 5272, + DecorationPerTaskNV = 5273, + DecorationPerVertexNV = 5285, + DecorationNonUniform = 5300, + DecorationNonUniformEXT = 5300, + DecorationRestrictPointer = 5355, + DecorationRestrictPointerEXT = 5355, + DecorationAliasedPointer = 5356, + DecorationAliasedPointerEXT = 5356, + DecorationCounterBuffer = 5634, + DecorationHlslCounterBufferGOOGLE = 5634, + DecorationHlslSemanticGOOGLE = 5635, + DecorationUserSemantic = 5635, + DecorationUserTypeGOOGLE = 5636, + DecorationMax = 0x7fffffff, +}; + +enum BuiltIn { + BuiltInPosition = 0, + BuiltInPointSize = 1, + BuiltInClipDistance = 3, + BuiltInCullDistance = 4, + BuiltInVertexId = 5, + BuiltInInstanceId = 6, + BuiltInPrimitiveId = 7, + BuiltInInvocationId = 8, + BuiltInLayer = 9, + BuiltInViewportIndex = 10, + BuiltInTessLevelOuter = 11, + BuiltInTessLevelInner = 12, + BuiltInTessCoord = 13, + BuiltInPatchVertices = 14, + BuiltInFragCoord = 15, + BuiltInPointCoord = 16, + BuiltInFrontFacing = 17, + BuiltInSampleId = 18, + BuiltInSamplePosition = 19, + BuiltInSampleMask = 20, + BuiltInFragDepth = 22, + BuiltInHelperInvocation = 23, + BuiltInNumWorkgroups = 24, + BuiltInWorkgroupSize = 25, + BuiltInWorkgroupId = 26, + BuiltInLocalInvocationId = 27, + BuiltInGlobalInvocationId = 28, + BuiltInLocalInvocationIndex = 29, + BuiltInWorkDim = 30, + BuiltInGlobalSize = 31, + BuiltInEnqueuedWorkgroupSize = 32, + BuiltInGlobalOffset = 33, + BuiltInGlobalLinearId = 34, + BuiltInSubgroupSize = 36, + BuiltInSubgroupMaxSize = 37, + BuiltInNumSubgroups = 38, + BuiltInNumEnqueuedSubgroups = 39, + BuiltInSubgroupId = 40, + BuiltInSubgroupLocalInvocationId = 41, + BuiltInVertexIndex = 42, + BuiltInInstanceIndex = 43, + BuiltInSubgroupEqMask = 4416, + BuiltInSubgroupEqMaskKHR = 4416, + BuiltInSubgroupGeMask = 4417, + BuiltInSubgroupGeMaskKHR = 4417, + BuiltInSubgroupGtMask = 4418, + BuiltInSubgroupGtMaskKHR = 4418, + BuiltInSubgroupLeMask = 4419, + BuiltInSubgroupLeMaskKHR = 4419, + BuiltInSubgroupLtMask = 4420, + BuiltInSubgroupLtMaskKHR = 4420, + BuiltInBaseVertex = 4424, + BuiltInBaseInstance = 4425, + BuiltInDrawIndex = 4426, + BuiltInDeviceIndex = 4438, + BuiltInViewIndex = 4440, + BuiltInBaryCoordNoPerspAMD = 4992, + BuiltInBaryCoordNoPerspCentroidAMD = 4993, + BuiltInBaryCoordNoPerspSampleAMD = 4994, + BuiltInBaryCoordSmoothAMD = 4995, + BuiltInBaryCoordSmoothCentroidAMD = 4996, + BuiltInBaryCoordSmoothSampleAMD = 4997, + BuiltInBaryCoordPullModelAMD = 4998, + BuiltInFragStencilRefEXT = 5014, + BuiltInViewportMaskNV = 5253, + BuiltInSecondaryPositionNV = 5257, + BuiltInSecondaryViewportMaskNV = 5258, + BuiltInPositionPerViewNV = 5261, + BuiltInViewportMaskPerViewNV = 5262, + BuiltInFullyCoveredEXT = 5264, + BuiltInTaskCountNV = 5274, + BuiltInPrimitiveCountNV = 5275, + BuiltInPrimitiveIndicesNV = 5276, + BuiltInClipDistancePerViewNV = 5277, + BuiltInCullDistancePerViewNV = 5278, + BuiltInLayerPerViewNV = 5279, + BuiltInMeshViewCountNV = 5280, + BuiltInMeshViewIndicesNV = 5281, + BuiltInBaryCoordNV = 5286, + BuiltInBaryCoordNoPerspNV = 5287, + BuiltInFragSizeEXT = 5292, + BuiltInFragmentSizeNV = 5292, + BuiltInFragInvocationCountEXT = 5293, + BuiltInInvocationsPerPixelNV = 5293, + BuiltInLaunchIdKHR = 5319, + BuiltInLaunchIdNV = 5319, + BuiltInLaunchSizeKHR = 5320, + BuiltInLaunchSizeNV = 5320, + BuiltInWorldRayOriginKHR = 5321, + BuiltInWorldRayOriginNV = 5321, + BuiltInWorldRayDirectionKHR = 5322, + BuiltInWorldRayDirectionNV = 5322, + BuiltInObjectRayOriginKHR = 5323, + BuiltInObjectRayOriginNV = 5323, + BuiltInObjectRayDirectionKHR = 5324, + BuiltInObjectRayDirectionNV = 5324, + BuiltInRayTminKHR = 5325, + BuiltInRayTminNV = 5325, + BuiltInRayTmaxKHR = 5326, + BuiltInRayTmaxNV = 5326, + BuiltInInstanceCustomIndexKHR = 5327, + BuiltInInstanceCustomIndexNV = 5327, + BuiltInObjectToWorldKHR = 5330, + BuiltInObjectToWorldNV = 5330, + BuiltInWorldToObjectKHR = 5331, + BuiltInWorldToObjectNV = 5331, + BuiltInHitTKHR = 5332, + BuiltInHitTNV = 5332, + BuiltInHitKindKHR = 5333, + BuiltInHitKindNV = 5333, + BuiltInIncomingRayFlagsKHR = 5351, + BuiltInIncomingRayFlagsNV = 5351, + BuiltInRayGeometryIndexKHR = 5352, + BuiltInWarpsPerSMNV = 5374, + BuiltInSMCountNV = 5375, + BuiltInWarpIDNV = 5376, + BuiltInSMIDNV = 5377, + BuiltInMax = 0x7fffffff, +}; + +enum SelectionControlShift { + SelectionControlFlattenShift = 0, + SelectionControlDontFlattenShift = 1, + SelectionControlMax = 0x7fffffff, +}; + +enum SelectionControlMask { + SelectionControlMaskNone = 0, + SelectionControlFlattenMask = 0x00000001, + SelectionControlDontFlattenMask = 0x00000002, +}; + +enum LoopControlShift { + LoopControlUnrollShift = 0, + LoopControlDontUnrollShift = 1, + LoopControlDependencyInfiniteShift = 2, + LoopControlDependencyLengthShift = 3, + LoopControlMinIterationsShift = 4, + LoopControlMaxIterationsShift = 5, + LoopControlIterationMultipleShift = 6, + LoopControlPeelCountShift = 7, + LoopControlPartialCountShift = 8, + LoopControlMax = 0x7fffffff, +}; + +enum LoopControlMask { + LoopControlMaskNone = 0, + LoopControlUnrollMask = 0x00000001, + LoopControlDontUnrollMask = 0x00000002, + LoopControlDependencyInfiniteMask = 0x00000004, + LoopControlDependencyLengthMask = 0x00000008, + LoopControlMinIterationsMask = 0x00000010, + LoopControlMaxIterationsMask = 0x00000020, + LoopControlIterationMultipleMask = 0x00000040, + LoopControlPeelCountMask = 0x00000080, + LoopControlPartialCountMask = 0x00000100, +}; + +enum FunctionControlShift { + FunctionControlInlineShift = 0, + FunctionControlDontInlineShift = 1, + FunctionControlPureShift = 2, + FunctionControlConstShift = 3, + FunctionControlMax = 0x7fffffff, +}; + +enum FunctionControlMask { + FunctionControlMaskNone = 0, + FunctionControlInlineMask = 0x00000001, + FunctionControlDontInlineMask = 0x00000002, + FunctionControlPureMask = 0x00000004, + FunctionControlConstMask = 0x00000008, +}; + +enum MemorySemanticsShift { + MemorySemanticsAcquireShift = 1, + MemorySemanticsReleaseShift = 2, + MemorySemanticsAcquireReleaseShift = 3, + MemorySemanticsSequentiallyConsistentShift = 4, + MemorySemanticsUniformMemoryShift = 6, + MemorySemanticsSubgroupMemoryShift = 7, + MemorySemanticsWorkgroupMemoryShift = 8, + MemorySemanticsCrossWorkgroupMemoryShift = 9, + MemorySemanticsAtomicCounterMemoryShift = 10, + MemorySemanticsImageMemoryShift = 11, + MemorySemanticsOutputMemoryShift = 12, + MemorySemanticsOutputMemoryKHRShift = 12, + MemorySemanticsMakeAvailableShift = 13, + MemorySemanticsMakeAvailableKHRShift = 13, + MemorySemanticsMakeVisibleShift = 14, + MemorySemanticsMakeVisibleKHRShift = 14, + MemorySemanticsVolatileShift = 15, + MemorySemanticsMax = 0x7fffffff, +}; + +enum MemorySemanticsMask { + MemorySemanticsMaskNone = 0, + MemorySemanticsAcquireMask = 0x00000002, + MemorySemanticsReleaseMask = 0x00000004, + MemorySemanticsAcquireReleaseMask = 0x00000008, + MemorySemanticsSequentiallyConsistentMask = 0x00000010, + MemorySemanticsUniformMemoryMask = 0x00000040, + MemorySemanticsSubgroupMemoryMask = 0x00000080, + MemorySemanticsWorkgroupMemoryMask = 0x00000100, + MemorySemanticsCrossWorkgroupMemoryMask = 0x00000200, + MemorySemanticsAtomicCounterMemoryMask = 0x00000400, + MemorySemanticsImageMemoryMask = 0x00000800, + MemorySemanticsOutputMemoryMask = 0x00001000, + MemorySemanticsOutputMemoryKHRMask = 0x00001000, + MemorySemanticsMakeAvailableMask = 0x00002000, + MemorySemanticsMakeAvailableKHRMask = 0x00002000, + MemorySemanticsMakeVisibleMask = 0x00004000, + MemorySemanticsMakeVisibleKHRMask = 0x00004000, + MemorySemanticsVolatileMask = 0x00008000, +}; + +enum MemoryAccessShift { + MemoryAccessVolatileShift = 0, + MemoryAccessAlignedShift = 1, + MemoryAccessNontemporalShift = 2, + MemoryAccessMakePointerAvailableShift = 3, + MemoryAccessMakePointerAvailableKHRShift = 3, + MemoryAccessMakePointerVisibleShift = 4, + MemoryAccessMakePointerVisibleKHRShift = 4, + MemoryAccessNonPrivatePointerShift = 5, + MemoryAccessNonPrivatePointerKHRShift = 5, + MemoryAccessMax = 0x7fffffff, +}; + +enum MemoryAccessMask { + MemoryAccessMaskNone = 0, + MemoryAccessVolatileMask = 0x00000001, + MemoryAccessAlignedMask = 0x00000002, + MemoryAccessNontemporalMask = 0x00000004, + MemoryAccessMakePointerAvailableMask = 0x00000008, + MemoryAccessMakePointerAvailableKHRMask = 0x00000008, + MemoryAccessMakePointerVisibleMask = 0x00000010, + MemoryAccessMakePointerVisibleKHRMask = 0x00000010, + MemoryAccessNonPrivatePointerMask = 0x00000020, + MemoryAccessNonPrivatePointerKHRMask = 0x00000020, +}; + +enum Scope { + ScopeCrossDevice = 0, + ScopeDevice = 1, + ScopeWorkgroup = 2, + ScopeSubgroup = 3, + ScopeInvocation = 4, + ScopeQueueFamily = 5, + ScopeQueueFamilyKHR = 5, + ScopeShaderCallKHR = 6, + ScopeMax = 0x7fffffff, +}; + +enum GroupOperation { + GroupOperationReduce = 0, + GroupOperationInclusiveScan = 1, + GroupOperationExclusiveScan = 2, + GroupOperationClusteredReduce = 3, + GroupOperationPartitionedReduceNV = 6, + GroupOperationPartitionedInclusiveScanNV = 7, + GroupOperationPartitionedExclusiveScanNV = 8, + GroupOperationMax = 0x7fffffff, +}; + +enum KernelEnqueueFlags { + KernelEnqueueFlagsNoWait = 0, + KernelEnqueueFlagsWaitKernel = 1, + KernelEnqueueFlagsWaitWorkGroup = 2, + KernelEnqueueFlagsMax = 0x7fffffff, +}; + +enum KernelProfilingInfoShift { + KernelProfilingInfoCmdExecTimeShift = 0, + KernelProfilingInfoMax = 0x7fffffff, +}; + +enum KernelProfilingInfoMask { + KernelProfilingInfoMaskNone = 0, + KernelProfilingInfoCmdExecTimeMask = 0x00000001, +}; + +enum Capability { + CapabilityMatrix = 0, + CapabilityShader = 1, + CapabilityGeometry = 2, + CapabilityTessellation = 3, + CapabilityAddresses = 4, + CapabilityLinkage = 5, + CapabilityKernel = 6, + CapabilityVector16 = 7, + CapabilityFloat16Buffer = 8, + CapabilityFloat16 = 9, + CapabilityFloat64 = 10, + CapabilityInt64 = 11, + CapabilityInt64Atomics = 12, + CapabilityImageBasic = 13, + CapabilityImageReadWrite = 14, + CapabilityImageMipmap = 15, + CapabilityPipes = 17, + CapabilityGroups = 18, + CapabilityDeviceEnqueue = 19, + CapabilityLiteralSampler = 20, + CapabilityAtomicStorage = 21, + CapabilityInt16 = 22, + CapabilityTessellationPointSize = 23, + CapabilityGeometryPointSize = 24, + CapabilityImageGatherExtended = 25, + CapabilityStorageImageMultisample = 27, + CapabilityUniformBufferArrayDynamicIndexing = 28, + CapabilitySampledImageArrayDynamicIndexing = 29, + CapabilityStorageBufferArrayDynamicIndexing = 30, + CapabilityStorageImageArrayDynamicIndexing = 31, + CapabilityClipDistance = 32, + CapabilityCullDistance = 33, + CapabilityImageCubeArray = 34, + CapabilitySampleRateShading = 35, + CapabilityImageRect = 36, + CapabilitySampledRect = 37, + CapabilityGenericPointer = 38, + CapabilityInt8 = 39, + CapabilityInputAttachment = 40, + CapabilitySparseResidency = 41, + CapabilityMinLod = 42, + CapabilitySampled1D = 43, + CapabilityImage1D = 44, + CapabilitySampledCubeArray = 45, + CapabilitySampledBuffer = 46, + CapabilityImageBuffer = 47, + CapabilityImageMSArray = 48, + CapabilityStorageImageExtendedFormats = 49, + CapabilityImageQuery = 50, + CapabilityDerivativeControl = 51, + CapabilityInterpolationFunction = 52, + CapabilityTransformFeedback = 53, + CapabilityGeometryStreams = 54, + CapabilityStorageImageReadWithoutFormat = 55, + CapabilityStorageImageWriteWithoutFormat = 56, + CapabilityMultiViewport = 57, + CapabilitySubgroupDispatch = 58, + CapabilityNamedBarrier = 59, + CapabilityPipeStorage = 60, + CapabilityGroupNonUniform = 61, + CapabilityGroupNonUniformVote = 62, + CapabilityGroupNonUniformArithmetic = 63, + CapabilityGroupNonUniformBallot = 64, + CapabilityGroupNonUniformShuffle = 65, + CapabilityGroupNonUniformShuffleRelative = 66, + CapabilityGroupNonUniformClustered = 67, + CapabilityGroupNonUniformQuad = 68, + CapabilityShaderLayer = 69, + CapabilityShaderViewportIndex = 70, + CapabilitySubgroupBallotKHR = 4423, + CapabilityDrawParameters = 4427, + CapabilitySubgroupVoteKHR = 4431, + CapabilityStorageBuffer16BitAccess = 4433, + CapabilityStorageUniformBufferBlock16 = 4433, + CapabilityStorageUniform16 = 4434, + CapabilityUniformAndStorageBuffer16BitAccess = 4434, + CapabilityStoragePushConstant16 = 4435, + CapabilityStorageInputOutput16 = 4436, + CapabilityDeviceGroup = 4437, + CapabilityMultiView = 4439, + CapabilityVariablePointersStorageBuffer = 4441, + CapabilityVariablePointers = 4442, + CapabilityAtomicStorageOps = 4445, + CapabilitySampleMaskPostDepthCoverage = 4447, + CapabilityStorageBuffer8BitAccess = 4448, + CapabilityUniformAndStorageBuffer8BitAccess = 4449, + CapabilityStoragePushConstant8 = 4450, + CapabilityDenormPreserve = 4464, + CapabilityDenormFlushToZero = 4465, + CapabilitySignedZeroInfNanPreserve = 4466, + CapabilityRoundingModeRTE = 4467, + CapabilityRoundingModeRTZ = 4468, + CapabilityRayQueryProvisionalKHR = 4471, + CapabilityRayTraversalPrimitiveCullingProvisionalKHR = 4478, + CapabilityFloat16ImageAMD = 5008, + CapabilityImageGatherBiasLodAMD = 5009, + CapabilityFragmentMaskAMD = 5010, + CapabilityStencilExportEXT = 5013, + CapabilityImageReadWriteLodAMD = 5015, + CapabilityShaderClockKHR = 5055, + CapabilitySampleMaskOverrideCoverageNV = 5249, + CapabilityGeometryShaderPassthroughNV = 5251, + CapabilityShaderViewportIndexLayerEXT = 5254, + CapabilityShaderViewportIndexLayerNV = 5254, + CapabilityShaderViewportMaskNV = 5255, + CapabilityShaderStereoViewNV = 5259, + CapabilityPerViewAttributesNV = 5260, + CapabilityFragmentFullyCoveredEXT = 5265, + CapabilityMeshShadingNV = 5266, + CapabilityImageFootprintNV = 5282, + CapabilityFragmentBarycentricNV = 5284, + CapabilityComputeDerivativeGroupQuadsNV = 5288, + CapabilityFragmentDensityEXT = 5291, + CapabilityShadingRateNV = 5291, + CapabilityGroupNonUniformPartitionedNV = 5297, + CapabilityShaderNonUniform = 5301, + CapabilityShaderNonUniformEXT = 5301, + CapabilityRuntimeDescriptorArray = 5302, + CapabilityRuntimeDescriptorArrayEXT = 5302, + CapabilityInputAttachmentArrayDynamicIndexing = 5303, + CapabilityInputAttachmentArrayDynamicIndexingEXT = 5303, + CapabilityUniformTexelBufferArrayDynamicIndexing = 5304, + CapabilityUniformTexelBufferArrayDynamicIndexingEXT = 5304, + CapabilityStorageTexelBufferArrayDynamicIndexing = 5305, + CapabilityStorageTexelBufferArrayDynamicIndexingEXT = 5305, + CapabilityUniformBufferArrayNonUniformIndexing = 5306, + CapabilityUniformBufferArrayNonUniformIndexingEXT = 5306, + CapabilitySampledImageArrayNonUniformIndexing = 5307, + CapabilitySampledImageArrayNonUniformIndexingEXT = 5307, + CapabilityStorageBufferArrayNonUniformIndexing = 5308, + CapabilityStorageBufferArrayNonUniformIndexingEXT = 5308, + CapabilityStorageImageArrayNonUniformIndexing = 5309, + CapabilityStorageImageArrayNonUniformIndexingEXT = 5309, + CapabilityInputAttachmentArrayNonUniformIndexing = 5310, + CapabilityInputAttachmentArrayNonUniformIndexingEXT = 5310, + CapabilityUniformTexelBufferArrayNonUniformIndexing = 5311, + CapabilityUniformTexelBufferArrayNonUniformIndexingEXT = 5311, + CapabilityStorageTexelBufferArrayNonUniformIndexing = 5312, + CapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312, + CapabilityRayTracingNV = 5340, + CapabilityVulkanMemoryModel = 5345, + CapabilityVulkanMemoryModelKHR = 5345, + CapabilityVulkanMemoryModelDeviceScope = 5346, + CapabilityVulkanMemoryModelDeviceScopeKHR = 5346, + CapabilityPhysicalStorageBufferAddresses = 5347, + CapabilityPhysicalStorageBufferAddressesEXT = 5347, + CapabilityComputeDerivativeGroupLinearNV = 5350, + CapabilityRayTracingProvisionalKHR = 5353, + CapabilityCooperativeMatrixNV = 5357, + CapabilityFragmentShaderSampleInterlockEXT = 5363, + CapabilityFragmentShaderShadingRateInterlockEXT = 5372, + CapabilityShaderSMBuiltinsNV = 5373, + CapabilityFragmentShaderPixelInterlockEXT = 5378, + CapabilityDemoteToHelperInvocationEXT = 5379, + CapabilitySubgroupShuffleINTEL = 5568, + CapabilitySubgroupBufferBlockIOINTEL = 5569, + CapabilitySubgroupImageBlockIOINTEL = 5570, + CapabilitySubgroupImageMediaBlockIOINTEL = 5579, + CapabilityIntegerFunctions2INTEL = 5584, + CapabilitySubgroupAvcMotionEstimationINTEL = 5696, + CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697, + CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698, + CapabilityMax = 0x7fffffff, +}; + +enum RayFlagsShift { + RayFlagsOpaqueKHRShift = 0, + RayFlagsNoOpaqueKHRShift = 1, + RayFlagsTerminateOnFirstHitKHRShift = 2, + RayFlagsSkipClosestHitShaderKHRShift = 3, + RayFlagsCullBackFacingTrianglesKHRShift = 4, + RayFlagsCullFrontFacingTrianglesKHRShift = 5, + RayFlagsCullOpaqueKHRShift = 6, + RayFlagsCullNoOpaqueKHRShift = 7, + RayFlagsSkipTrianglesKHRShift = 8, + RayFlagsSkipAABBsKHRShift = 9, + RayFlagsMax = 0x7fffffff, +}; + +enum RayFlagsMask { + RayFlagsMaskNone = 0, + RayFlagsOpaqueKHRMask = 0x00000001, + RayFlagsNoOpaqueKHRMask = 0x00000002, + RayFlagsTerminateOnFirstHitKHRMask = 0x00000004, + RayFlagsSkipClosestHitShaderKHRMask = 0x00000008, + RayFlagsCullBackFacingTrianglesKHRMask = 0x00000010, + RayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020, + RayFlagsCullOpaqueKHRMask = 0x00000040, + RayFlagsCullNoOpaqueKHRMask = 0x00000080, + RayFlagsSkipTrianglesKHRMask = 0x00000100, + RayFlagsSkipAABBsKHRMask = 0x00000200, +}; + +enum RayQueryIntersection { + RayQueryIntersectionRayQueryCandidateIntersectionKHR = 0, + RayQueryIntersectionRayQueryCommittedIntersectionKHR = 1, + RayQueryIntersectionMax = 0x7fffffff, +}; + +enum RayQueryCommittedIntersectionType { + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR = 0, + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR = 1, + RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR = 2, + RayQueryCommittedIntersectionTypeMax = 0x7fffffff, +}; + +enum RayQueryCandidateIntersectionType { + RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR = 0, + RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR = 1, + RayQueryCandidateIntersectionTypeMax = 0x7fffffff, +}; + +enum Op { + OpNop = 0, + OpUndef = 1, + OpSourceContinued = 2, + OpSource = 3, + OpSourceExtension = 4, + OpName = 5, + OpMemberName = 6, + OpString = 7, + OpLine = 8, + OpExtension = 10, + OpExtInstImport = 11, + OpExtInst = 12, + OpMemoryModel = 14, + OpEntryPoint = 15, + OpExecutionMode = 16, + OpCapability = 17, + OpTypeVoid = 19, + OpTypeBool = 20, + OpTypeInt = 21, + OpTypeFloat = 22, + OpTypeVector = 23, + OpTypeMatrix = 24, + OpTypeImage = 25, + OpTypeSampler = 26, + OpTypeSampledImage = 27, + OpTypeArray = 28, + OpTypeRuntimeArray = 29, + OpTypeStruct = 30, + OpTypeOpaque = 31, + OpTypePointer = 32, + OpTypeFunction = 33, + OpTypeEvent = 34, + OpTypeDeviceEvent = 35, + OpTypeReserveId = 36, + OpTypeQueue = 37, + OpTypePipe = 38, + OpTypeForwardPointer = 39, + OpConstantTrue = 41, + OpConstantFalse = 42, + OpConstant = 43, + OpConstantComposite = 44, + OpConstantSampler = 45, + OpConstantNull = 46, + OpSpecConstantTrue = 48, + OpSpecConstantFalse = 49, + OpSpecConstant = 50, + OpSpecConstantComposite = 51, + OpSpecConstantOp = 52, + OpFunction = 54, + OpFunctionParameter = 55, + OpFunctionEnd = 56, + OpFunctionCall = 57, + OpVariable = 59, + OpImageTexelPointer = 60, + OpLoad = 61, + OpStore = 62, + OpCopyMemory = 63, + OpCopyMemorySized = 64, + OpAccessChain = 65, + OpInBoundsAccessChain = 66, + OpPtrAccessChain = 67, + OpArrayLength = 68, + OpGenericPtrMemSemantics = 69, + OpInBoundsPtrAccessChain = 70, + OpDecorate = 71, + OpMemberDecorate = 72, + OpDecorationGroup = 73, + OpGroupDecorate = 74, + OpGroupMemberDecorate = 75, + OpVectorExtractDynamic = 77, + OpVectorInsertDynamic = 78, + OpVectorShuffle = 79, + OpCompositeConstruct = 80, + OpCompositeExtract = 81, + OpCompositeInsert = 82, + OpCopyObject = 83, + OpTranspose = 84, + OpSampledImage = 86, + OpImageSampleImplicitLod = 87, + OpImageSampleExplicitLod = 88, + OpImageSampleDrefImplicitLod = 89, + OpImageSampleDrefExplicitLod = 90, + OpImageSampleProjImplicitLod = 91, + OpImageSampleProjExplicitLod = 92, + OpImageSampleProjDrefImplicitLod = 93, + OpImageSampleProjDrefExplicitLod = 94, + OpImageFetch = 95, + OpImageGather = 96, + OpImageDrefGather = 97, + OpImageRead = 98, + OpImageWrite = 99, + OpImage = 100, + OpImageQueryFormat = 101, + OpImageQueryOrder = 102, + OpImageQuerySizeLod = 103, + OpImageQuerySize = 104, + OpImageQueryLod = 105, + OpImageQueryLevels = 106, + OpImageQuerySamples = 107, + OpConvertFToU = 109, + OpConvertFToS = 110, + OpConvertSToF = 111, + OpConvertUToF = 112, + OpUConvert = 113, + OpSConvert = 114, + OpFConvert = 115, + OpQuantizeToF16 = 116, + OpConvertPtrToU = 117, + OpSatConvertSToU = 118, + OpSatConvertUToS = 119, + OpConvertUToPtr = 120, + OpPtrCastToGeneric = 121, + OpGenericCastToPtr = 122, + OpGenericCastToPtrExplicit = 123, + OpBitcast = 124, + OpSNegate = 126, + OpFNegate = 127, + OpIAdd = 128, + OpFAdd = 129, + OpISub = 130, + OpFSub = 131, + OpIMul = 132, + OpFMul = 133, + OpUDiv = 134, + OpSDiv = 135, + OpFDiv = 136, + OpUMod = 137, + OpSRem = 138, + OpSMod = 139, + OpFRem = 140, + OpFMod = 141, + OpVectorTimesScalar = 142, + OpMatrixTimesScalar = 143, + OpVectorTimesMatrix = 144, + OpMatrixTimesVector = 145, + OpMatrixTimesMatrix = 146, + OpOuterProduct = 147, + OpDot = 148, + OpIAddCarry = 149, + OpISubBorrow = 150, + OpUMulExtended = 151, + OpSMulExtended = 152, + OpAny = 154, + OpAll = 155, + OpIsNan = 156, + OpIsInf = 157, + OpIsFinite = 158, + OpIsNormal = 159, + OpSignBitSet = 160, + OpLessOrGreater = 161, + OpOrdered = 162, + OpUnordered = 163, + OpLogicalEqual = 164, + OpLogicalNotEqual = 165, + OpLogicalOr = 166, + OpLogicalAnd = 167, + OpLogicalNot = 168, + OpSelect = 169, + OpIEqual = 170, + OpINotEqual = 171, + OpUGreaterThan = 172, + OpSGreaterThan = 173, + OpUGreaterThanEqual = 174, + OpSGreaterThanEqual = 175, + OpULessThan = 176, + OpSLessThan = 177, + OpULessThanEqual = 178, + OpSLessThanEqual = 179, + OpFOrdEqual = 180, + OpFUnordEqual = 181, + OpFOrdNotEqual = 182, + OpFUnordNotEqual = 183, + OpFOrdLessThan = 184, + OpFUnordLessThan = 185, + OpFOrdGreaterThan = 186, + OpFUnordGreaterThan = 187, + OpFOrdLessThanEqual = 188, + OpFUnordLessThanEqual = 189, + OpFOrdGreaterThanEqual = 190, + OpFUnordGreaterThanEqual = 191, + OpShiftRightLogical = 194, + OpShiftRightArithmetic = 195, + OpShiftLeftLogical = 196, + OpBitwiseOr = 197, + OpBitwiseXor = 198, + OpBitwiseAnd = 199, + OpNot = 200, + OpBitFieldInsert = 201, + OpBitFieldSExtract = 202, + OpBitFieldUExtract = 203, + OpBitReverse = 204, + OpBitCount = 205, + OpDPdx = 207, + OpDPdy = 208, + OpFwidth = 209, + OpDPdxFine = 210, + OpDPdyFine = 211, + OpFwidthFine = 212, + OpDPdxCoarse = 213, + OpDPdyCoarse = 214, + OpFwidthCoarse = 215, + OpEmitVertex = 218, + OpEndPrimitive = 219, + OpEmitStreamVertex = 220, + OpEndStreamPrimitive = 221, + OpControlBarrier = 224, + OpMemoryBarrier = 225, + OpAtomicLoad = 227, + OpAtomicStore = 228, + OpAtomicExchange = 229, + OpAtomicCompareExchange = 230, + OpAtomicCompareExchangeWeak = 231, + OpAtomicIIncrement = 232, + OpAtomicIDecrement = 233, + OpAtomicIAdd = 234, + OpAtomicISub = 235, + OpAtomicSMin = 236, + OpAtomicUMin = 237, + OpAtomicSMax = 238, + OpAtomicUMax = 239, + OpAtomicAnd = 240, + OpAtomicOr = 241, + OpAtomicXor = 242, + OpPhi = 245, + OpLoopMerge = 246, + OpSelectionMerge = 247, + OpLabel = 248, + OpBranch = 249, + OpBranchConditional = 250, + OpSwitch = 251, + OpKill = 252, + OpReturn = 253, + OpReturnValue = 254, + OpUnreachable = 255, + OpLifetimeStart = 256, + OpLifetimeStop = 257, + OpGroupAsyncCopy = 259, + OpGroupWaitEvents = 260, + OpGroupAll = 261, + OpGroupAny = 262, + OpGroupBroadcast = 263, + OpGroupIAdd = 264, + OpGroupFAdd = 265, + OpGroupFMin = 266, + OpGroupUMin = 267, + OpGroupSMin = 268, + OpGroupFMax = 269, + OpGroupUMax = 270, + OpGroupSMax = 271, + OpReadPipe = 274, + OpWritePipe = 275, + OpReservedReadPipe = 276, + OpReservedWritePipe = 277, + OpReserveReadPipePackets = 278, + OpReserveWritePipePackets = 279, + OpCommitReadPipe = 280, + OpCommitWritePipe = 281, + OpIsValidReserveId = 282, + OpGetNumPipePackets = 283, + OpGetMaxPipePackets = 284, + OpGroupReserveReadPipePackets = 285, + OpGroupReserveWritePipePackets = 286, + OpGroupCommitReadPipe = 287, + OpGroupCommitWritePipe = 288, + OpEnqueueMarker = 291, + OpEnqueueKernel = 292, + OpGetKernelNDrangeSubGroupCount = 293, + OpGetKernelNDrangeMaxSubGroupSize = 294, + OpGetKernelWorkGroupSize = 295, + OpGetKernelPreferredWorkGroupSizeMultiple = 296, + OpRetainEvent = 297, + OpReleaseEvent = 298, + OpCreateUserEvent = 299, + OpIsValidEvent = 300, + OpSetUserEventStatus = 301, + OpCaptureEventProfilingInfo = 302, + OpGetDefaultQueue = 303, + OpBuildNDRange = 304, + OpImageSparseSampleImplicitLod = 305, + OpImageSparseSampleExplicitLod = 306, + OpImageSparseSampleDrefImplicitLod = 307, + OpImageSparseSampleDrefExplicitLod = 308, + OpImageSparseSampleProjImplicitLod = 309, + OpImageSparseSampleProjExplicitLod = 310, + OpImageSparseSampleProjDrefImplicitLod = 311, + OpImageSparseSampleProjDrefExplicitLod = 312, + OpImageSparseFetch = 313, + OpImageSparseGather = 314, + OpImageSparseDrefGather = 315, + OpImageSparseTexelsResident = 316, + OpNoLine = 317, + OpAtomicFlagTestAndSet = 318, + OpAtomicFlagClear = 319, + OpImageSparseRead = 320, + OpSizeOf = 321, + OpTypePipeStorage = 322, + OpConstantPipeStorage = 323, + OpCreatePipeFromPipeStorage = 324, + OpGetKernelLocalSizeForSubgroupCount = 325, + OpGetKernelMaxNumSubgroups = 326, + OpTypeNamedBarrier = 327, + OpNamedBarrierInitialize = 328, + OpMemoryNamedBarrier = 329, + OpModuleProcessed = 330, + OpExecutionModeId = 331, + OpDecorateId = 332, + OpGroupNonUniformElect = 333, + OpGroupNonUniformAll = 334, + OpGroupNonUniformAny = 335, + OpGroupNonUniformAllEqual = 336, + OpGroupNonUniformBroadcast = 337, + OpGroupNonUniformBroadcastFirst = 338, + OpGroupNonUniformBallot = 339, + OpGroupNonUniformInverseBallot = 340, + OpGroupNonUniformBallotBitExtract = 341, + OpGroupNonUniformBallotBitCount = 342, + OpGroupNonUniformBallotFindLSB = 343, + OpGroupNonUniformBallotFindMSB = 344, + OpGroupNonUniformShuffle = 345, + OpGroupNonUniformShuffleXor = 346, + OpGroupNonUniformShuffleUp = 347, + OpGroupNonUniformShuffleDown = 348, + OpGroupNonUniformIAdd = 349, + OpGroupNonUniformFAdd = 350, + OpGroupNonUniformIMul = 351, + OpGroupNonUniformFMul = 352, + OpGroupNonUniformSMin = 353, + OpGroupNonUniformUMin = 354, + OpGroupNonUniformFMin = 355, + OpGroupNonUniformSMax = 356, + OpGroupNonUniformUMax = 357, + OpGroupNonUniformFMax = 358, + OpGroupNonUniformBitwiseAnd = 359, + OpGroupNonUniformBitwiseOr = 360, + OpGroupNonUniformBitwiseXor = 361, + OpGroupNonUniformLogicalAnd = 362, + OpGroupNonUniformLogicalOr = 363, + OpGroupNonUniformLogicalXor = 364, + OpGroupNonUniformQuadBroadcast = 365, + OpGroupNonUniformQuadSwap = 366, + OpCopyLogical = 400, + OpPtrEqual = 401, + OpPtrNotEqual = 402, + OpPtrDiff = 403, + OpSubgroupBallotKHR = 4421, + OpSubgroupFirstInvocationKHR = 4422, + OpSubgroupAllKHR = 4428, + OpSubgroupAnyKHR = 4429, + OpSubgroupAllEqualKHR = 4430, + OpSubgroupReadInvocationKHR = 4432, + OpTypeRayQueryProvisionalKHR = 4472, + OpRayQueryInitializeKHR = 4473, + OpRayQueryTerminateKHR = 4474, + OpRayQueryGenerateIntersectionKHR = 4475, + OpRayQueryConfirmIntersectionKHR = 4476, + OpRayQueryProceedKHR = 4477, + OpRayQueryGetIntersectionTypeKHR = 4479, + OpGroupIAddNonUniformAMD = 5000, + OpGroupFAddNonUniformAMD = 5001, + OpGroupFMinNonUniformAMD = 5002, + OpGroupUMinNonUniformAMD = 5003, + OpGroupSMinNonUniformAMD = 5004, + OpGroupFMaxNonUniformAMD = 5005, + OpGroupUMaxNonUniformAMD = 5006, + OpGroupSMaxNonUniformAMD = 5007, + OpFragmentMaskFetchAMD = 5011, + OpFragmentFetchAMD = 5012, + OpReadClockKHR = 5056, + OpImageSampleFootprintNV = 5283, + OpGroupNonUniformPartitionNV = 5296, + OpWritePackedPrimitiveIndices4x8NV = 5299, + OpReportIntersectionKHR = 5334, + OpReportIntersectionNV = 5334, + OpIgnoreIntersectionKHR = 5335, + OpIgnoreIntersectionNV = 5335, + OpTerminateRayKHR = 5336, + OpTerminateRayNV = 5336, + OpTraceNV = 5337, + OpTraceRayKHR = 5337, + OpTypeAccelerationStructureKHR = 5341, + OpTypeAccelerationStructureNV = 5341, + OpExecuteCallableKHR = 5344, + OpExecuteCallableNV = 5344, + OpTypeCooperativeMatrixNV = 5358, + OpCooperativeMatrixLoadNV = 5359, + OpCooperativeMatrixStoreNV = 5360, + OpCooperativeMatrixMulAddNV = 5361, + OpCooperativeMatrixLengthNV = 5362, + OpBeginInvocationInterlockEXT = 5364, + OpEndInvocationInterlockEXT = 5365, + OpDemoteToHelperInvocationEXT = 5380, + OpIsHelperInvocationEXT = 5381, + OpSubgroupShuffleINTEL = 5571, + OpSubgroupShuffleDownINTEL = 5572, + OpSubgroupShuffleUpINTEL = 5573, + OpSubgroupShuffleXorINTEL = 5574, + OpSubgroupBlockReadINTEL = 5575, + OpSubgroupBlockWriteINTEL = 5576, + OpSubgroupImageBlockReadINTEL = 5577, + OpSubgroupImageBlockWriteINTEL = 5578, + OpSubgroupImageMediaBlockReadINTEL = 5580, + OpSubgroupImageMediaBlockWriteINTEL = 5581, + OpUCountLeadingZerosINTEL = 5585, + OpUCountTrailingZerosINTEL = 5586, + OpAbsISubINTEL = 5587, + OpAbsUSubINTEL = 5588, + OpIAddSatINTEL = 5589, + OpUAddSatINTEL = 5590, + OpIAverageINTEL = 5591, + OpUAverageINTEL = 5592, + OpIAverageRoundedINTEL = 5593, + OpUAverageRoundedINTEL = 5594, + OpISubSatINTEL = 5595, + OpUSubSatINTEL = 5596, + OpIMul32x16INTEL = 5597, + OpUMul32x16INTEL = 5598, + OpDecorateString = 5632, + OpDecorateStringGOOGLE = 5632, + OpMemberDecorateString = 5633, + OpMemberDecorateStringGOOGLE = 5633, + OpVmeImageINTEL = 5699, + OpTypeVmeImageINTEL = 5700, + OpTypeAvcImePayloadINTEL = 5701, + OpTypeAvcRefPayloadINTEL = 5702, + OpTypeAvcSicPayloadINTEL = 5703, + OpTypeAvcMcePayloadINTEL = 5704, + OpTypeAvcMceResultINTEL = 5705, + OpTypeAvcImeResultINTEL = 5706, + OpTypeAvcImeResultSingleReferenceStreamoutINTEL = 5707, + OpTypeAvcImeResultDualReferenceStreamoutINTEL = 5708, + OpTypeAvcImeSingleReferenceStreaminINTEL = 5709, + OpTypeAvcImeDualReferenceStreaminINTEL = 5710, + OpTypeAvcRefResultINTEL = 5711, + OpTypeAvcSicResultINTEL = 5712, + OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL = 5713, + OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL = 5714, + OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL = 5715, + OpSubgroupAvcMceSetInterShapePenaltyINTEL = 5716, + OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL = 5717, + OpSubgroupAvcMceSetInterDirectionPenaltyINTEL = 5718, + OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL = 5719, + OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL = 5720, + OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL = 5721, + OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL = 5722, + OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL = 5723, + OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL = 5724, + OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL = 5725, + OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL = 5726, + OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL = 5727, + OpSubgroupAvcMceSetAcOnlyHaarINTEL = 5728, + OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL = 5729, + OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL = 5730, + OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL = 5731, + OpSubgroupAvcMceConvertToImePayloadINTEL = 5732, + OpSubgroupAvcMceConvertToImeResultINTEL = 5733, + OpSubgroupAvcMceConvertToRefPayloadINTEL = 5734, + OpSubgroupAvcMceConvertToRefResultINTEL = 5735, + OpSubgroupAvcMceConvertToSicPayloadINTEL = 5736, + OpSubgroupAvcMceConvertToSicResultINTEL = 5737, + OpSubgroupAvcMceGetMotionVectorsINTEL = 5738, + OpSubgroupAvcMceGetInterDistortionsINTEL = 5739, + OpSubgroupAvcMceGetBestInterDistortionsINTEL = 5740, + OpSubgroupAvcMceGetInterMajorShapeINTEL = 5741, + OpSubgroupAvcMceGetInterMinorShapeINTEL = 5742, + OpSubgroupAvcMceGetInterDirectionsINTEL = 5743, + OpSubgroupAvcMceGetInterMotionVectorCountINTEL = 5744, + OpSubgroupAvcMceGetInterReferenceIdsINTEL = 5745, + OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL = 5746, + OpSubgroupAvcImeInitializeINTEL = 5747, + OpSubgroupAvcImeSetSingleReferenceINTEL = 5748, + OpSubgroupAvcImeSetDualReferenceINTEL = 5749, + OpSubgroupAvcImeRefWindowSizeINTEL = 5750, + OpSubgroupAvcImeAdjustRefOffsetINTEL = 5751, + OpSubgroupAvcImeConvertToMcePayloadINTEL = 5752, + OpSubgroupAvcImeSetMaxMotionVectorCountINTEL = 5753, + OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL = 5754, + OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL = 5755, + OpSubgroupAvcImeSetWeightedSadINTEL = 5756, + OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL = 5757, + OpSubgroupAvcImeEvaluateWithDualReferenceINTEL = 5758, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL = 5759, + OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL = 5760, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL = 5761, + OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL = 5762, + OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL = 5763, + OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL = 5764, + OpSubgroupAvcImeConvertToMceResultINTEL = 5765, + OpSubgroupAvcImeGetSingleReferenceStreaminINTEL = 5766, + OpSubgroupAvcImeGetDualReferenceStreaminINTEL = 5767, + OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL = 5768, + OpSubgroupAvcImeStripDualReferenceStreamoutINTEL = 5769, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL = 5770, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL = 5771, + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL = 5772, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL = 5773, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL = 5774, + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL = 5775, + OpSubgroupAvcImeGetBorderReachedINTEL = 5776, + OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL = 5777, + OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL = 5778, + OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL = 5779, + OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL = 5780, + OpSubgroupAvcFmeInitializeINTEL = 5781, + OpSubgroupAvcBmeInitializeINTEL = 5782, + OpSubgroupAvcRefConvertToMcePayloadINTEL = 5783, + OpSubgroupAvcRefSetBidirectionalMixDisableINTEL = 5784, + OpSubgroupAvcRefSetBilinearFilterEnableINTEL = 5785, + OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL = 5786, + OpSubgroupAvcRefEvaluateWithDualReferenceINTEL = 5787, + OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL = 5788, + OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL = 5789, + OpSubgroupAvcRefConvertToMceResultINTEL = 5790, + OpSubgroupAvcSicInitializeINTEL = 5791, + OpSubgroupAvcSicConfigureSkcINTEL = 5792, + OpSubgroupAvcSicConfigureIpeLumaINTEL = 5793, + OpSubgroupAvcSicConfigureIpeLumaChromaINTEL = 5794, + OpSubgroupAvcSicGetMotionVectorMaskINTEL = 5795, + OpSubgroupAvcSicConvertToMcePayloadINTEL = 5796, + OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL = 5797, + OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL = 5798, + OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL = 5799, + OpSubgroupAvcSicSetBilinearFilterEnableINTEL = 5800, + OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL = 5801, + OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL = 5802, + OpSubgroupAvcSicEvaluateIpeINTEL = 5803, + OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL = 5804, + OpSubgroupAvcSicEvaluateWithDualReferenceINTEL = 5805, + OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL = 5806, + OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL = 5807, + OpSubgroupAvcSicConvertToMceResultINTEL = 5808, + OpSubgroupAvcSicGetIpeLumaShapeINTEL = 5809, + OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL = 5810, + OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL = 5811, + OpSubgroupAvcSicGetPackedIpeLumaModesINTEL = 5812, + OpSubgroupAvcSicGetIpeChromaModeINTEL = 5813, + OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, + OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, + OpSubgroupAvcSicGetInterRawSadsINTEL = 5816, + OpRayQueryGetRayTMinKHR = 6016, + OpRayQueryGetRayFlagsKHR = 6017, + OpRayQueryGetIntersectionTKHR = 6018, + OpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019, + OpRayQueryGetIntersectionInstanceIdKHR = 6020, + OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021, + OpRayQueryGetIntersectionGeometryIndexKHR = 6022, + OpRayQueryGetIntersectionPrimitiveIndexKHR = 6023, + OpRayQueryGetIntersectionBarycentricsKHR = 6024, + OpRayQueryGetIntersectionFrontFaceKHR = 6025, + OpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026, + OpRayQueryGetIntersectionObjectRayDirectionKHR = 6027, + OpRayQueryGetIntersectionObjectRayOriginKHR = 6028, + OpRayQueryGetWorldRayDirectionKHR = 6029, + OpRayQueryGetWorldRayOriginKHR = 6030, + OpRayQueryGetIntersectionObjectToWorldKHR = 6031, + OpRayQueryGetIntersectionWorldToObjectKHR = 6032, + OpMax = 0x7fffffff, +}; + +#ifdef SPV_ENABLE_UTILITY_CODE +inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) { + *hasResult = *hasResultType = false; + switch (opcode) { + default: /* unknown opcode */ break; + case OpNop: *hasResult = false; *hasResultType = false; break; + case OpUndef: *hasResult = true; *hasResultType = true; break; + case OpSourceContinued: *hasResult = false; *hasResultType = false; break; + case OpSource: *hasResult = false; *hasResultType = false; break; + case OpSourceExtension: *hasResult = false; *hasResultType = false; break; + case OpName: *hasResult = false; *hasResultType = false; break; + case OpMemberName: *hasResult = false; *hasResultType = false; break; + case OpString: *hasResult = true; *hasResultType = false; break; + case OpLine: *hasResult = false; *hasResultType = false; break; + case OpExtension: *hasResult = false; *hasResultType = false; break; + case OpExtInstImport: *hasResult = true; *hasResultType = false; break; + case OpExtInst: *hasResult = true; *hasResultType = true; break; + case OpMemoryModel: *hasResult = false; *hasResultType = false; break; + case OpEntryPoint: *hasResult = false; *hasResultType = false; break; + case OpExecutionMode: *hasResult = false; *hasResultType = false; break; + case OpCapability: *hasResult = false; *hasResultType = false; break; + case OpTypeVoid: *hasResult = true; *hasResultType = false; break; + case OpTypeBool: *hasResult = true; *hasResultType = false; break; + case OpTypeInt: *hasResult = true; *hasResultType = false; break; + case OpTypeFloat: *hasResult = true; *hasResultType = false; break; + case OpTypeVector: *hasResult = true; *hasResultType = false; break; + case OpTypeMatrix: *hasResult = true; *hasResultType = false; break; + case OpTypeImage: *hasResult = true; *hasResultType = false; break; + case OpTypeSampler: *hasResult = true; *hasResultType = false; break; + case OpTypeSampledImage: *hasResult = true; *hasResultType = false; break; + case OpTypeArray: *hasResult = true; *hasResultType = false; break; + case OpTypeRuntimeArray: *hasResult = true; *hasResultType = false; break; + case OpTypeStruct: *hasResult = true; *hasResultType = false; break; + case OpTypeOpaque: *hasResult = true; *hasResultType = false; break; + case OpTypePointer: *hasResult = true; *hasResultType = false; break; + case OpTypeFunction: *hasResult = true; *hasResultType = false; break; + case OpTypeEvent: *hasResult = true; *hasResultType = false; break; + case OpTypeDeviceEvent: *hasResult = true; *hasResultType = false; break; + case OpTypeReserveId: *hasResult = true; *hasResultType = false; break; + case OpTypeQueue: *hasResult = true; *hasResultType = false; break; + case OpTypePipe: *hasResult = true; *hasResultType = false; break; + case OpTypeForwardPointer: *hasResult = false; *hasResultType = false; break; + case OpConstantTrue: *hasResult = true; *hasResultType = true; break; + case OpConstantFalse: *hasResult = true; *hasResultType = true; break; + case OpConstant: *hasResult = true; *hasResultType = true; break; + case OpConstantComposite: *hasResult = true; *hasResultType = true; break; + case OpConstantSampler: *hasResult = true; *hasResultType = true; break; + case OpConstantNull: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantTrue: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantFalse: *hasResult = true; *hasResultType = true; break; + case OpSpecConstant: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantComposite: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantOp: *hasResult = true; *hasResultType = true; break; + case OpFunction: *hasResult = true; *hasResultType = true; break; + case OpFunctionParameter: *hasResult = true; *hasResultType = true; break; + case OpFunctionEnd: *hasResult = false; *hasResultType = false; break; + case OpFunctionCall: *hasResult = true; *hasResultType = true; break; + case OpVariable: *hasResult = true; *hasResultType = true; break; + case OpImageTexelPointer: *hasResult = true; *hasResultType = true; break; + case OpLoad: *hasResult = true; *hasResultType = true; break; + case OpStore: *hasResult = false; *hasResultType = false; break; + case OpCopyMemory: *hasResult = false; *hasResultType = false; break; + case OpCopyMemorySized: *hasResult = false; *hasResultType = false; break; + case OpAccessChain: *hasResult = true; *hasResultType = true; break; + case OpInBoundsAccessChain: *hasResult = true; *hasResultType = true; break; + case OpPtrAccessChain: *hasResult = true; *hasResultType = true; break; + case OpArrayLength: *hasResult = true; *hasResultType = true; break; + case OpGenericPtrMemSemantics: *hasResult = true; *hasResultType = true; break; + case OpInBoundsPtrAccessChain: *hasResult = true; *hasResultType = true; break; + case OpDecorate: *hasResult = false; *hasResultType = false; break; + case OpMemberDecorate: *hasResult = false; *hasResultType = false; break; + case OpDecorationGroup: *hasResult = true; *hasResultType = false; break; + case OpGroupDecorate: *hasResult = false; *hasResultType = false; break; + case OpGroupMemberDecorate: *hasResult = false; *hasResultType = false; break; + case OpVectorExtractDynamic: *hasResult = true; *hasResultType = true; break; + case OpVectorInsertDynamic: *hasResult = true; *hasResultType = true; break; + case OpVectorShuffle: *hasResult = true; *hasResultType = true; break; + case OpCompositeConstruct: *hasResult = true; *hasResultType = true; break; + case OpCompositeExtract: *hasResult = true; *hasResultType = true; break; + case OpCompositeInsert: *hasResult = true; *hasResultType = true; break; + case OpCopyObject: *hasResult = true; *hasResultType = true; break; + case OpTranspose: *hasResult = true; *hasResultType = true; break; + case OpSampledImage: *hasResult = true; *hasResultType = true; break; + case OpImageSampleImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageFetch: *hasResult = true; *hasResultType = true; break; + case OpImageGather: *hasResult = true; *hasResultType = true; break; + case OpImageDrefGather: *hasResult = true; *hasResultType = true; break; + case OpImageRead: *hasResult = true; *hasResultType = true; break; + case OpImageWrite: *hasResult = false; *hasResultType = false; break; + case OpImage: *hasResult = true; *hasResultType = true; break; + case OpImageQueryFormat: *hasResult = true; *hasResultType = true; break; + case OpImageQueryOrder: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySizeLod: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySize: *hasResult = true; *hasResultType = true; break; + case OpImageQueryLod: *hasResult = true; *hasResultType = true; break; + case OpImageQueryLevels: *hasResult = true; *hasResultType = true; break; + case OpImageQuerySamples: *hasResult = true; *hasResultType = true; break; + case OpConvertFToU: *hasResult = true; *hasResultType = true; break; + case OpConvertFToS: *hasResult = true; *hasResultType = true; break; + case OpConvertSToF: *hasResult = true; *hasResultType = true; break; + case OpConvertUToF: *hasResult = true; *hasResultType = true; break; + case OpUConvert: *hasResult = true; *hasResultType = true; break; + case OpSConvert: *hasResult = true; *hasResultType = true; break; + case OpFConvert: *hasResult = true; *hasResultType = true; break; + case OpQuantizeToF16: *hasResult = true; *hasResultType = true; break; + case OpConvertPtrToU: *hasResult = true; *hasResultType = true; break; + case OpSatConvertSToU: *hasResult = true; *hasResultType = true; break; + case OpSatConvertUToS: *hasResult = true; *hasResultType = true; break; + case OpConvertUToPtr: *hasResult = true; *hasResultType = true; break; + case OpPtrCastToGeneric: *hasResult = true; *hasResultType = true; break; + case OpGenericCastToPtr: *hasResult = true; *hasResultType = true; break; + case OpGenericCastToPtrExplicit: *hasResult = true; *hasResultType = true; break; + case OpBitcast: *hasResult = true; *hasResultType = true; break; + case OpSNegate: *hasResult = true; *hasResultType = true; break; + case OpFNegate: *hasResult = true; *hasResultType = true; break; + case OpIAdd: *hasResult = true; *hasResultType = true; break; + case OpFAdd: *hasResult = true; *hasResultType = true; break; + case OpISub: *hasResult = true; *hasResultType = true; break; + case OpFSub: *hasResult = true; *hasResultType = true; break; + case OpIMul: *hasResult = true; *hasResultType = true; break; + case OpFMul: *hasResult = true; *hasResultType = true; break; + case OpUDiv: *hasResult = true; *hasResultType = true; break; + case OpSDiv: *hasResult = true; *hasResultType = true; break; + case OpFDiv: *hasResult = true; *hasResultType = true; break; + case OpUMod: *hasResult = true; *hasResultType = true; break; + case OpSRem: *hasResult = true; *hasResultType = true; break; + case OpSMod: *hasResult = true; *hasResultType = true; break; + case OpFRem: *hasResult = true; *hasResultType = true; break; + case OpFMod: *hasResult = true; *hasResultType = true; break; + case OpVectorTimesScalar: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesScalar: *hasResult = true; *hasResultType = true; break; + case OpVectorTimesMatrix: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesVector: *hasResult = true; *hasResultType = true; break; + case OpMatrixTimesMatrix: *hasResult = true; *hasResultType = true; break; + case OpOuterProduct: *hasResult = true; *hasResultType = true; break; + case OpDot: *hasResult = true; *hasResultType = true; break; + case OpIAddCarry: *hasResult = true; *hasResultType = true; break; + case OpISubBorrow: *hasResult = true; *hasResultType = true; break; + case OpUMulExtended: *hasResult = true; *hasResultType = true; break; + case OpSMulExtended: *hasResult = true; *hasResultType = true; break; + case OpAny: *hasResult = true; *hasResultType = true; break; + case OpAll: *hasResult = true; *hasResultType = true; break; + case OpIsNan: *hasResult = true; *hasResultType = true; break; + case OpIsInf: *hasResult = true; *hasResultType = true; break; + case OpIsFinite: *hasResult = true; *hasResultType = true; break; + case OpIsNormal: *hasResult = true; *hasResultType = true; break; + case OpSignBitSet: *hasResult = true; *hasResultType = true; break; + case OpLessOrGreater: *hasResult = true; *hasResultType = true; break; + case OpOrdered: *hasResult = true; *hasResultType = true; break; + case OpUnordered: *hasResult = true; *hasResultType = true; break; + case OpLogicalEqual: *hasResult = true; *hasResultType = true; break; + case OpLogicalNotEqual: *hasResult = true; *hasResultType = true; break; + case OpLogicalOr: *hasResult = true; *hasResultType = true; break; + case OpLogicalAnd: *hasResult = true; *hasResultType = true; break; + case OpLogicalNot: *hasResult = true; *hasResultType = true; break; + case OpSelect: *hasResult = true; *hasResultType = true; break; + case OpIEqual: *hasResult = true; *hasResultType = true; break; + case OpINotEqual: *hasResult = true; *hasResultType = true; break; + case OpUGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpSGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpUGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpSGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpULessThan: *hasResult = true; *hasResultType = true; break; + case OpSLessThan: *hasResult = true; *hasResultType = true; break; + case OpULessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpSLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdNotEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordNotEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdLessThan: *hasResult = true; *hasResultType = true; break; + case OpFUnordLessThan: *hasResult = true; *hasResultType = true; break; + case OpFOrdGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpFUnordGreaterThan: *hasResult = true; *hasResultType = true; break; + case OpFOrdLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordLessThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFOrdGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpFUnordGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case OpShiftRightLogical: *hasResult = true; *hasResultType = true; break; + case OpShiftRightArithmetic: *hasResult = true; *hasResultType = true; break; + case OpShiftLeftLogical: *hasResult = true; *hasResultType = true; break; + case OpBitwiseOr: *hasResult = true; *hasResultType = true; break; + case OpBitwiseXor: *hasResult = true; *hasResultType = true; break; + case OpBitwiseAnd: *hasResult = true; *hasResultType = true; break; + case OpNot: *hasResult = true; *hasResultType = true; break; + case OpBitFieldInsert: *hasResult = true; *hasResultType = true; break; + case OpBitFieldSExtract: *hasResult = true; *hasResultType = true; break; + case OpBitFieldUExtract: *hasResult = true; *hasResultType = true; break; + case OpBitReverse: *hasResult = true; *hasResultType = true; break; + case OpBitCount: *hasResult = true; *hasResultType = true; break; + case OpDPdx: *hasResult = true; *hasResultType = true; break; + case OpDPdy: *hasResult = true; *hasResultType = true; break; + case OpFwidth: *hasResult = true; *hasResultType = true; break; + case OpDPdxFine: *hasResult = true; *hasResultType = true; break; + case OpDPdyFine: *hasResult = true; *hasResultType = true; break; + case OpFwidthFine: *hasResult = true; *hasResultType = true; break; + case OpDPdxCoarse: *hasResult = true; *hasResultType = true; break; + case OpDPdyCoarse: *hasResult = true; *hasResultType = true; break; + case OpFwidthCoarse: *hasResult = true; *hasResultType = true; break; + case OpEmitVertex: *hasResult = false; *hasResultType = false; break; + case OpEndPrimitive: *hasResult = false; *hasResultType = false; break; + case OpEmitStreamVertex: *hasResult = false; *hasResultType = false; break; + case OpEndStreamPrimitive: *hasResult = false; *hasResultType = false; break; + case OpControlBarrier: *hasResult = false; *hasResultType = false; break; + case OpMemoryBarrier: *hasResult = false; *hasResultType = false; break; + case OpAtomicLoad: *hasResult = true; *hasResultType = true; break; + case OpAtomicStore: *hasResult = false; *hasResultType = false; break; + case OpAtomicExchange: *hasResult = true; *hasResultType = true; break; + case OpAtomicCompareExchange: *hasResult = true; *hasResultType = true; break; + case OpAtomicCompareExchangeWeak: *hasResult = true; *hasResultType = true; break; + case OpAtomicIIncrement: *hasResult = true; *hasResultType = true; break; + case OpAtomicIDecrement: *hasResult = true; *hasResultType = true; break; + case OpAtomicIAdd: *hasResult = true; *hasResultType = true; break; + case OpAtomicISub: *hasResult = true; *hasResultType = true; break; + case OpAtomicSMin: *hasResult = true; *hasResultType = true; break; + case OpAtomicUMin: *hasResult = true; *hasResultType = true; break; + case OpAtomicSMax: *hasResult = true; *hasResultType = true; break; + case OpAtomicUMax: *hasResult = true; *hasResultType = true; break; + case OpAtomicAnd: *hasResult = true; *hasResultType = true; break; + case OpAtomicOr: *hasResult = true; *hasResultType = true; break; + case OpAtomicXor: *hasResult = true; *hasResultType = true; break; + case OpPhi: *hasResult = true; *hasResultType = true; break; + case OpLoopMerge: *hasResult = false; *hasResultType = false; break; + case OpSelectionMerge: *hasResult = false; *hasResultType = false; break; + case OpLabel: *hasResult = true; *hasResultType = false; break; + case OpBranch: *hasResult = false; *hasResultType = false; break; + case OpBranchConditional: *hasResult = false; *hasResultType = false; break; + case OpSwitch: *hasResult = false; *hasResultType = false; break; + case OpKill: *hasResult = false; *hasResultType = false; break; + case OpReturn: *hasResult = false; *hasResultType = false; break; + case OpReturnValue: *hasResult = false; *hasResultType = false; break; + case OpUnreachable: *hasResult = false; *hasResultType = false; break; + case OpLifetimeStart: *hasResult = false; *hasResultType = false; break; + case OpLifetimeStop: *hasResult = false; *hasResultType = false; break; + case OpGroupAsyncCopy: *hasResult = true; *hasResultType = true; break; + case OpGroupWaitEvents: *hasResult = false; *hasResultType = false; break; + case OpGroupAll: *hasResult = true; *hasResultType = true; break; + case OpGroupAny: *hasResult = true; *hasResultType = true; break; + case OpGroupBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupIAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupFAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupFMin: *hasResult = true; *hasResultType = true; break; + case OpGroupUMin: *hasResult = true; *hasResultType = true; break; + case OpGroupSMin: *hasResult = true; *hasResultType = true; break; + case OpGroupFMax: *hasResult = true; *hasResultType = true; break; + case OpGroupUMax: *hasResult = true; *hasResultType = true; break; + case OpGroupSMax: *hasResult = true; *hasResultType = true; break; + case OpReadPipe: *hasResult = true; *hasResultType = true; break; + case OpWritePipe: *hasResult = true; *hasResultType = true; break; + case OpReservedReadPipe: *hasResult = true; *hasResultType = true; break; + case OpReservedWritePipe: *hasResult = true; *hasResultType = true; break; + case OpReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; + case OpReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; + case OpCommitReadPipe: *hasResult = false; *hasResultType = false; break; + case OpCommitWritePipe: *hasResult = false; *hasResultType = false; break; + case OpIsValidReserveId: *hasResult = true; *hasResultType = true; break; + case OpGetNumPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGetMaxPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; + case OpGroupCommitReadPipe: *hasResult = false; *hasResultType = false; break; + case OpGroupCommitWritePipe: *hasResult = false; *hasResultType = false; break; + case OpEnqueueMarker: *hasResult = true; *hasResultType = true; break; + case OpEnqueueKernel: *hasResult = true; *hasResultType = true; break; + case OpGetKernelNDrangeSubGroupCount: *hasResult = true; *hasResultType = true; break; + case OpGetKernelNDrangeMaxSubGroupSize: *hasResult = true; *hasResultType = true; break; + case OpGetKernelWorkGroupSize: *hasResult = true; *hasResultType = true; break; + case OpGetKernelPreferredWorkGroupSizeMultiple: *hasResult = true; *hasResultType = true; break; + case OpRetainEvent: *hasResult = false; *hasResultType = false; break; + case OpReleaseEvent: *hasResult = false; *hasResultType = false; break; + case OpCreateUserEvent: *hasResult = true; *hasResultType = true; break; + case OpIsValidEvent: *hasResult = true; *hasResultType = true; break; + case OpSetUserEventStatus: *hasResult = false; *hasResultType = false; break; + case OpCaptureEventProfilingInfo: *hasResult = false; *hasResultType = false; break; + case OpGetDefaultQueue: *hasResult = true; *hasResultType = true; break; + case OpBuildNDRange: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case OpImageSparseFetch: *hasResult = true; *hasResultType = true; break; + case OpImageSparseGather: *hasResult = true; *hasResultType = true; break; + case OpImageSparseDrefGather: *hasResult = true; *hasResultType = true; break; + case OpImageSparseTexelsResident: *hasResult = true; *hasResultType = true; break; + case OpNoLine: *hasResult = false; *hasResultType = false; break; + case OpAtomicFlagTestAndSet: *hasResult = true; *hasResultType = true; break; + case OpAtomicFlagClear: *hasResult = false; *hasResultType = false; break; + case OpImageSparseRead: *hasResult = true; *hasResultType = true; break; + case OpSizeOf: *hasResult = true; *hasResultType = true; break; + case OpTypePipeStorage: *hasResult = true; *hasResultType = false; break; + case OpConstantPipeStorage: *hasResult = true; *hasResultType = true; break; + case OpCreatePipeFromPipeStorage: *hasResult = true; *hasResultType = true; break; + case OpGetKernelLocalSizeForSubgroupCount: *hasResult = true; *hasResultType = true; break; + case OpGetKernelMaxNumSubgroups: *hasResult = true; *hasResultType = true; break; + case OpTypeNamedBarrier: *hasResult = true; *hasResultType = false; break; + case OpNamedBarrierInitialize: *hasResult = true; *hasResultType = true; break; + case OpMemoryNamedBarrier: *hasResult = false; *hasResultType = false; break; + case OpModuleProcessed: *hasResult = false; *hasResultType = false; break; + case OpExecutionModeId: *hasResult = false; *hasResultType = false; break; + case OpDecorateId: *hasResult = false; *hasResultType = false; break; + case OpGroupNonUniformElect: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAll: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAny: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformAllEqual: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBroadcastFirst: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallot: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformInverseBallot: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotBitExtract: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotBitCount: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotFindLSB: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBallotFindMSB: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffle: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleUp: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformShuffleDown: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformIAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFAdd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformIMul: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMul: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformSMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformUMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMin: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformSMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformUMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformFMax: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseAnd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseOr: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformBitwiseXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalAnd: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalOr: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformLogicalXor: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformQuadBroadcast: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformQuadSwap: *hasResult = true; *hasResultType = true; break; + case OpCopyLogical: *hasResult = true; *hasResultType = true; break; + case OpPtrEqual: *hasResult = true; *hasResultType = true; break; + case OpPtrNotEqual: *hasResult = true; *hasResultType = true; break; + case OpPtrDiff: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break; + case OpGroupIAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupUMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupSMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupFMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupUMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpGroupSMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case OpFragmentMaskFetchAMD: *hasResult = true; *hasResultType = true; break; + case OpFragmentFetchAMD: *hasResult = true; *hasResultType = true; break; + case OpReadClockKHR: *hasResult = true; *hasResultType = true; break; + case OpImageSampleFootprintNV: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformPartitionNV: *hasResult = true; *hasResultType = true; break; + case OpWritePackedPrimitiveIndices4x8NV: *hasResult = false; *hasResultType = false; break; + case OpReportIntersectionNV: *hasResult = true; *hasResultType = true; break; + case OpIgnoreIntersectionNV: *hasResult = false; *hasResultType = false; break; + case OpTerminateRayNV: *hasResult = false; *hasResultType = false; break; + case OpTraceNV: *hasResult = false; *hasResultType = false; break; + case OpTypeAccelerationStructureNV: *hasResult = true; *hasResultType = false; break; + case OpTypeRayQueryProvisionalKHR: *hasResult = true; *hasResultType = false; break; + case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case OpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetRayTMinKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetRayFlagsKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionTKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceCustomIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceIdKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionGeometryIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionPrimitiveIndexKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionBarycentricsKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionFrontFaceKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetWorldRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetWorldRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break; + case OpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break; + case OpExecuteCallableNV: *hasResult = false; *hasResultType = false; break; + case OpTypeCooperativeMatrixNV: *hasResult = true; *hasResultType = false; break; + case OpCooperativeMatrixLoadNV: *hasResult = true; *hasResultType = true; break; + case OpCooperativeMatrixStoreNV: *hasResult = false; *hasResultType = false; break; + case OpCooperativeMatrixMulAddNV: *hasResult = true; *hasResultType = true; break; + case OpCooperativeMatrixLengthNV: *hasResult = true; *hasResultType = true; break; + case OpBeginInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; + case OpEndInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; + case OpDemoteToHelperInvocationEXT: *hasResult = false; *hasResultType = false; break; + case OpIsHelperInvocationEXT: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleDownINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleUpINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupShuffleXorINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpSubgroupImageBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupImageBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpSubgroupImageMediaBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupImageMediaBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case OpUCountLeadingZerosINTEL: *hasResult = true; *hasResultType = true; break; + case OpUCountTrailingZerosINTEL: *hasResult = true; *hasResultType = true; break; + case OpAbsISubINTEL: *hasResult = true; *hasResultType = true; break; + case OpAbsUSubINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAddSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAddSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAverageINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAverageINTEL: *hasResult = true; *hasResultType = true; break; + case OpIAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; + case OpUAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; + case OpISubSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break; + case OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break; + case OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break; + case OpDecorateString: *hasResult = false; *hasResultType = false; break; + case OpMemberDecorateString: *hasResult = false; *hasResultType = false; break; + case OpVmeImageINTEL: *hasResult = true; *hasResultType = true; break; + case OpTypeVmeImageINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImePayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcRefPayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcSicPayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcMcePayloadINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcMceResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeResultDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcImeDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcRefResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpTypeAvcSicResultINTEL: *hasResult = true; *hasResultType = false; break; + case OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetAcOnlyHaarINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToImePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToImeResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToRefPayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToRefResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToSicPayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceConvertToSicResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetBestInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMajorShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMinorShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterDirectionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeRefWindowSizeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeAdjustRefOffsetINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetMaxMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeSetWeightedSadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeStripDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetBorderReachedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcFmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcBmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefSetBidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcRefConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureSkcINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureIpeLumaINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConfigureIpeLumaChromaINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetMotionVectorMaskINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateIpeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetIpeLumaShapeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedIpeLumaModesINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetIpeChromaModeINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break; + } +} +#endif /* SPV_ENABLE_UTILITY_CODE */ + +// Overload operator| for mask bit combining + +inline ImageOperandsMask operator|(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) | unsigned(b)); } +inline FPFastMathModeMask operator|(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) | unsigned(b)); } +inline SelectionControlMask operator|(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) | unsigned(b)); } +inline LoopControlMask operator|(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) | unsigned(b)); } +inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) | unsigned(b)); } +inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); } +inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); } +inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); } +inline RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); } + +} // end namespace spv + +#endif // #ifndef spirv_HPP + diff --git a/mac/include/spirv_cross/spirv_cfg.hpp b/mac/include/spirv_cross/spirv_cfg.hpp new file mode 100644 index 00000000..9f3e62a1 --- /dev/null +++ b/mac/include/spirv_cross/spirv_cfg.hpp @@ -0,0 +1,156 @@ +/* + * Copyright 2016-2020 Arm Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SPIRV_CROSS_CFG_HPP +#define SPIRV_CROSS_CFG_HPP + +#include "spirv_common.hpp" +#include + +namespace SPIRV_CROSS_NAMESPACE +{ +class Compiler; +class CFG +{ +public: + CFG(Compiler &compiler, const SPIRFunction &function); + + Compiler &get_compiler() + { + return compiler; + } + + const Compiler &get_compiler() const + { + return compiler; + } + + const SPIRFunction &get_function() const + { + return func; + } + + uint32_t get_immediate_dominator(uint32_t block) const + { + auto itr = immediate_dominators.find(block); + if (itr != std::end(immediate_dominators)) + return itr->second; + else + return 0; + } + + uint32_t get_visit_order(uint32_t block) const + { + auto itr = visit_order.find(block); + assert(itr != std::end(visit_order)); + int v = itr->second.get(); + assert(v > 0); + return uint32_t(v); + } + + uint32_t find_common_dominator(uint32_t a, uint32_t b) const; + + const SmallVector &get_preceding_edges(uint32_t block) const + { + auto itr = preceding_edges.find(block); + if (itr != std::end(preceding_edges)) + return itr->second; + else + return empty_vector; + } + + const SmallVector &get_succeeding_edges(uint32_t block) const + { + auto itr = succeeding_edges.find(block); + if (itr != std::end(succeeding_edges)) + return itr->second; + else + return empty_vector; + } + + template + void walk_from(std::unordered_set &seen_blocks, uint32_t block, const Op &op) const + { + if (seen_blocks.count(block)) + return; + seen_blocks.insert(block); + + if (op(block)) + { + for (auto b : get_succeeding_edges(block)) + walk_from(seen_blocks, b, op); + } + } + + uint32_t find_loop_dominator(uint32_t block) const; + + bool node_terminates_control_flow_in_sub_graph(BlockID from, BlockID to) const; + +private: + struct VisitOrder + { + int &get() + { + return v; + } + + const int &get() const + { + return v; + } + + int v = -1; + }; + + Compiler &compiler; + const SPIRFunction &func; + std::unordered_map> preceding_edges; + std::unordered_map> succeeding_edges; + std::unordered_map immediate_dominators; + std::unordered_map visit_order; + SmallVector post_order; + SmallVector empty_vector; + + void add_branch(uint32_t from, uint32_t to); + void build_post_order_visit_order(); + void build_immediate_dominators(); + bool post_order_visit(uint32_t block); + uint32_t visit_count = 0; + + bool is_back_edge(uint32_t to) const; + bool has_visited_forward_edge(uint32_t to) const; +}; + +class DominatorBuilder +{ +public: + DominatorBuilder(const CFG &cfg); + + void add_block(uint32_t block); + uint32_t get_dominator() const + { + return dominator; + } + + void lift_continue_block_dominator(); + +private: + const CFG &cfg; + uint32_t dominator = 0; +}; +} // namespace SPIRV_CROSS_NAMESPACE + +#endif diff --git a/mac/include/spirv_cross/spirv_common.hpp b/mac/include/spirv_cross/spirv_common.hpp new file mode 100644 index 00000000..252d0329 --- /dev/null +++ b/mac/include/spirv_cross/spirv_common.hpp @@ -0,0 +1,1781 @@ +/* + * Copyright 2015-2020 Arm Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SPIRV_CROSS_COMMON_HPP +#define SPIRV_CROSS_COMMON_HPP + +#include "spirv.hpp" +#include "spirv_cross_containers.hpp" +#include "spirv_cross_error_handling.hpp" +#include + +// A bit crude, but allows projects which embed SPIRV-Cross statically to +// effectively hide all the symbols from other projects. +// There is a case where we have: +// - Project A links against SPIRV-Cross statically. +// - Project A links against Project B statically. +// - Project B links against SPIRV-Cross statically (might be a different version). +// This leads to a conflict with extremely bizarre results. +// By overriding the namespace in one of the project builds, we can work around this. +// If SPIRV-Cross is embedded in dynamic libraries, +// prefer using -fvisibility=hidden on GCC/Clang instead. +#ifdef SPIRV_CROSS_NAMESPACE_OVERRIDE +#define SPIRV_CROSS_NAMESPACE SPIRV_CROSS_NAMESPACE_OVERRIDE +#else +#define SPIRV_CROSS_NAMESPACE spirv_cross +#endif + +namespace SPIRV_CROSS_NAMESPACE +{ +namespace inner +{ +template +void join_helper(StringStream<> &stream, T &&t) +{ + stream << std::forward(t); +} + +template +void join_helper(StringStream<> &stream, T &&t, Ts &&... ts) +{ + stream << std::forward(t); + join_helper(stream, std::forward(ts)...); +} +} // namespace inner + +class Bitset +{ +public: + Bitset() = default; + explicit inline Bitset(uint64_t lower_) + : lower(lower_) + { + } + + inline bool get(uint32_t bit) const + { + if (bit < 64) + return (lower & (1ull << bit)) != 0; + else + return higher.count(bit) != 0; + } + + inline void set(uint32_t bit) + { + if (bit < 64) + lower |= 1ull << bit; + else + higher.insert(bit); + } + + inline void clear(uint32_t bit) + { + if (bit < 64) + lower &= ~(1ull << bit); + else + higher.erase(bit); + } + + inline uint64_t get_lower() const + { + return lower; + } + + inline void reset() + { + lower = 0; + higher.clear(); + } + + inline void merge_and(const Bitset &other) + { + lower &= other.lower; + std::unordered_set tmp_set; + for (auto &v : higher) + if (other.higher.count(v) != 0) + tmp_set.insert(v); + higher = std::move(tmp_set); + } + + inline void merge_or(const Bitset &other) + { + lower |= other.lower; + for (auto &v : other.higher) + higher.insert(v); + } + + inline bool operator==(const Bitset &other) const + { + if (lower != other.lower) + return false; + + if (higher.size() != other.higher.size()) + return false; + + for (auto &v : higher) + if (other.higher.count(v) == 0) + return false; + + return true; + } + + inline bool operator!=(const Bitset &other) const + { + return !(*this == other); + } + + template + void for_each_bit(const Op &op) const + { + // TODO: Add ctz-based iteration. + for (uint32_t i = 0; i < 64; i++) + { + if (lower & (1ull << i)) + op(i); + } + + if (higher.empty()) + return; + + // Need to enforce an order here for reproducible results, + // but hitting this path should happen extremely rarely, so having this slow path is fine. + SmallVector bits; + bits.reserve(higher.size()); + for (auto &v : higher) + bits.push_back(v); + std::sort(std::begin(bits), std::end(bits)); + + for (auto &v : bits) + op(v); + } + + inline bool empty() const + { + return lower == 0 && higher.empty(); + } + +private: + // The most common bits to set are all lower than 64, + // so optimize for this case. Bits spilling outside 64 go into a slower data structure. + // In almost all cases, higher data structure will not be used. + uint64_t lower = 0; + std::unordered_set higher; +}; + +// Helper template to avoid lots of nasty string temporary munging. +template +std::string join(Ts &&... ts) +{ + StringStream<> stream; + inner::join_helper(stream, std::forward(ts)...); + return stream.str(); +} + +inline std::string merge(const SmallVector &list, const char *between = ", ") +{ + StringStream<> stream; + for (auto &elem : list) + { + stream << elem; + if (&elem != &list.back()) + stream << between; + } + return stream.str(); +} + +// Make sure we don't accidentally call this with float or doubles with SFINAE. +// Have to use the radix-aware overload. +template ::value, int>::type = 0> +inline std::string convert_to_string(const T &t) +{ + return std::to_string(t); +} + +// Allow implementations to set a convenient standard precision +#ifndef SPIRV_CROSS_FLT_FMT +#define SPIRV_CROSS_FLT_FMT "%.32g" +#endif + +// Disable sprintf and strcat warnings. +// We cannot rely on snprintf and family existing because, ..., MSVC. +#if defined(__clang__) || defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#elif defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4996) +#endif + +static inline void fixup_radix_point(char *str, char radix_point) +{ + // Setting locales is a very risky business in multi-threaded program, + // so just fixup locales instead. We only need to care about the radix point. + if (radix_point != '.') + { + while (*str != '\0') + { + if (*str == radix_point) + *str = '.'; + str++; + } + } +} + +inline std::string convert_to_string(float t, char locale_radix_point) +{ + // std::to_string for floating point values is broken. + // Fallback to something more sane. + char buf[64]; + sprintf(buf, SPIRV_CROSS_FLT_FMT, t); + fixup_radix_point(buf, locale_radix_point); + + // Ensure that the literal is float. + if (!strchr(buf, '.') && !strchr(buf, 'e')) + strcat(buf, ".0"); + return buf; +} + +inline std::string convert_to_string(double t, char locale_radix_point) +{ + // std::to_string for floating point values is broken. + // Fallback to something more sane. + char buf[64]; + sprintf(buf, SPIRV_CROSS_FLT_FMT, t); + fixup_radix_point(buf, locale_radix_point); + + // Ensure that the literal is float. + if (!strchr(buf, '.') && !strchr(buf, 'e')) + strcat(buf, ".0"); + return buf; +} + +#if defined(__clang__) || defined(__GNUC__) +#pragma GCC diagnostic pop +#elif defined(_MSC_VER) +#pragma warning(pop) +#endif + +struct Instruction +{ + uint16_t op = 0; + uint16_t count = 0; + uint32_t offset = 0; + uint32_t length = 0; +}; + +enum Types +{ + TypeNone, + TypeType, + TypeVariable, + TypeConstant, + TypeFunction, + TypeFunctionPrototype, + TypeBlock, + TypeExtension, + TypeExpression, + TypeConstantOp, + TypeCombinedImageSampler, + TypeAccessChain, + TypeUndef, + TypeString, + TypeCount +}; + +template +class TypedID; + +template <> +class TypedID +{ +public: + TypedID() = default; + TypedID(uint32_t id_) + : id(id_) + { + } + + template + TypedID(const TypedID &other) + { + *this = other; + } + + template + TypedID &operator=(const TypedID &other) + { + id = uint32_t(other); + return *this; + } + + // Implicit conversion to u32 is desired here. + // As long as we block implicit conversion between TypedID and TypedID we're good. + operator uint32_t() const + { + return id; + } + + template + operator TypedID() const + { + return TypedID(*this); + } + + bool operator==(const TypedID &other) const + { + return id == other.id; + } + + bool operator!=(const TypedID &other) const + { + return id != other.id; + } + + template + bool operator==(const TypedID &other) const + { + return id == uint32_t(other); + } + + template + bool operator!=(const TypedID &other) const + { + return id != uint32_t(other); + } + +private: + uint32_t id = 0; +}; + +template +class TypedID +{ +public: + TypedID() = default; + TypedID(uint32_t id_) + : id(id_) + { + } + + explicit TypedID(const TypedID &other) + : id(uint32_t(other)) + { + } + + operator uint32_t() const + { + return id; + } + + bool operator==(const TypedID &other) const + { + return id == other.id; + } + + bool operator!=(const TypedID &other) const + { + return id != other.id; + } + + bool operator==(const TypedID &other) const + { + return id == uint32_t(other); + } + + bool operator!=(const TypedID &other) const + { + return id != uint32_t(other); + } + +private: + uint32_t id = 0; +}; + +using VariableID = TypedID; +using TypeID = TypedID; +using ConstantID = TypedID; +using FunctionID = TypedID; +using BlockID = TypedID; +using ID = TypedID; + +// Helper for Variant interface. +struct IVariant +{ + virtual ~IVariant() = default; + virtual IVariant *clone(ObjectPoolBase *pool) = 0; + ID self = 0; +}; + +#define SPIRV_CROSS_DECLARE_CLONE(T) \ + IVariant *clone(ObjectPoolBase *pool) override \ + { \ + return static_cast *>(pool)->allocate(*this); \ + } + +struct SPIRUndef : IVariant +{ + enum + { + type = TypeUndef + }; + + explicit SPIRUndef(TypeID basetype_) + : basetype(basetype_) + { + } + TypeID basetype; + + SPIRV_CROSS_DECLARE_CLONE(SPIRUndef) +}; + +struct SPIRString : IVariant +{ + enum + { + type = TypeString + }; + + explicit SPIRString(std::string str_) + : str(std::move(str_)) + { + } + + std::string str; + + SPIRV_CROSS_DECLARE_CLONE(SPIRString) +}; + +// This type is only used by backends which need to access the combined image and sampler IDs separately after +// the OpSampledImage opcode. +struct SPIRCombinedImageSampler : IVariant +{ + enum + { + type = TypeCombinedImageSampler + }; + SPIRCombinedImageSampler(TypeID type_, VariableID image_, VariableID sampler_) + : combined_type(type_) + , image(image_) + , sampler(sampler_) + { + } + TypeID combined_type; + VariableID image; + VariableID sampler; + + SPIRV_CROSS_DECLARE_CLONE(SPIRCombinedImageSampler) +}; + +struct SPIRConstantOp : IVariant +{ + enum + { + type = TypeConstantOp + }; + + SPIRConstantOp(TypeID result_type, spv::Op op, const uint32_t *args, uint32_t length) + : opcode(op) + , basetype(result_type) + { + arguments.reserve(length); + for (uint32_t i = 0; i < length; i++) + arguments.push_back(args[i]); + } + + spv::Op opcode; + SmallVector arguments; + TypeID basetype; + + SPIRV_CROSS_DECLARE_CLONE(SPIRConstantOp) +}; + +struct SPIRType : IVariant +{ + enum + { + type = TypeType + }; + + enum BaseType + { + Unknown, + Void, + Boolean, + SByte, + UByte, + Short, + UShort, + Int, + UInt, + Int64, + UInt64, + AtomicCounter, + Half, + Float, + Double, + Struct, + Image, + SampledImage, + Sampler, + AccelerationStructure, + RayQuery, + + // Keep internal types at the end. + ControlPointArray, + Char + }; + + // Scalar/vector/matrix support. + BaseType basetype = Unknown; + uint32_t width = 0; + uint32_t vecsize = 1; + uint32_t columns = 1; + + // Arrays, support array of arrays by having a vector of array sizes. + SmallVector array; + + // Array elements can be either specialization constants or specialization ops. + // This array determines how to interpret the array size. + // If an element is true, the element is a literal, + // otherwise, it's an expression, which must be resolved on demand. + // The actual size is not really known until runtime. + SmallVector array_size_literal; + + // Pointers + // Keep track of how many pointer layers we have. + uint32_t pointer_depth = 0; + bool pointer = false; + + spv::StorageClass storage = spv::StorageClassGeneric; + + SmallVector member_types; + + struct ImageType + { + TypeID type; + spv::Dim dim; + bool depth; + bool arrayed; + bool ms; + uint32_t sampled; + spv::ImageFormat format; + spv::AccessQualifier access; + } image; + + // Structs can be declared multiple times if they are used as part of interface blocks. + // We want to detect this so that we only emit the struct definition once. + // Since we cannot rely on OpName to be equal, we need to figure out aliases. + TypeID type_alias = 0; + + // Denotes the type which this type is based on. + // Allows the backend to traverse how a complex type is built up during access chains. + TypeID parent_type = 0; + + // Used in backends to avoid emitting members with conflicting names. + std::unordered_set member_name_cache; + + SPIRV_CROSS_DECLARE_CLONE(SPIRType) +}; + +struct SPIRExtension : IVariant +{ + enum + { + type = TypeExtension + }; + + enum Extension + { + Unsupported, + GLSL, + SPV_debug_info, + SPV_AMD_shader_ballot, + SPV_AMD_shader_explicit_vertex_parameter, + SPV_AMD_shader_trinary_minmax, + SPV_AMD_gcn_shader + }; + + explicit SPIRExtension(Extension ext_) + : ext(ext_) + { + } + + Extension ext; + SPIRV_CROSS_DECLARE_CLONE(SPIRExtension) +}; + +// SPIREntryPoint is not a variant since its IDs are used to decorate OpFunction, +// so in order to avoid conflicts, we can't stick them in the ids array. +struct SPIREntryPoint +{ + SPIREntryPoint(FunctionID self_, spv::ExecutionModel execution_model, const std::string &entry_name) + : self(self_) + , name(entry_name) + , orig_name(entry_name) + , model(execution_model) + { + } + SPIREntryPoint() = default; + + FunctionID self = 0; + std::string name; + std::string orig_name; + SmallVector interface_variables; + + Bitset flags; + struct + { + uint32_t x = 0, y = 0, z = 0; + uint32_t constant = 0; // Workgroup size can be expressed as a constant/spec-constant instead. + } workgroup_size; + uint32_t invocations = 0; + uint32_t output_vertices = 0; + spv::ExecutionModel model = spv::ExecutionModelMax; + bool geometry_passthrough = false; +}; + +struct SPIRExpression : IVariant +{ + enum + { + type = TypeExpression + }; + + // Only created by the backend target to avoid creating tons of temporaries. + SPIRExpression(std::string expr, TypeID expression_type_, bool immutable_) + : expression(move(expr)) + , expression_type(expression_type_) + , immutable(immutable_) + { + } + + // If non-zero, prepend expression with to_expression(base_expression). + // Used in amortizing multiple calls to to_expression() + // where in certain cases that would quickly force a temporary when not needed. + ID base_expression = 0; + + std::string expression; + TypeID expression_type = 0; + + // If this expression is a forwarded load, + // allow us to reference the original variable. + ID loaded_from = 0; + + // If this expression will never change, we can avoid lots of temporaries + // in high level source. + // An expression being immutable can be speculative, + // it is assumed that this is true almost always. + bool immutable = false; + + // Before use, this expression must be transposed. + // This is needed for targets which don't support row_major layouts. + bool need_transpose = false; + + // Whether or not this is an access chain expression. + bool access_chain = false; + + // A list of expressions which this expression depends on. + SmallVector expression_dependencies; + + // By reading this expression, we implicitly read these expressions as well. + // Used by access chain Store and Load since we read multiple expressions in this case. + SmallVector implied_read_expressions; + + SPIRV_CROSS_DECLARE_CLONE(SPIRExpression) +}; + +struct SPIRFunctionPrototype : IVariant +{ + enum + { + type = TypeFunctionPrototype + }; + + explicit SPIRFunctionPrototype(TypeID return_type_) + : return_type(return_type_) + { + } + + TypeID return_type; + SmallVector parameter_types; + + SPIRV_CROSS_DECLARE_CLONE(SPIRFunctionPrototype) +}; + +struct SPIRBlock : IVariant +{ + enum + { + type = TypeBlock + }; + + enum Terminator + { + Unknown, + Direct, // Emit next block directly without a particular condition. + + Select, // Block ends with an if/else block. + MultiSelect, // Block ends with switch statement. + + Return, // Block ends with return. + Unreachable, // Noop + Kill // Discard + }; + + enum Merge + { + MergeNone, + MergeLoop, + MergeSelection + }; + + enum Hints + { + HintNone, + HintUnroll, + HintDontUnroll, + HintFlatten, + HintDontFlatten + }; + + enum Method + { + MergeToSelectForLoop, + MergeToDirectForLoop, + MergeToSelectContinueForLoop + }; + + enum ContinueBlockType + { + ContinueNone, + + // Continue block is branchless and has at least one instruction. + ForLoop, + + // Noop continue block. + WhileLoop, + + // Continue block is conditional. + DoWhileLoop, + + // Highly unlikely that anything will use this, + // since it is really awkward/impossible to express in GLSL. + ComplexLoop + }; + + enum + { + NoDominator = 0xffffffffu + }; + + Terminator terminator = Unknown; + Merge merge = MergeNone; + Hints hint = HintNone; + BlockID next_block = 0; + BlockID merge_block = 0; + BlockID continue_block = 0; + + ID return_value = 0; // If 0, return nothing (void). + ID condition = 0; + BlockID true_block = 0; + BlockID false_block = 0; + BlockID default_block = 0; + + SmallVector ops; + + struct Phi + { + ID local_variable; // flush local variable ... + BlockID parent; // If we're in from_block and want to branch into this block ... + VariableID function_variable; // to this function-global "phi" variable first. + }; + + // Before entering this block flush out local variables to magical "phi" variables. + SmallVector phi_variables; + + // Declare these temporaries before beginning the block. + // Used for handling complex continue blocks which have side effects. + SmallVector> declare_temporary; + + // Declare these temporaries, but only conditionally if this block turns out to be + // a complex loop header. + SmallVector> potential_declare_temporary; + + struct Case + { + uint32_t value; + BlockID block; + }; + SmallVector cases; + + // If we have tried to optimize code for this block but failed, + // keep track of this. + bool disable_block_optimization = false; + + // If the continue block is complex, fallback to "dumb" for loops. + bool complex_continue = false; + + // Do we need a ladder variable to defer breaking out of a loop construct after a switch block? + bool need_ladder_break = false; + + // If marked, we have explicitly handled Phi from this block, so skip any flushes related to that on a branch. + // Used to handle an edge case with switch and case-label fallthrough where fall-through writes to Phi. + BlockID ignore_phi_from_block = 0; + + // The dominating block which this block might be within. + // Used in continue; blocks to determine if we really need to write continue. + BlockID loop_dominator = 0; + + // All access to these variables are dominated by this block, + // so before branching anywhere we need to make sure that we declare these variables. + SmallVector dominated_variables; + + // These are variables which should be declared in a for loop header, if we + // fail to use a classic for-loop, + // we remove these variables, and fall back to regular variables outside the loop. + SmallVector loop_variables; + + // Some expressions are control-flow dependent, i.e. any instruction which relies on derivatives or + // sub-group-like operations. + // Make sure that we only use these expressions in the original block. + SmallVector invalidate_expressions; + + SPIRV_CROSS_DECLARE_CLONE(SPIRBlock) +}; + +struct SPIRFunction : IVariant +{ + enum + { + type = TypeFunction + }; + + SPIRFunction(TypeID return_type_, TypeID function_type_) + : return_type(return_type_) + , function_type(function_type_) + { + } + + struct Parameter + { + TypeID type; + ID id; + uint32_t read_count; + uint32_t write_count; + + // Set to true if this parameter aliases a global variable, + // used mostly in Metal where global variables + // have to be passed down to functions as regular arguments. + // However, for this kind of variable, we should not care about + // read and write counts as access to the function arguments + // is not local to the function in question. + bool alias_global_variable; + }; + + // When calling a function, and we're remapping separate image samplers, + // resolve these arguments into combined image samplers and pass them + // as additional arguments in this order. + // It gets more complicated as functions can pull in their own globals + // and combine them with parameters, + // so we need to distinguish if something is local parameter index + // or a global ID. + struct CombinedImageSamplerParameter + { + VariableID id; + VariableID image_id; + VariableID sampler_id; + bool global_image; + bool global_sampler; + bool depth; + }; + + TypeID return_type; + TypeID function_type; + SmallVector arguments; + + // Can be used by backends to add magic arguments. + // Currently used by combined image/sampler implementation. + + SmallVector shadow_arguments; + SmallVector local_variables; + BlockID entry_block = 0; + SmallVector blocks; + SmallVector combined_parameters; + + struct EntryLine + { + uint32_t file_id = 0; + uint32_t line_literal = 0; + }; + EntryLine entry_line; + + void add_local_variable(VariableID id) + { + local_variables.push_back(id); + } + + void add_parameter(TypeID parameter_type, ID id, bool alias_global_variable = false) + { + // Arguments are read-only until proven otherwise. + arguments.push_back({ parameter_type, id, 0u, 0u, alias_global_variable }); + } + + // Hooks to be run when the function returns. + // Mostly used for lowering internal data structures onto flattened structures. + // Need to defer this, because they might rely on things which change during compilation. + // Intentionally not a small vector, this one is rare, and std::function can be large. + Vector> fixup_hooks_out; + + // Hooks to be run when the function begins. + // Mostly used for populating internal data structures from flattened structures. + // Need to defer this, because they might rely on things which change during compilation. + // Intentionally not a small vector, this one is rare, and std::function can be large. + Vector> fixup_hooks_in; + + // On function entry, make sure to copy a constant array into thread addr space to work around + // the case where we are passing a constant array by value to a function on backends which do not + // consider arrays value types. + SmallVector constant_arrays_needed_on_stack; + + bool active = false; + bool flush_undeclared = true; + bool do_combined_parameters = true; + + SPIRV_CROSS_DECLARE_CLONE(SPIRFunction) +}; + +struct SPIRAccessChain : IVariant +{ + enum + { + type = TypeAccessChain + }; + + SPIRAccessChain(TypeID basetype_, spv::StorageClass storage_, std::string base_, std::string dynamic_index_, + int32_t static_index_) + : basetype(basetype_) + , storage(storage_) + , base(std::move(base_)) + , dynamic_index(std::move(dynamic_index_)) + , static_index(static_index_) + { + } + + // The access chain represents an offset into a buffer. + // Some backends need more complicated handling of access chains to be able to use buffers, like HLSL + // which has no usable buffer type ala GLSL SSBOs. + // StructuredBuffer is too limited, so our only option is to deal with ByteAddressBuffer which works with raw addresses. + + TypeID basetype; + spv::StorageClass storage; + std::string base; + std::string dynamic_index; + int32_t static_index; + + VariableID loaded_from = 0; + uint32_t matrix_stride = 0; + uint32_t array_stride = 0; + bool row_major_matrix = false; + bool immutable = false; + + // By reading this expression, we implicitly read these expressions as well. + // Used by access chain Store and Load since we read multiple expressions in this case. + SmallVector implied_read_expressions; + + SPIRV_CROSS_DECLARE_CLONE(SPIRAccessChain) +}; + +struct SPIRVariable : IVariant +{ + enum + { + type = TypeVariable + }; + + SPIRVariable() = default; + SPIRVariable(TypeID basetype_, spv::StorageClass storage_, ID initializer_ = 0, VariableID basevariable_ = 0) + : basetype(basetype_) + , storage(storage_) + , initializer(initializer_) + , basevariable(basevariable_) + { + } + + TypeID basetype = 0; + spv::StorageClass storage = spv::StorageClassGeneric; + uint32_t decoration = 0; + ID initializer = 0; + VariableID basevariable = 0; + + SmallVector dereference_chain; + bool compat_builtin = false; + + // If a variable is shadowed, we only statically assign to it + // and never actually emit a statement for it. + // When we read the variable as an expression, just forward + // shadowed_id as the expression. + bool statically_assigned = false; + ID static_expression = 0; + + // Temporaries which can remain forwarded as long as this variable is not modified. + SmallVector dependees; + bool forwardable = true; + + bool deferred_declaration = false; + bool phi_variable = false; + + // Used to deal with Phi variable flushes. See flush_phi(). + bool allocate_temporary_copy = false; + + bool remapped_variable = false; + uint32_t remapped_components = 0; + + // The block which dominates all access to this variable. + BlockID dominator = 0; + // If true, this variable is a loop variable, when accessing the variable + // outside a loop, + // we should statically forward it. + bool loop_variable = false; + // Set to true while we're inside the for loop. + bool loop_variable_enable = false; + + SPIRFunction::Parameter *parameter = nullptr; + + SPIRV_CROSS_DECLARE_CLONE(SPIRVariable) +}; + +struct SPIRConstant : IVariant +{ + enum + { + type = TypeConstant + }; + + union Constant { + uint32_t u32; + int32_t i32; + float f32; + + uint64_t u64; + int64_t i64; + double f64; + }; + + struct ConstantVector + { + Constant r[4]; + // If != 0, this element is a specialization constant, and we should keep track of it as such. + ID id[4]; + uint32_t vecsize = 1; + + ConstantVector() + { + memset(r, 0, sizeof(r)); + } + }; + + struct ConstantMatrix + { + ConstantVector c[4]; + // If != 0, this column is a specialization constant, and we should keep track of it as such. + ID id[4]; + uint32_t columns = 1; + }; + + static inline float f16_to_f32(uint16_t u16_value) + { + // Based on the GLM implementation. + int s = (u16_value >> 15) & 0x1; + int e = (u16_value >> 10) & 0x1f; + int m = (u16_value >> 0) & 0x3ff; + + union { + float f32; + uint32_t u32; + } u; + + if (e == 0) + { + if (m == 0) + { + u.u32 = uint32_t(s) << 31; + return u.f32; + } + else + { + while ((m & 0x400) == 0) + { + m <<= 1; + e--; + } + + e++; + m &= ~0x400; + } + } + else if (e == 31) + { + if (m == 0) + { + u.u32 = (uint32_t(s) << 31) | 0x7f800000u; + return u.f32; + } + else + { + u.u32 = (uint32_t(s) << 31) | 0x7f800000u | (m << 13); + return u.f32; + } + } + + e += 127 - 15; + m <<= 13; + u.u32 = (uint32_t(s) << 31) | (e << 23) | m; + return u.f32; + } + + inline uint32_t specialization_constant_id(uint32_t col, uint32_t row) const + { + return m.c[col].id[row]; + } + + inline uint32_t specialization_constant_id(uint32_t col) const + { + return m.id[col]; + } + + inline uint32_t scalar(uint32_t col = 0, uint32_t row = 0) const + { + return m.c[col].r[row].u32; + } + + inline int16_t scalar_i16(uint32_t col = 0, uint32_t row = 0) const + { + return int16_t(m.c[col].r[row].u32 & 0xffffu); + } + + inline uint16_t scalar_u16(uint32_t col = 0, uint32_t row = 0) const + { + return uint16_t(m.c[col].r[row].u32 & 0xffffu); + } + + inline int8_t scalar_i8(uint32_t col = 0, uint32_t row = 0) const + { + return int8_t(m.c[col].r[row].u32 & 0xffu); + } + + inline uint8_t scalar_u8(uint32_t col = 0, uint32_t row = 0) const + { + return uint8_t(m.c[col].r[row].u32 & 0xffu); + } + + inline float scalar_f16(uint32_t col = 0, uint32_t row = 0) const + { + return f16_to_f32(scalar_u16(col, row)); + } + + inline float scalar_f32(uint32_t col = 0, uint32_t row = 0) const + { + return m.c[col].r[row].f32; + } + + inline int32_t scalar_i32(uint32_t col = 0, uint32_t row = 0) const + { + return m.c[col].r[row].i32; + } + + inline double scalar_f64(uint32_t col = 0, uint32_t row = 0) const + { + return m.c[col].r[row].f64; + } + + inline int64_t scalar_i64(uint32_t col = 0, uint32_t row = 0) const + { + return m.c[col].r[row].i64; + } + + inline uint64_t scalar_u64(uint32_t col = 0, uint32_t row = 0) const + { + return m.c[col].r[row].u64; + } + + inline const ConstantVector &vector() const + { + return m.c[0]; + } + + inline uint32_t vector_size() const + { + return m.c[0].vecsize; + } + + inline uint32_t columns() const + { + return m.columns; + } + + inline void make_null(const SPIRType &constant_type_) + { + m = {}; + m.columns = constant_type_.columns; + for (auto &c : m.c) + c.vecsize = constant_type_.vecsize; + } + + inline bool constant_is_null() const + { + if (specialization) + return false; + if (!subconstants.empty()) + return false; + + for (uint32_t col = 0; col < columns(); col++) + for (uint32_t row = 0; row < vector_size(); row++) + if (scalar_u64(col, row) != 0) + return false; + + return true; + } + + explicit SPIRConstant(uint32_t constant_type_) + : constant_type(constant_type_) + { + } + + SPIRConstant() = default; + + SPIRConstant(TypeID constant_type_, const uint32_t *elements, uint32_t num_elements, bool specialized) + : constant_type(constant_type_) + , specialization(specialized) + { + subconstants.reserve(num_elements); + for (uint32_t i = 0; i < num_elements; i++) + subconstants.push_back(elements[i]); + specialization = specialized; + } + + // Construct scalar (32-bit). + SPIRConstant(TypeID constant_type_, uint32_t v0, bool specialized) + : constant_type(constant_type_) + , specialization(specialized) + { + m.c[0].r[0].u32 = v0; + m.c[0].vecsize = 1; + m.columns = 1; + } + + // Construct scalar (64-bit). + SPIRConstant(TypeID constant_type_, uint64_t v0, bool specialized) + : constant_type(constant_type_) + , specialization(specialized) + { + m.c[0].r[0].u64 = v0; + m.c[0].vecsize = 1; + m.columns = 1; + } + + // Construct vectors and matrices. + SPIRConstant(TypeID constant_type_, const SPIRConstant *const *vector_elements, uint32_t num_elements, + bool specialized) + : constant_type(constant_type_) + , specialization(specialized) + { + bool matrix = vector_elements[0]->m.c[0].vecsize > 1; + + if (matrix) + { + m.columns = num_elements; + + for (uint32_t i = 0; i < num_elements; i++) + { + m.c[i] = vector_elements[i]->m.c[0]; + if (vector_elements[i]->specialization) + m.id[i] = vector_elements[i]->self; + } + } + else + { + m.c[0].vecsize = num_elements; + m.columns = 1; + + for (uint32_t i = 0; i < num_elements; i++) + { + m.c[0].r[i] = vector_elements[i]->m.c[0].r[0]; + if (vector_elements[i]->specialization) + m.c[0].id[i] = vector_elements[i]->self; + } + } + } + + TypeID constant_type = 0; + ConstantMatrix m; + + // If this constant is a specialization constant (i.e. created with OpSpecConstant*). + bool specialization = false; + // If this constant is used as an array length which creates specialization restrictions on some backends. + bool is_used_as_array_length = false; + + // If true, this is a LUT, and should always be declared in the outer scope. + bool is_used_as_lut = false; + + // For composites which are constant arrays, etc. + SmallVector subconstants; + + // Non-Vulkan GLSL, HLSL and sometimes MSL emits defines for each specialization constant, + // and uses them to initialize the constant. This allows the user + // to still be able to specialize the value by supplying corresponding + // preprocessor directives before compiling the shader. + std::string specialization_constant_macro_name; + + SPIRV_CROSS_DECLARE_CLONE(SPIRConstant) +}; + +// Variants have a very specific allocation scheme. +struct ObjectPoolGroup +{ + std::unique_ptr pools[TypeCount]; +}; + +class Variant +{ +public: + explicit Variant(ObjectPoolGroup *group_) + : group(group_) + { + } + + ~Variant() + { + if (holder) + group->pools[type]->free_opaque(holder); + } + + // Marking custom move constructor as noexcept is important. + Variant(Variant &&other) SPIRV_CROSS_NOEXCEPT + { + *this = std::move(other); + } + + // We cannot copy from other variant without our own pool group. + // Have to explicitly copy. + Variant(const Variant &variant) = delete; + + // Marking custom move constructor as noexcept is important. + Variant &operator=(Variant &&other) SPIRV_CROSS_NOEXCEPT + { + if (this != &other) + { + if (holder) + group->pools[type]->free_opaque(holder); + holder = other.holder; + group = other.group; + type = other.type; + allow_type_rewrite = other.allow_type_rewrite; + + other.holder = nullptr; + other.type = TypeNone; + } + return *this; + } + + // This copy/clone should only be called in the Compiler constructor. + // If this is called inside ::compile(), we invalidate any references we took higher in the stack. + // This should never happen. + Variant &operator=(const Variant &other) + { +//#define SPIRV_CROSS_COPY_CONSTRUCTOR_SANITIZE +#ifdef SPIRV_CROSS_COPY_CONSTRUCTOR_SANITIZE + abort(); +#endif + if (this != &other) + { + if (holder) + group->pools[type]->free_opaque(holder); + + if (other.holder) + holder = other.holder->clone(group->pools[other.type].get()); + else + holder = nullptr; + + type = other.type; + allow_type_rewrite = other.allow_type_rewrite; + } + return *this; + } + + void set(IVariant *val, Types new_type) + { + if (holder) + group->pools[type]->free_opaque(holder); + holder = nullptr; + + if (!allow_type_rewrite && type != TypeNone && type != new_type) + { + if (val) + group->pools[new_type]->free_opaque(val); + SPIRV_CROSS_THROW("Overwriting a variant with new type."); + } + + holder = val; + type = new_type; + allow_type_rewrite = false; + } + + template + T *allocate_and_set(Types new_type, Ts &&... ts) + { + T *val = static_cast &>(*group->pools[new_type]).allocate(std::forward(ts)...); + set(val, new_type); + return val; + } + + template + T &get() + { + if (!holder) + SPIRV_CROSS_THROW("nullptr"); + if (static_cast(T::type) != type) + SPIRV_CROSS_THROW("Bad cast"); + return *static_cast(holder); + } + + template + const T &get() const + { + if (!holder) + SPIRV_CROSS_THROW("nullptr"); + if (static_cast(T::type) != type) + SPIRV_CROSS_THROW("Bad cast"); + return *static_cast(holder); + } + + Types get_type() const + { + return type; + } + + ID get_id() const + { + return holder ? holder->self : ID(0); + } + + bool empty() const + { + return !holder; + } + + void reset() + { + if (holder) + group->pools[type]->free_opaque(holder); + holder = nullptr; + type = TypeNone; + } + + void set_allow_type_rewrite() + { + allow_type_rewrite = true; + } + +private: + ObjectPoolGroup *group = nullptr; + IVariant *holder = nullptr; + Types type = TypeNone; + bool allow_type_rewrite = false; +}; + +template +T &variant_get(Variant &var) +{ + return var.get(); +} + +template +const T &variant_get(const Variant &var) +{ + return var.get(); +} + +template +T &variant_set(Variant &var, P &&... args) +{ + auto *ptr = var.allocate_and_set(static_cast(T::type), std::forward

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

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

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

(args)...); + var.self = id; + return var; + } + + template + T &get(uint32_t id) + { + return variant_get(ir.ids[id]); + } + + template + T *maybe_get(uint32_t id) + { + if (ir.ids[id].get_type() == static_cast(T::type)) + return &get(id); + else + return nullptr; + } + + template + const T &get(uint32_t id) const + { + return variant_get(ir.ids[id]); + } + + template + const T *maybe_get(uint32_t id) const + { + if (ir.ids[id].get_type() == T::type) + return &get(id); + else + return nullptr; + } + + // This must be an ordered data structure so we always pick the same type aliases. + SmallVector global_struct_cache; + + bool types_are_logically_equivalent(const SPIRType &a, const SPIRType &b) const; + bool variable_storage_is_aliased(const SPIRVariable &v) const; +}; +} // namespace SPIRV_CROSS_NAMESPACE + +#endif diff --git a/mac/include/spirv_cross/spirv_reflect.hpp b/mac/include/spirv_cross/spirv_reflect.hpp new file mode 100644 index 00000000..844d3f1e --- /dev/null +++ b/mac/include/spirv_cross/spirv_reflect.hpp @@ -0,0 +1,83 @@ +/* + * Copyright 2018-2020 Bradley Austin Davis + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SPIRV_CROSS_REFLECT_HPP +#define SPIRV_CROSS_REFLECT_HPP + +#include "spirv_glsl.hpp" +#include + +namespace simple_json +{ +class Stream; +} + +namespace SPIRV_CROSS_NAMESPACE +{ +class CompilerReflection : public CompilerGLSL +{ + using Parent = CompilerGLSL; + +public: + explicit CompilerReflection(std::vector spirv_) + : Parent(std::move(spirv_)) + { + options.vulkan_semantics = true; + } + + CompilerReflection(const uint32_t *ir_, size_t word_count) + : Parent(ir_, word_count) + { + options.vulkan_semantics = true; + } + + explicit CompilerReflection(const ParsedIR &ir_) + : CompilerGLSL(ir_) + { + options.vulkan_semantics = true; + } + + explicit CompilerReflection(ParsedIR &&ir_) + : CompilerGLSL(std::move(ir_)) + { + options.vulkan_semantics = true; + } + + void set_format(const std::string &format); + std::string compile() override; + +private: + static std::string execution_model_to_str(spv::ExecutionModel model); + + void emit_entry_points(); + void emit_types(); + void emit_resources(); + void emit_specialization_constants(); + + void emit_type(const SPIRType &type, bool &emitted_open_tag); + void emit_type_member(const SPIRType &type, uint32_t index); + void emit_type_member_qualifiers(const SPIRType &type, uint32_t index); + void emit_type_array(const SPIRType &type); + void emit_resources(const char *tag, const SmallVector &resources); + + std::string to_member_name(const SPIRType &type, uint32_t index) const; + + std::shared_ptr json_stream; +}; + +} // namespace SPIRV_CROSS_NAMESPACE + +#endif diff --git a/mac/libs/libOGLCompiler.a b/mac/libs/libOGLCompiler.a new file mode 100644 index 0000000000000000000000000000000000000000..3a8754088557b12219b4eb15df3c847ccdf6abe2 GIT binary patch literal 2488 zcma)8O=ufe5Ps`Aj;tn?p{3Ns!P_5#Tac?&WXpy))QJ=;#Z82zhBU2t-pK37WUV#w zsx>*OIBjD}LC_v@Ej{)U2$UR3NpK;@4mck#cW1E#^?aiH6ac$rWuQjRmST;DKDH!U$QrBvvSEuoUW|8#d6g$m$RRDh71bj zt4_(<*a*jx8Ot?G<-H4!s^H$GNkbJ8`KoEJUa?MBmaWaK5Hy#m_E>bD%S3vz%Up~U zk8vs5X3N<2cxioo+`&$j+3$)!mtbNIA+>S#s9aoJ!ly%ob;TO9;P@NZTc7 zkG_PrS%|V9B1}TxfO=)IsOX21&`HUE1AQC>)(3?66-lTUd1z3OB1nTX3C4S^ zKhACcQ^@~IDL1v;)=U#3YRZw@CRUOA>b5)MWn8`OrgGoTC}-0h^PC9RboTy6+wfBd zji$HU?KA%L7TXVUTfav>UEEn2kBwd>7ST}W50Jj+rJ|P?p=~qzgv1wM8}`^}2Ql^< zj~D-=GvCk_cVeUBx$}>-Dqe3@sP1=m2X1P+!)Q&7KqcPY_dksc(rShbUusxrLgTx_ z_u_i;a;{7KKF8w@P!nonO_7vjusoYFWkkg8J~~L!aFg66P!y@pGnKv$Em%bo*PEcN|-hgg7R_F>BjS zsdbi6La%Ro&(F7U6ur&a&PCIncS@JT{{`s<%eKr7t9wR|AC8_s6*QJY$5;vp*)iI# ie-^Gtz+@Up_CSa+>inI1|95Tg))oHgxxf4W z{{PQ8z4zRg4{A9*@pjXzzBm0|rA)q#?ry)otF!wpMd|SRps>_FueY}L#BlTdI!#@%VzoVrJA~@u9hdx}T4|{oah7OqY z<%B?tW9g`vToa=c20f`%MqjmXB%`W_2gy@A$x{!?|azcv+G(&T=>i5AY zP?*T}i-}Bbsy9E`)zPS;Sg;uO=2{~>EqnFcim^jFsVg_kxaa2G7v@J7eDe#d z@u0F&xLeu7*vtNRsYR>PB13b_YH4&)oxMZTaOazHeGGxiHcYr&dXm?i2B}aRHjeeR;Uk9$|f0^{=UZw3!A`@;Bv)#fq@fS&7 z%isEgFm?iV>*XJ#h)>ptKV3&ZS4aOe)#o}r%v_T#u9j_E8b5*0YmmQ)@zp;oCdv6V zsi(Q+qfNcr8-g?D-(T8cyEFE$Wk>VOm~Ce|S@BZ1U!r(&zD=_2j+EnFfMS{KXx

zqrBuM^IpNQ71>0`35R9*E!W30$56A1D4@;5P6_fS8*@2Y`s}*-!d6fIGpr z08;B!i0~C4Xt#W}KLa^xlkZiJ zV&!X)MdH`62)V?0!a2fe!ZE_bgbE?R^n)*J#>L)`pWzACjA6fze}di({g^ZaUBZyO zbe7bIA$j|MI|X0KUpBRj?IHal@iF43iT}gqDc(My8K3m$Nk2z=Ij?kUT1-3mgUDa0 zk2?4V4*MS*{D6a(?`Qm0=~D-P(!n=5@?CN0Z#(!s4*Nj|f7)SRbpQ_ex&p$`^n`UX z4JFfswP)bEhvaq~UN<_3*E>YlKK)jGEY$fN*!Wwb?m6A(ubc_z`Ml;KK5Lj~dOlIW zahE6Y!NPczOf!s}EiV{(Oh3csy80Rr9nR3|U_=wMqai_FemKUj5*hk& gg_R$Ea?8~DHuLkNp}`|PAyu7%0T3LBTK|yJe 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

a_NK67n2s zuPJq(ss9c-m12(%J)LN;Cz1jD`F&f`6Y6}5=7I|T=-$BNv_~QKGXfv^`<3*KE$M?s zLB=R%Ghj~XOo5D1UNFfRmFxRrn9G@3Hk4m5EeZRmq7CwwhavZ~@EztYh`D%8Q+)-H zk5IbjUFap!J->wRxdFO|{6OL7#^YT}t?o(iM57PzkGW1rz*xT#a}IjHBH79gF}c=7 zbAW#M$^Slany2FbFmEQVY3xqGIH0{dtT7WX4iY@2p76k+D>c6KrF^U#}Bd&9M~boz&<$!p28Ry22HBv7}$a_Fb(og@_H-e z^+7rBAb#Hpd2PY-e#FKqaIVU%Ha?}!xwW!k6o;~u2Ht5Q+wn1SGfUCWPoP(BLjP~Y zHxh92R7zlfJnpfTcxc;7Ax>-tkUFRLXl?*%U>Lbo49 zu6ew966Yn&U%R2tUI+g^L_1nu;#~`_&z_XLEY#>TYmC)XdNX2{D8{<4UH8J zSA9M3#0^_@-3GLyUN0rAHa5EJYQJ7nf0fYG|GLeMj=J@ZdS~qhS2!dQ!(}G?A)d>B z>0G^s)4-8kTV7x1E>B8coSvSRwkSOb%mW|mYLn_0F3MP#xwI@LsjM1JCT(%mH-NZF znG4buEJ;ePXl&fr@a-$FbczZVY^bZ-Q0;1{+gxAfT2NM3b7f;)U3FQ7(_MR|fM2(G z@%r@gMXq)0%NH(Qw?1Rh!t(Sb`b#cof(-6%a=G8ud~_8%2BnydqqXpUnBa`u%$Ld zB}lA1QEpqylshg}X2v8kx|bmDA0{H=pnJ$|;m0ERi`zSpIA-^_ zJ(dSz7(Fi?j5j z)J~5q{}zPVk7H>F9DjUKd)(dxPBZEc9ewnlmLIqzew-fVIpMfWK2OuOX+Re$U;QP^ zKk_BY6Ag~Z^3QAW8HEPPfZ+-NKaGI((``f_Vj0QteAG+F!HDXg`UuG#;Z-i-?t{Yd zw=oJ{1oNj!qYdv7kulSA8$kim%vC~(n!DH7@cOZqW`ii z(IGru30%hRlQ7kI(Jwqqpf5cVj^xG<7m_y^|G=N~U&2H>evzZdk4VbLqGTEt5$Qe=ejN1?d-3pNk+yv3egHzqoU@zDIVnpLk%K?k@*cNKq1qr@iSpFWd094ply-;*Yh<|~ z-i54N(6m{WZ$Z8C)UY2!(`RI%5^edA^#{iJdlDv6--A9rKu4Ok4FlRzpO?$>_eEH~ zQI?+{VfiOyd7{0aMj`twX!@oszdwTV#M?2@wRG&lpTGVfy%8hqzbqHT+tBh1A4`l& z8qeht4*3Ov`oq8xT_2Hf%e8Q$@Zp#&-xoo7F4MAn&nW#SKX4F926Pa8g8W4I?a8>c zTs{x7i9z&(e~fZecB3r&ww5;|`V`Cc%_C~P+Wr{uoyK?vHG(5k{BRqLoH>5X4O@p8 zFEqyDWIaU@!psK@_EO|WkZg?TSHPFrD$7UW-xJ;T%kt+Vpxc|W?DN{P26UT`y2oIn z2Rbsf{T&5&+8BZk@`o+r)KF(p{pGU!6A|LGN0yJo&!qZak>z)3>mLRGb6)}7 zqLV>7*Fe74$g<_5;u6cp!X2{g9TAk>FUvj>rYzCpOU>l8YH zY(Bnuz>inxe_d=S8MiX!^KiP0>wj6cI_#K;6Z0Qge%Y7cHI0j767C$%jcAdCXFYNF zkACUDAX*7Oh4){UAs;nl|K;=N@i=r_qAuQlS++TX{!>5p$nt}Rb;oetKOaFkia{NY z$A36B(toBv@RM`|lg~QB;wE$i$*g560U{12ez?qDEblR**9cjKT*a_4@Z>jB(J`IqE%VLsz zHXjXzZ%g?6NvLK%Ws>8ddEH2Q#PW96$TDlFpr&1-QMG(lPS3RC4?cGiZtarKpBnL8 z$lW5`e_P@nWakX&BycDC(1+;g2=b?b_!N+ByDa-Q`st_7DE4BbEdORiyc0N)4BtWj z;n35HhQPz}Sqv3eJ~8$usGDf`jJ$8B`&t^}lAga2=J{!Dn>u)U6gwUN;V9z&sc|L? z9}n~8v*eKc4~z$@=SEqU59fSY5AM&!Uxx+bm|d1j(%Nyux&=Rp_C>O;_oyN*Z6V*JGpptE zH8du})JJsck$8~)@zW_tX2o3f6glFKnh4Ys_LP5tM{TEVi#_=}pkmXKOIUT(?|3_)#a0G48xQ~(Lo-(AN z823bn80t8VG2(~QCP{aX@LDAAEu(UN+E{q`HS(GK;rGhrg|^_4f9Te*r(O$sEdqdXs9$@t{MOB@a&&kIN@J{F)l9yQQ5KYG#dLB}C#aJS|m&vj; zukhD}Q^H&AQzUpNp?r(1%ZQ$7DD#%Y{V52NUmuJz-ihyhvfk%I@=4H*%2^WeAC5N+ z`yI!}cA6{~uD%;1sE_*el*I4L^yy%PIJ_MJ4%GKCN%#*(xIWEK;>AX#5y?e~ET@-e zYU>e+(;A%ndFa<60o(Vmtb=Iem#y7^SkO>`M4LwEI<}zEwY5?FzrbUiV^N-IuS8NRV+&UHRr}S8y|0+KlofjZmwvD|a?J7nC(LW(G*0tsui)L&;Bh zYYNNQf(>OzNaA@&4)6qNRh%n&ek^HlH5R#RU3qSU=g#tS{=Cv{RKi~aZsl`-Rv9o4lwX1&Af;K9+rp{g4h%rLrCcPLban22{+-he-gT8lu zTr&x5MP2=^&iZm==wQ;Q!0AghZLX-Vs|j0ArH;sIO*Y=m0^p7j&bx^>-b2cvZ6Qav zy3W}s${7?}M8zOVU^OqN6{ZZ4I9O1r6PQX87(?M)0ufl{ta0U48Wu@U3$%)K#m&{C zZNpx3B(LXLj2y{IgP~*N1+Q^pWNeiM4N9hSLgqrBL8u$uTU=V8N<&0AQM2poolT;8 zLqsyDgKIa}Ho9wEyu6`c@scYx*YcqzYK@o&20Z0h7SuqdMSYO+h0EPFdF$4#11q5q z_%jG$jk6I0U#dZ!VG#lpc`c#zl;krXl~4IGjkB@2U!E`r`%?y7gKC&EB=YKB=*!E{ov*VHvM=1{&X6&|4-g3G6) z{Ho10yks3zr@L{ptF|#nodf~c7Lx`qb5=X~FdhXJTP8~8*3~w`RJ*vQ{L+OrV;~rb z^fFN|PZ-W4*+^f#k%$ryi3kBy?gtfLn4#9crlJXSbXH4Mo3nZSdRP7G`q4*5=6a+s z3mT#Sa7bz!NnsO;FkpsbG#r=_&utm*2DP2l8*}T*U21CqaSiHTdYZeTc%!Q<98i!1 za$zNFrb1y<2I>zgs_J@w$;wKjqDx5Kz$|1e3KVV{weSkE4F1CFjmmPfx4dpM{2hPc za-+iB%<+nC8UE7Rsx#rWZEkc|H)Q6!w(^1nq>s}0>6-ewtxW~%$vuHHs}?8`UQ2O0 z`IH%D&W6U4Ism0P@SlzTb1ac9;`u7Lo(093!u`zKvbKagQ`_SDy3Muaj&gTBEC{rU z&e!qVR&G32fb&w;DvdgtZX?Oet%Gye;BE{M295FYW1zp&wN4kep$3c>63lIK02zZy zgFLxWDoy8p&q$mrBd*to>kDD;^J*LGo48vfxRL7`m3xf-|jofG(;dPCxW}T~Ecq48@cZ3&R?ka;D$mN3@$u!LkjRFlCq11$? z*a$e|78eIWl18V#Y1`DOsh~E=!xr7rwmbsd2;~UDjWOq=M8j|6l3XeIxlR(og(Ikw zfHn}oMI%NF6ymbbQTbNc>@4}=AZ)Ft2SEyT4?<#lEB)qO(%z=#w zxeznPpX@e)B2|gm z1|I?;Yg=4g20vfx>;;iSGN!1`DTm=#sbq=dt|qQRz0*<5K-MF+3~DPh11aL~OrhVQ zsgu4`U^HTmqrw@0NooW;HpG)JXWC$e4H`&S@sj2-2&8-+G<&8#a-6Gby(;sZE{Qs2(?BdS+gw^T)M8-S>F_3kzsKu znmO)TZDAu0$_ z5x&Rh{9L=mS-sg+e5?Dm+oYuoa&nA(>`=4{#H4K*qc>U<)F?ETL1!XWhPH(p5t^)P zbcrc9H^bU)tgQrd4N$T*)L>D;0MJlir8T2Pi$-@XXHR9N`|EZ?)>?wNIU+~ARuUs^ zS1J(+TeprHN^{tj$dYTE^@v&`D$Ex*Y)g2&N`|mU8`SC2JjrT!6iRKCY^HHD1~V$P zLcfin6DM4p5#6A8Kp<43b!xs`9cuI@s0Qf(YOs(?0&t2oD-NRui4DX>vWQP^De_z= zBJo-l88k6+$QUTBbg4W=T=y^CQjo7}qo^W9{ty6MTX$O(9C-0E&bR}3_OTek+`rfFaC5{DZTv~)*- zX3i&qKubrl?6yUiLql7mxg7XGRYvr%EvbbP5e17~8)^{I%|mnQ8mTJzL2UNd>^w{2l=T?L~4wT&yP zog0kDXGR0od#l~+OLe$`oYdYY#4tFZ=tJ-I|isHAJjhSCMK=r#f(q(!wb zL3(yk`Q{p!(~$!(q!2e?) z#O2}=mF{rxnS`T})-DWTj=ocP*$a&Zfnf zMc7BCfjU#P&c@@m6wA#fAzf1LLdHp56L&XkHi4j{7V8I8V9ge7ipt1-@R6C8>)hyE z=dN})@<_923+(1-X%m$AV$x_0riX3tE7QnN1ca;!u|*&NosCL>3>`ir6_G{=ZXT&2 zMY5G%d1(13lD0A(4(G;=@JsS)0#Z}xCwF=pWQC_;IB2sS2bfz^S6je&NzWQ9>g#TG zXg71xD)XRfLKF=Ofa`aKg6FJzE;H3^klzYtLxo7n;u5_?-qDElSC?tXDuC0`%I4a- zdSu+W%DH$`o38o-xS$Ai5>x30T?S;^kq$8qhC;@ivpN8j$*&!ab-{o%DEKPoB3ft^ z&!`8BWyi4Sh^4B!dhYhpSm6W^Vc3b$yOA1R;>qQkKO_Z?~I5qu!xSg5N0rdgH_Cb{57I?G((J-6Let|o`G zenSH>awQpe2*yS?7JqJa^Fbu%)efHCu()wEa@Y!1uI8cy*<0l(SPAujgQRSu(=8l< zFCz=21zC2vW+3(Fu| zTp>v|3LNQxGRmHyn2y8Q=zt;N3VD&kvCiG-@T)Bto1%4Tc||p8s$63(Osk9z_xgex z8|q1Kx*HtpMY?4Gt^~?;G1uyOTk;l>zmf+%8MM?CU@hzemi?MA2%XjL4OkB)R7Sxb zE(xK7LN-0VB^=!wi`*Pvu>hUnxDkUXPrXTaED5P_VU5Vwg2lvMdr%6__0Zl9H(zNI z3LKd75~RSnVJ#qcCogYHi36@*zz~zw_pe0MK#<_rte5$j z;1oGN1uM4b($~}BAFp*e%PR0+15%85teAp0!$e`0K+MKJ;pguhlfn z3N-4Qk8q*nzP3_Q?N|t{V63{KGlCVjpLSoNy6~0hRHRmWjc#N@n3xfml9>*Qjg6QR z3rnsKj)`}Zf_15we;d(_KMg~-Naxo^ZG<$d0Zm6>+V^_C>cl%TKc8eu6^IBrwis%T z4nP^sk}F|`@LbH1AvtRF$8d%$0Rr=54G^XJ@#US-rdpMePqa`qkYD}Pr&&wol>09; z&H5ih{;xl=`XAHP$fi;ulyL^$DZ}KWU=4(fl#XVa<8($c(P^ls_YwlrDmP|H^g(G+yiadaS>H#cHvb6y$pSWsnV7YY?{ZX+ly# zGHcXV%QX{S;VOO|&PCkPSEkIDYaxhA5sQj(8zEWoRiyDtHWAbh9k;)<@2dR*M#vEv zSYHY%s#_Ea{*;EgXvAOhuXj}=Sq`t#ms}szQOwb04jlrQwgoo-rF)XF0`HN8d>p*=rfH(2SijPxe;D*F6cttU0)U$DqUfaGoEV3;Pv5sLxqJT*-prH%^hIkrKp?@u*DRgpOLj$Dg=2icr{HVP2H0*QG=pe6D zxM?tPZfq_hdUN&le_Q?epVk}OlJ)L-u!q00ik0U7(X0vC8GpXA(0p2DK4RcQi3KZk zziwPm)W9<*7x1lE^!uZz+0S1oC7bK-|02lj|SOdr#m#wN#>G)A95 zqFhk6pcdKk3$9*u-M9E|Ic$Ne!m*x`$Z02^uYJ(g-?T-O`dI|ELc4mR`yHdZrmbT~ zgQxxUw1*x(+W>x0!qNVD+CvXtg@>Wqr+v5Su!m{?Ur{C$e6`%uFC2UvfJ4F4{!?_6 zh#&v|di=j-0MF!iMEJLw{Lq2DK;?-Z>>T5cDZjp-~UTfhra!LCA?&pzhrETI4zgI>H|IeqXz9a(#Bah_e`X zf6)N`2?>8Uo@)<1{GSZqljXjM4~KythmKPb{rKya`wYINBaFWNIs^EJQe9;X8 zDxChCf^Rv6>i-=#MFxMB0sK?n74S*o$N#?`|Mdp&$0U4_A5xs?;U6@BPq;;tFAoF% zZwBypNcie7@MjF*`y*`sQaCc9=wI~rqT$9c?H3uqcT4#9!oc4y;dNrhp7@>s)VV(# zS8bI~8MOb5gwNL&#<`wArxp~wHb zn81c=f7vDhbWj6Jr+WAw7{H&F@YP}3f6oB^mIl!<-+x(ygTDQx7~rAse?lsraPoJ* z0sPimMWZcY@c*L$JZlp0C1K!G@tvqp_?O%!;KR+It}}pt>vjR37N-4s4B#!>1pIwr z;Q!44{^9Qn`1xVr6*w57`v1yy0UwV4b_4jB9RhxTnD%!Vz#qI*!0!@2{{Qvz_oM;5 z{Vo9#PX6-nov2X#kNcs3r|axdD9teFFaNF!JLzfPdwF*?t)M{mcM9 z^8o=br(xm(|Lf@&g8*Wv{%@4iJSgD1!@$390Key#0{(Ou_?h^A6cy3;|L(&Ap1!H4J@oQZU;w}C zp9NGn|9`6i{Ql|X@@!7%Xj4X;rBKYc{Nhg<*okpcYv7X^HG82WuI z;h~0tj*YK~OPHsiL%mji&4}}d!oOL@LT^wK+(4=wTB-5Jp=gCKME-N zmZkR4U9!uu&O%+(k(s@BQb57I4?1+@V3iVHKYq_i_;BO*e;L4^|C4BzzLBXt^!TS> zoriGJ6=Ta!2`KtjruNXo?>2ys`9wf%4%k)(NJbe!nw-Up_40 z>HD7ALwCvYE(uM)X0ssNIV~{G_3$+Y@Qq^xe7O0~F$4HzV+DM;`SYwxL*rjDPQX7O z2LG!K;OCAP@XcZ9Uu^*YgjK*xG4x}hrys4eQc3;zeIzO}_-+IEJ<$SwqrYWwqHq6Q z1Nbp90=^?m|8GeQjsFu91-x{l{8;GQzs~^v#z_L66UPrdQvUw85qzwGmp}d*^zBbd z3XOloWZ8c|q&U&TFEfC*TqNM>`>EPPcgcQi0RP5R0iUb|#)AD1TZPZmG^TJ-d5Hh^Dd6M%7kNO7Wv?=gU1BjLmK|6>FA z4hf$Yrv3OULeuXJ2_J6$xEu<|8#X^`2T|e z{8P1&;qNnmzhh%$?XR+j#y_(@vi1)ez*`yxd^r7c!2teZ3BSfKdE!Jbzp2@w@voNf zFz-Q!9)6{S*SYzuL&7HoL2JIzF7H=Lc$nd!qg%pP2Hh37(k($9#+oF&&P`_XH;WQ_ zeD&84OL#s0X%aq3*S;>C#C~M}za~QXw+-;$DB+P_5p;-N1#S%)!0(XodjCTYAD<&= zsi$9?gb%lVv_Qh^>DOVO3*SBws?Z%=>yd%zQ=_54@+A8!18B;ob=w@CVhli&EOL$}`{;ls^;Zk6!* z_PZs#zQ6kGA4_<>p6`+Hav8`kMXLO(zmG|He*t-N{8qI@@Du&r=M4J)mV|#MDHvXl zKh>x2J3+L_#Ixs7zxL3#e`SU(Nqg89XJ)3SXJ**al9Cpu(X(`%B_-L?(lQn;N=jOo zo}QM;0ZOB`=M}9mDS;Xl_A9?#(zf|VP2kGTPwmXkve>7SE*|{k2E}`BwaI(ocC+`w z%dG7av(kCeY)Uv-Iew=Cvzlz1kja>8N)o(WiFY zAnwyWhqdS|v$B$xOwDWmWWG3E+eRN_OCAexKWRS8s9a?q+I**}&7s8m`pm4PA8lJx z@4Tq+5_?ybVvXKDnQii2v2Vu9sjQ@EtbGXc*@LIdF`c^<`_QrB;X@OF@B8Mc&U+?g z4?c~1?>$yI+W*)*weu6y*F)_;D%$Un?LSNH|0CL;%1Wr*erg}MQ+aAX(I(pKnFyYb1%GYI zwOJF`rW^|^sfe<7S+-e<6Rl%5_2h@&w_7gp-14`1ipw z)S`Is4)vL5l3TtfS!rIIcn9-Nv#=rLt8{gn*iZ$=J!E63 zWehu5v5F172$_J1D_u!;2#A{hs2%w(sOA5UTt56Z`Q!~ zTrA*s0OmcwpM=gVU27jAyeqD!al+avu4hA`_@6Y6We^=(OhP}9Zs|8$JFU=NS)dzI zSW7TIhOBr_V{iy#FblM6#(lbe74o<9i{V4W?;g~%-^>o-btujsx=zM5UJnILEMm-y zw)}MMflej5#)qOS#-d7B!fW(?1?!&fWTBU7+&Ppuzg`}gr_syM8>E-ZuJ}vq-1byi_m8UZO zNddX(mvR>uLhkx64anWcVd<;0hhqb}{d(EA5xQMB?qbjejk{9VHdVJ<6z#YZW7-0l zfsgGUN1)vZc~QrKb{w@xd7*JMn!JRvllEyW!>_L=Yjv?k_eot$G$vd55cLPTxcj1j z?yG>EBR-JsGm=-X>&6KiK(>?GB^y9=BzYZS14f~vY6F7lD0HDpM_vXvk48tWK2hmN z`eZaZQa^S~5Oy&ezbgH%3+ji4e$v*f^yBgXStof=Z3p#3r60+73vj5267s;y;F@fJ zs+apA-w2;V-~2cA8TMP{8QJ#DkU8SncrLF3hyF3_5MC*O4bt>oCp#7?JAD}EYTsK> zm)du=uUej|HbB*tUxjCS``&GK{C?PMIzBX$4GlWR!0wNQ{T~Nkd^~({rR}CSzVo}} zY4#!V!~5Wue~iEWX$)$Ld50%4ZetSd?AdqWe|>^7iMOybjkA@uchRqbIjpVcw#4Ek ziv79%Ic(|m3Oj^YN?cD4YfJdxj{Ez}3BtEG+n@Usu<-l6{o~nCANC`_<^v z3iK_{JLp*M9hzw$LZ92H?|spiaQjYUwePO(W&JLJ#x-Z^D`W=swX>i!b?I zyr09$WcGx@@K^r6iM5!TagJknSV`TlSO#O*Gs-JajOWJ2c28hWjEjAK0_z_)=3ESG z9zW*r1a|j$P*0Sf%+3S$yi)R%nZ2Q@XELK?h+XEA(_>hl`Jli47=}sq#g=7k?tI=} ze9^M^6xO1YF!r`$!RdR7n1uruXh&#;gC@&)Gkf0D@2_JrdmH!PHd&q+!`?H!skz^W z`+X+M{xPgS=)O_;Cs6(gljVIgd&*zlY&w3v&gA`UgBd&=DW}P?_O6d0o995=#60t+ z7|czq|A@IkJlk|9bS&u-nulzG&3i!V*r0jHYr#IEi+sda;UiuWuvPovXQ}fLYk~RN ztm$kMWYS;vFJ~CkeLT4Cl~gy{vriAy-JhVTo93)mw&}6Cti+A^Nh{_i^DqY~YN{Ia zOtyDzAFFISIfIqlg}KSom~T`udsiWzRbk#jzcsl3B+74BCRRO)HUKj;0C}!b%)QkY za!%|+-S1Y2hyemobq(Y{2;5-o!RN8p}$mw$>hQ9``*j z;grY}AMhL6q%@Q7ToR4(yAEwQlF%2_zYfm|(U0v)Y?Tw&g=6S^auq@gC50B8-vc`V zowEHBw#kX#!WetkF3f#d6540Xx8uTai4S$uStonSfWw^A+wXrDeQb^~d+tV=|1_IB zA9{1U_rDMm_!<7*xmekhje0%-eTU`wuW+v3|DDO+rQRQu=e}wCX3+B?{2npIR(*!w zM00G_=lH$JJUuFFJlk}eIXa5!{omv4T{knf=nMRApUF0z9}igk&NH*MAE5kBb9CyH z%8V$?HmqGl_L!0sD_^1N2 zHR`|c>;uz;s3%R)sb0mJTBVFjO;N_DZdXv>lt*SDC1=yXlm}-J?fwaT%VE~kyX~xP z)~CZISVx&=wk|aL}S27=it#Uw8w}a zCgz*<#c;`oDE~U-;~iy!ukZu#XFPQB5Zlymz9fBM{H5v1N=v)jU2%9P;7*yXg(*r@ zl-r$rc-=&M*X%KD@f`3`o#$1+Csb{I#kl6RWN+1H(8K;``FKY239WzFvP$Ue7Sh?6 zr#%Xt4GqKR6U}m-)FS6eEtn@!`*(sLWNS`J-CXh0Y;US!>0OEOLUlY}|`LGA$x3Z~n@D$q5!5DqapzcHCSR2)U zpfqW<5g{!^+6G9*zwtLi6Ubfs(n=T-6!LOPRd8w6#S8IDfC`c z=TXe(9g3xj;y*`0la=skkqQ&%p!fyXnNvGEG5@F>OS&n_Kc811D-{?k6o0WG{*nlN zQt`=fKo4R*98$;rE?5sHqOC;e#%@ka5$ge;{W?~iN4I=5d}s&ksCsR|_1(Dk^Z)E{ z(0svyYgJZ~(dRofWs}bYm)(ClP__lKvk7H~bH~BfOo6S5gRO~&-!K*a!!-Cr3Em6l zacwukC$hl5IQO!tjlIX}24-5*TQb-X{ILTACs-Hs;DLe1@q3r)z(50CD+dO0S=ZF0 zA}`tgcT5&vGvaGY4*cM^(>AcIo>*AAdhHTZpcEcs{?eUGC2(^iUmCirF{zPS!C(U=FkgZj$w>^G?E&t2BN z?AC~sWZ-K1P^7pNDVEj`(C;UQJ&?^W zLzn4~+r3$4!S5dc))H+WS_)s3?j@ZbE=e|nr&fDceV0}eq(JEDZodZxoj|OKUP@?-*cr!N%-@&vK8or#%t!aNt?X z-c?FW>peT}X@|`_b71n1+7~p{3_cBcdmVCDi{IZs?uJp8$W$!TTmnwH3Lhk6A0^ak`muifimB63I4`Rr^51?oF}ds_-$782WUh(gZlWX?1KV3v-uPI z5cQMRIrf{T_P%Pec(Sk#!Qd}gF68b$G||#K?aa0lJ(af(zEinmaI|`<9+DNc&Lr5& zjvqM&kA%R3=t(@<@(JdLn7?%Z&neJz46;J=r(ZyZ`aq-MDQw7&XZ$|oEo3?9qTzX( za*(}{<)9~qa|7j?A+w>%HG_8hfU{k;OSWNW2I)4dZx;G=;r1J0KW=~>xgPf9I@pyG z*zsa7>B}|iXyl*s<|@Yr9SUe;0*$c#cl#LF zSf%ZH*w~(_VvbM!p}4?7TI+y*wIZII0$H;|<}gn>a~FOe;xcOSkTcAbC|}W;R5It z&Iuc)F|J=?{ly+CgXPhBpW$JBdLiq`xQJpEtS@B@JHWQ@x}0s_iN76}1HZ4~;=(Sz z7ljTyjd8>~I{U`m#Cj3S>bv7&)^{H2Ma%*53{mIj;QJH&KV58Y19T?^^Y0DB;TuL3 z^=4!2mudRJ<>>P^%(dOq)ee?sKIx@9AdpzoGo!5I9 z@}M?scg$~+@iFqt(as~FIk|N)#-SMFQ3PE@ECl`r#YspmT(1)FQT3nNMdRrLy&HTm zmRpB)odgf%Gf~Xu9qiNjn2u(BN8*g@dO5CN!SnMNSMD#N&l54OhtWT>SI&OGMqykh z@^O6!{n?aYY$-;$`_|%K8eg36@bS&e*j}z<4AnT(81q;b#+Sxf$9}>b-@Q97KMEZ@ zQUSOo*UyO406oehvM45&HFOn|{3o{d%CEeof^1b-bT`2|axv zj($yOU64?}8ZKVkMeRF`_K}{YXlU~^$PIo4%`e_g_#|rILbmf5;&_%mmOzgdL!XMF zkJ$U{vhJRfnx{bu5LgA^So;^SFXkI-}V~eBZ^{ z-`g1HA_m_G&zE;$JZnT-DF*s3#{F%qH`EUOtA$;en4?$&U!?Qb2gkF@$>8%h>=EhQ zC*RFFE}ylt{OatTZr$3O33^t=eKbF(q926&IL0sqZMhb{5cw^%Pk7rs z1^tCyW#CL+JCE-PmtwBdIS2YNj(9Q5LBivA0$@i7pUyen1rOr$EcoiSeY%c1=&Y3X z<5P6j>7N^s7(B+->^0?U~G;#vb@#(^l~P;daFG*L`W{Sh_dT`{gBF8FCMS zYwqKY78Uei4ecNp`L~lHhq;*7G>>=OTmU;D)}hQa@`-eQU*)n3OS-Bg4;tIdOAGq0 z1rLI4haXLPMs(w_7g2Y5F#g$!*Y@{D%x}2()7*~G+Hf3ky>!^#cKFaum={lI<9M8K zFMRoX5v#f%I^PJrXw)X8Z9{Bg+4Os-ki8*$TL^!%>UG zXy2mt#YYh9IEwy}ZBS6^)za7s) zj5XCc6TG%*TF+FBWwxiFFI!`M8(>e$Qdl3=m5KR4&mP1HQ-NEBdXKx?J2iiHZE*m`y{E^$x3kPYvo{lU zr=ZNe>{e9Sjr0W%N{7`8i!bH+R4HfF&^PoZBOUg z@jJP%(Tj2U8|=VmMi(t?fNt+ORrun)ZWg`_@z^T&9`d|KbCX9qKjf{^eh@> zoNjQ9YkvU#C&gR)-Y9s)`^NPzf@VLRgZ7S^(*7$>GYK|;XeM;`jhc)wE!&Sa_2_8N zeOQaL;18#=?YEbWEPD>I|MpbuZ5pwE-Ud0{>pHh*`Ar$UJFw4rbX7rD@2HgaZJ>Q@ z8tXa$-`ETK^%8eG^jl}JanMiN^Aj!YwXvCeRLDAZPw;O2j~+l<#yR&21Sk39?q&DS zF#c+96K_1?-TO@O7V!9}j=k6f$o*Nw!&4#mZk>H+Ln`8}7^gCn3Hk5o!Pk2$vmk%6 z>l5KeFBpNd;P)VZ^at%T<^K-kdl>R0`R&2DrlwD5KZ-aD?b%b{FSq0rbfu(EY^S}| zVekwXg69rl@@_dfv{ zZ-9*bQpSnm8TZO~#+zuXka7Qeck#~Z51Xt8Lv{!{F;=-gsadK=g47W97t z`t_UlitkwH9@nlzUytIRTP9$~px29_*B6?4J*j8PoZX#|BmTb>c)J~X4ZG6UfW6TE z;p_yhuMN;=AM}Rq=e-M=7ua5Bg1G@q5s{Icie-gP8YD+pxKub+tl< z+vM=sqiP)#R8!>``6=a<36OaVaNncrgXz<;Q$D{`$5@$aZC+yedV_ zheAFdCSyL_g*ap8sT=yuhrV}UZ{E4Vv^US_Xp&67JJD$BN*}F8skZCa0d!4!w0DZ2D@%2)5$R3HElC*o*B(OyYrE z=lAM*LEoZDdXFDx%cr*CzDXMED;(DQJ;Z(w=_gBH9FILRjpKcCZXX6t!^H(%r{=H& z+1Q6I!@imJX<6ghSY1nPf9pc6>)3^K9s@u5D~NU1h_&Ic`^hVOt|zZp@7jLF5%=~h zj;6u(L%v>CcMrvDj-lQHsTD!1*fH^}aGZ zQ{gkEVXc~_O+0w#$h7u!cWQe&{G#Vj$8yA!Z^7S#TH15lPO=kz*fTn7zgN>vpbeE| zzv%3AFL3rkMtdQnZT?xkWWNY+1<4KaBKRp+YGYJOZ+{AYe#QuPVkVvw-E8hr_mn(c zo4B0z0BPUe-I)SgiF@b=H^Bd&HTBn>nbV)`Bs)9Fop!KMo7k=+9v?W#I#BnCy$`o{ zB9_&bsb#k9IazuK#szo0Sl@oEPn##FEZ0xb-h!Q&^6;IVpEy-|$2`~&vX68QtMqW` zpRT)Ick2hS&pxr=HNL$OecW(eYi~R1JO()K!`!}S`cF_#N}FHHYQwoQ-FMH%y59HZ z2-f$`x$FSlJtN&XdLj1nFI)QXMh41@*@0uwA-vbQ?>O{@#*D|wW{9{1-AOpPwG896 z6yvr8<5vpbtOT(M%lFTMEYtCqjqysuUzV1Buxw;Xdluxh2y$q`IYIjfHup8i^0?c@ zzYFj)Ep7Q#w-h|KNE_XA;lsCe(i-$S?reN(>cP%J@cQQTpLPCFJ7@W8+L*R&%+nJ> z`gzFq*6q7GXS&iFZ$o)IaO-y5);SaSx3N(N|8?r2PNI8V8`f5D-9&(QI^^m!%(M7eCoK3Vd^1Ic*)<$o5=1=hxEHXgm+2Etf!ccz^9! z;@!kXw*ORP-9gm95`W8eb^!9Ld=PcLhI&R_{L{`?r#}zb<+OoE_k);=J?@lj>>Cc0 zq0Y1vb|3{XvXw(y6N=@UaJ{uAU=26dgpq1Z5I&N%CiM4_oIWVlguY&^&2MAf=4--d zS?`CjCiGT)A9E`9`#=+5?-t#+u*lUX%l<4gB~(}v`U-M^D^j{ zr~ImOL)V16t8f;5AMz>SLH3IBWbfN>cL;QiPeG^P%XDL$#~mIa_UsRUH|-;6KL)=7 zaW7XF#g(79RqMsQ$S%4wv3^>?f6#q=O}p@(@4{X`?Yi(Dmp<)+0`JrdZi4>*eiS?L z?7Q1u{0i#&3HrDQeWd$9WS?oT>z(Ai0CC3d6qa=ltwB?CiIEqk^vfOJISRB zPm&GoqevDcm!pu;B*@5*_GUsZyU`BB7yHOQj-zte+Eje!sEzW_$IRA+y}NJ)`jm^!#eJVHfNhkm0oF{*K)U7Y)V}_VL(NZ6<=jhR9@9$j1#`jdq zHXMdeWN!n_|2J)MA?n*xxEDix%KSU#F788bmp)GeWQLd+zmKZ?3$(F23SXSYU{Pyk zFUg%^akLkF6=S;_V~ZHeqiGn+J?LMyHtsmhgKgTlo*F!xQhwR_;6vl?*3stm;6eMz z0*nc@e;fEBK!t!?N?Q}kzTP^smtsR-#~I`-E}!&n%Fn`{;TG^myyH>C=Xz?;*KdID z3*Q-c_Y+!L&y(^V$3x&l`2ysF;P*Pd7x#0Vb0gsO=xgrL-LHe!H&ORK#P&|$FT-_C zV*&ax8hRB1{zEuxe%;^HOL#v6jCj0&{MV7DcD(wxQ@B=zJIAe;^d1H89(-?(w-0dg z=iglYG}k@!&D<}N{E;7L_wi{A)SV*8h2O`)lk4{Soljm)y!3SF>-O!JtJs>t%LJZ| zcs|?y%kXHc|{f!^%{t~kTM^JU<_a-l^t9_=C9upa&{=4i)D_#_3)2w+#7ZxL@=Zd<5$A)yR{bCtH&(?ffa+7a&{q4BFEJ8@9z}=X+f#ZH*ZFsKd^; zW4>>bcAj)`o3!%**sJ!3CfvQvX6H$#DNp@vhdj0+uAuCE8Dw;Lgt#mI0O}!o&h5M| zb>Ks^>m-LSqmBP4c3sS!vo`$ydmE0p_zC>MhWDIl8~(xDCHF_tE-fRwB)_9dc1il4 z+&<}_(LQva^Q>(;>tFsu`j`LEw&|?TG}vDFtX(>5m(JQH?8^t(_r~*?VqGTc3WK%bkiXWOIS+4vn>{zr3t>Pmp`bTBXYTwt3-fETyfpz|u-?1L2uILY@4}qf zISag*4bfYUdi& zb+vQmRoBg*JEt~pL2Y%7FSoiHucynOw_x^cyrgbHR#LnJflW=`IW=?g=hPVsd<%@+ zIn}f4s(o{PH4EnXX6O2R^B2ykUErHnots-z3)W`$R;*aJQuHOVDVU{(Z;VW6*OfEv zGZ$zdOV40lz$QufjcG_!rk_9N9@m#VcMRXJe=ha&>0cN_uUp_B?YcE9IAz)wC4`+v zJP=D~7fA^2-7v(G#php~yhhzQ=B{xZf3HLdAmGi`$HN=jIqvQWU!=Cp#ovtz9|tBT z|3T=eUEh~<^j>C@?wUCD0gv!smH0S!8xnpc_|j(!E)@^f59-T}5}(U!g=&Y+<<}s~ zaF%V=ZQ@`&04E+e+v1iU+%$s9sm^m-2ZknHR-p?1)P z5&Ep)|HR6CoSPT1UV6ms&p19d9*KuDTx)D%+MUkjQ!DZQhuWM-)+nN}+9z>whnIgy zC%!s__RyH_mv|R}*3|2m_R!qLd;>1cU%dZ>e_o+~*C-j#9Oti7Vds(l;={+))G48J z#6$hApG4#BUn4ULMzXGznF6Hk<3K#N%Q7#O;X|*Vcidy^u z_+h#8nnRK3nsBJbh(sz|n~jq4<*O>Ha&yaqAa1E4pQU6&0@^%ZZEeYxs1c;qzGThv z8kSRE1FwfWJ5{JTU?iZ-wbfcu-mk(0RC8@q#idJ1HpSx2D}sa9IA?Cy*c|ppjlxK= zFBl5?YkYyV!LZ?jhk*vIG{W^p0?GvgQWl4TQGc+-C|Of6yDGM3Q=0j<7M2>mXiM0L zI4d)eV}xMqOGR{kRaLOIF*k2^RaLYh9NJuE_b-K@X-H`>o!)10p0ivrTL5NZ!>FqE z!AYwzs(f`(?uSQ=aI|a^MG(Gw%IHOIWVA+c5+>(+6!jCsj^Tkep zi(z(4(7&<8sA`Ue%lJ%-ok}E@xwS@}uO$$zsx<;e6m6V?Haexl;{gjNX(q zSsG{S02D;j&4=rw*M5?4b4#QF&8umwiUgp_&Aw=Z7|ujs=EQhm8fgw%TYQ=*Q#ULRf8RD4<_O!!#>dcnh}RC z7u~N3Nn>5*i&jBdxFXJlZevdjLl~w_FKO9|>e(eLnr4%-@wsRO$s$(y>&mW)gsDIN zNL5`ZyxAA7wdg9LobxvM0x*1=O6EpsiKtjuh5s#uG}}oQq$bqdTGbNt1^o5cpi@)S zfW~Qk2{nl~CfC{CO5WUSR`_{)SHS?0)?8CLyQ)M1sT~XAwL{e?R7k7~4(lUyC-ETi z@&v<3wyD7ft>#M{mo|(mhj2kvk(A0vXJQ)?qjApm%;QFY%OVf_TY{l5)@P%(s>#>P zc^l!f4HfxS;5wJ8DubGFLq&|JAF&j|Y)XQKJXaMB*@@;up!rm39;~L()Ew|(QIOWF z(P*vmh3g|_8S#JkMl{`PYzOXgfu zl?RQrFEdmHHKZc1%Csf@+Od$@5wnU|>vZmi-4K|gng9Z%_C@WZ&>YBcc9k02ib9Ai z-u(X1rB!QSvlD8yOY8rg66G$G&4GWYqSPOamemAGR%6Xwjb)>vcnFqx&2sL-nR7-i zTztx6idn0Yf;cDLfJ+mImT^K_g_2uo=Dxp`=JflMgsngQ$_BBvLs~^+tgjlTg#HN- z;HS}Wa1Vv!59*_sL=Js03GG_Jy`+I07H}J~%Tm6aw-EZX;{AIq^WL8>K}flAoW_r& zypzz{f23|DH9uko#?o-wx+7;(T?w%(E#Kb{sI+rPX~mX=cqipH&v}0ec-kFGLMu+Y zuB3*FHeTiyDQ0l6MM2&+G_+?KXka!h6T6z^hGfJ0+Q%f>>?FjWBDFNg?&v1KQ1`kf9SZIj_KsFgvqYJOvNVT z5tIo$2dRPR`FXmD-T$}5@qNs=^gpDA;j^2V+dj_vTTn(QIG&05tQaY>=M6&tS)j#h zKfd?KKm2T7B>BJ2`u_vac=W&I2gi&Ba8_^sIO+e8fWCkZEb*Z;d;7;ppMmmt^^d`~ z9O*-6`1X&JzA6FzSG|IYpXu8eIO+E$pg(WAAiBs#OGzjF!wKjMB>kE}=>InX{XR)Q zdl35f63{;>>D3(q#m3qGa>y4f`put)8G>RK71};d`Y||@jz_G|D;0qXy^1oYcy3L<{*VF3EK63{m;uHF3*ufgXj<5^%I{S zFRG%?{|rK34Z|OA{3hXr67*5`GDNO_`;RA}zh;i07_9$gu#fTTUo%(G)7=jH$0`43 zaq%M_eRRH{dc{tRw3GhZDe>vASs(}pn?LuZ#;5<~LP77W&zV1wfd0RRNZ*QeGG71x zN75IFW|;pv>&JJXBcz=A{_6JIa z*8WB;aPj)TrgUiS|4jn==a&e2r(^1r|Gx3@>wg|!mY~mI@;{z{{#(lg{b2GhognI` zmzdf=v*g0}J3A0*k`;Z_bFHLzs2NLHDe!22VE-sO1q&yjpCaj@-Z391{jCY;vn4&u zL(IoX|8J5WZcxl;VS@V2dxjGGM+xYcO8QALTy6IhCH#*G=+_UCUY{t&!rA^UlHNN= z{g+63=lI7DX&=0B03{`(~T(n0F~Qv&*=Wj z=u$8L4E9^_3+67!&EuFu|1J3cO0#M$;LR#v>sb}c7{@j~fSb$c6Mw%7`^|d(-aw%2 z!yo@0f~B|b9IG=ujeb85djWbs)4nW?b+qB?>r8*c!euFG?FCxKuk17#lfYNv;$0~C zJv7$woDE;$I_VT#zNf`(!$$!=g?;RTsTa*)bH~p45(;IgH*Iqu9bVmB%W0|r2{f*0Rr2}_qL)L+3XTJZw45hzk zam4)msL5dxTX5MG1;wRhD^{1Uop8-3Kkcin-_XqqaB_HHfcM-0v0ebmO_gKAF+8*}c2$>(KEo1Qr{hg~#Zer9CP zpMS}0o|(gr-X`YxtFT`g-@@+_;(d>_MkHhR!9%Pu4-ehGEPYbcyB)v#(IC@1khb^z zXtTh1YFsSbj&nBs(X=D~zm3b~%(R;QjpnT#`@hinrTf0}wXUy!^O5g7_V4V`v5$^_ z^wCEr;m`Jg;j`r~vZaxn5t|)qF8dP3j)vs?95#I8F`DOJXB(fz`|kS9^VWtftP*NJmQj11im7>@iqKRB7MHjzKMSy;py0azQZ14|IU8Eo?<^_|A!$4 zBR?;&pQ|K$kx}p_+0Sp-|FGY)m)IZJQP#s=V<$L+H`zPvU3PLP%rv~YdB~sPT8fsg z;T^<`$Cd_(S!IkFJQhMRFY+yP#HJ`dMRA!_4W6z>|E6j4uw(FJtKt za0-TiGj|9$L+Ia7;z3Et;JhKU3vsN$;)zMs=^dQkkoxIiS7l@gUdo^J{-&W{taB*w z(4pv7#!%Y*eq;rm^h%w4Hq*B69%JpBliGK0l)m;0!(!rk$KOlrYolJVSN~mXJb2jv z{<;3RXzSF!pNiR^WBPxjV!UVD^N;JNogKTgV|P{u&YTXoF1$Ev)}?v#7JmH7!o^FL ztz>H|)_vk%s;Z3!))?Fv-F)5k+jrf(XYXydf9}q^@45f0|JMD`x4!+|1K)q*=^tTK zo;~=}L%;m>Z-2+|3o-ojY3cj<@T}G9wGCR6){Jz7!|^+o__X5R&uH7Uo!U)2FDM88 zcXteCyEc*?W-oJ+KjPnG0~04*iZi{lpZ~`acpdfsmABz7@%}5M|Hj@kTcv597@aT+ z%)|(k7($wxtF0a&4^%yGHvY(o6T-{K10Z8+H2?1SQ5N3`t-+o->5#fZE6 z64PX=Gos!zcCkYII9Eylse#wxyK>yZ_v$+-ykrgZerl3ro4+`-owBx3w3uw-8WJ< zjb>=s+9ld-ZH_h{@xy%Wa&3`Tq?J%CQCqI9(yl_PQoCBaR{NB;UaQgSG`|+mLRwgB z(Y9z?wHve@8vPQ)XSFu%7Hyw)hxU2xF71ne+^c$(b+IeUHOqCWE6+90wb1o(*Ojh9*J9Ta*D}{i*BV!aYn|&8 zu77b=xvE`;tHIUi3c5DBqOQ%Z>s;5nw!3z@Zg%Z)?RDMey503T*PX7rUH7=|cYW3M zZ?10FL#}VRzU}(1>wxR~t|weiyME+))^*VJQ`aHaFI~TO72vMdZ(YB09d^C!`lIWZ z>s8n5uD`n8a`n3Y=6cVixjpU??o{_k_ZauN?g{S6?qb{wJI|frp5~tJF2xMnDyaIbckyVts}aevbNX?Gd!lKI@V?t1qIcayu>9dU1R zx4J*$-saxvzRA7Y-R{2C-QnKv{(`&H{U!H(?ytDN=I(NT-Th7X3fw_^#Qh!jWA1-< z|G@o}`-krT<9^Qlg8S$07u~;d|Hl14?$x-X_IvkB?mxJXx_jKOxlg#?bid<%*L~8> zJZ{f$Pl_kqGukuOGu|`F^D)l_o~fRTJTpAmo=ZHlJ##$sonL%~-sJ;!xo455$W!83 z>RIkt<+;jJ>ABi-t>;so^`06}oyYG9ctW1Ar^U0yv(3L z@43tKMbEvSFUR2x_DOyI)st=hb^;MT==p}{VeozQ1K@3M$oD*td;Y`oq~{sWkHPsT zo(1fA&(A!+@cgIezdZl#`CnPv5zi|haJ{MxfAWk`NqSzx*eC7z_-XnQ4oWsKTt~Ej z_}6mSww-nuV>j()&J#Vx-Wq*=@0+W&u9I6`T_<<3j&X=b@5k@ozA+*#?{ltm+wXII zy0<|7X8nCT|D|_3(z^j?+WEa;zh9(3*}I-_c6^M(B0IGcQ*p=pN z(HHcd+=}riW*ztnJ*|2BA};=0@*PLO`z80e-6VH{GyFch3$g<|+k&z9c)cyxbD z*9!VhZY}IO=GMF47*W)_2yI=2b}q_g`HN0!T}bz3-OoBw@1NYUNK5U}PMwn9F)iq$ zzGm!TeM}qi5YvX^Zy5eO_;cgWg+C2{>>*VT+W{E*&d_(JZNEanGae=$seq;6PsiU7 z`Pq19T+g}`zt}oOU3B-4%2Tw0{4&PoQ~vLv$GhIG*SdPETwQNp?S|fZFeip#9JG#) z0e7prps&}>@+N64pT@;sQ<%Tu<&ylyn#K8nnkD&J<1ZNNuhH_$==t)nd_SJ;_}fsk z1~?<~8(+RQ-(Ta&U&di$@*DYc9pF>&cXhu1<*Q`b1X=b8z$fBwE9WifCX2F{KLz;5 z!M7?uOUuZkvSoM@&qh4`FP{T`>(RdR^EcE~11|&kH6|aTAzV(w@x5r90o-YzsRQnX zplL{qUo##2{lL8#G>yQ`1Wh0@{>xe59|Z19(1d_H3p5)OOr&wCkjjE`~SOu#oROxwJxT;#I_UX{p`Z2b!7?%QH<(sq}pYWIa> z_%u5BOpJrG%Yk#7%8Ry`?Ra@9`o0`;SjPMAe_4lIR&t%8K9Oz^?uMGw{M0|)TJEnI z3H-Et-k(!D9c_)RBdxeCwtTh9OL=@!<)u98RbH02tGq1#g38PCe^+@~en-2kPnO@S z^0NFvm6zq;6L}$jiSvvD=VvM}%l}*DC67O;yexl1Dc6ma-OG4gR;BH*s=5Tq*OhS$>4!(;r(K`Xm2r;iK*m*ie#SXkU&aYMeaLsD85UnyW9P&;wrQ=880p_3eF*8RCgx|H zK)P?(fsvXUe2^dJ?#q}u{J^O3cy>(6&zS7)OD`LKV00Gpxs&rVE^+tS=e4lU=bE*O4 zXSPAuqH|4KM0HFen&Om>NtnwP%_NhC);epQBU)>ni^q@pvi_OWer=8vr`!0)u36M~ zr@WL*obdIQ5q>h&~G2Wwm9}z%r4xPT`v}86n12!D+pTJd?rK8znEhd`vp- zt5`a@zIZB^yB#<3%(M;*KeiqVPCk#tCsKS-@-)v(Pe^mbeO|xuNmTa-1@~e7c8-4` zUw_p+nqtn?_0K3Dgyyp4^F@lY^g*U0*Ey3alxr4i0}N zC(hiO-Em~Js?*Zxc=I{(%w>t?9*2i$OFpkt$V2ou@=R_*K2~32^_}!oAHK7k{G#=4 zz5RZ+z1-e!vPJsXo#kYUs2uU0yqDaTEz&R8Ssnp=YMimM>WtOR!Z^74wL8n>)vwnH zc)xnXqTWPxSn$~X>OU5A@y5oYvDO2!IeMFg!?n9yM{H&@pEo3faW<+gYC_r-6J8OZTky>E9K+ta&Qxv#%jS zm*c~geky$Z>0R7b_OppU9bCp_&&if6o-wxkx6VFWb2eVT;_~?8F30?|)?@u`r@at! z;cd(bvN7VE$nNu6b0wb5&|S{xT9xew)Mi0`M9<9k}N+3+FOwaHnRWs9sn zypMUY)5&+>`DWE+?TLpx=C{7zy55K0uDaD>7YFXwko$1$8RA=)9A9f3-iK_$A7WiM zBv;pv$D!>E@%?;qd{1i}zWgE9^$llTACUcc+{t&~d1lG$eb|p5zu&sv#~g7DuxB%U zr1xQOe{pMEe~!lne&w`}))*!7tMr#{l>R$IEXBgtUrWr(8Uw5S`nw7E48JKp{~sj4 ze=Y%h)UH8&U~8{tiwR9}`sG$1H{rFAg zv`-Z=FB&J?e(r6%d~NXRJvO;paM~~GmwmRJ&X_HJ)?Cs{KWn42;1mncFSx0k;sF+& zZBLzTZ-)gZnd$RyGGltwZ~H!<$MlMBvc>eM+$O_ScD^?FwRX5AL%q%px7wk%+2J<) z&)eY^f8OpJ61Q9b@=b~7;Wz9&ZFN1K0RCgh)r@n*p1+v$R>oeyk|l8xp`b zC4lct0KfIK3FW3@3)Vcd##Zl4OcxjbYf0kgiFt31owWB#-WEJIcB;E>E~j>rE+jf{ z8)#3ikGk0*53A2szic*pN|N{&CyAezB>t62;x9`Qe_fLJ)k)$9lf=I+N&K6W#J@dB z{Ckqb?{?x_>%~B8rT$$fon>n*J+;}3r=9p#Jr=&jL;tB0-zu~4Egt%B1->;eriB6%bW*WXQ2m%_Up zb94}$xgkmX;Ys4RC5iv}B=L)q#9x&p{+E-)|3;GdW0So_ z{x6cm|KB9>vy;T1pCtbAB=O%)4xi2y_3!Q}r*lPX?`N}9PbaWbKTQDtZ36fo6TttP z0RCPAcxsz%FKTP&g!phCwnmSOtvw2Ek7+2M zZ>pq;@!@V2eB;r@#s7tMcSo&JMYg>=wJ#Bz@Kl*o%$S9$FN;PLM1^RW778~5Su4j;$z1AXS49a!h%^1a{;@tuE$_>Mh8 ze6!CG-=Z_bchwop;&kIj>voK z_WOJK=bbXNY}}F2>deLBp?|}9C)0N4>v6#=*)=m!9~4~OJyU(te{9uL6lV=qbWWKN z{79OR3(=YUj&t-sk}+_5zXrl5ym<172iNmNf0AueTwYfu=4HuL>8?$t%M#P6e#FRg-B9qYu}&l_ zy*e=;6+78su4$H?7_cwF#608iirc@NKL8%L51q%GQg>CKtu|SG)~_21KWj|m^635m zczpK*;Bn6fz~i@j`5kWB=OnsQXvsj>-8XSZn{32D{<`|^r$uYC&wmu{w#qEO(}LM- zytErHxvjZi;o129H8Ef1w_9`;f3;V$$}At&g2mH`LE7_P;`Ug4t#(+j52*gsTO4bH zCFh~_d6521NX&oWz6`>5+EDn$liMJCbIuUo%Wko)%~reg(xKEhNSn()03M$fJmRg5 z);L+ZVZq|*;UMkZ@FCW<>HXGajgi&YLHf1xL#(Sv_~nV#`()vI_N{~7n;M9xl2MV} zAHBf2cd+bZB3}B~TW#~i!q;E3&mSB7-30Jo-7@H&V<6u~#c5Q(?01a@jLEztbiksE zr$<)%Ej-IVwqVwL(|>SFIjxtp2GjczEF5cXvtS=kozFS@at7;q-!>bq=0mQ-fNaxIuszJ%u-Q-V3ilwj7F zTK%E@sns9-YqylgexJ>ffoOx{`)u6ziTysCg=e*&^j*K_HZz7#w%*=uy<6NxwblTu zPqFfh{r_i-OC9v|hy?J)OtPF-@0&4k3f;LC%((K;q>`ayZiCobcXouJVShMJwtpu&k*0Qogu!D zoFTqHI757&J41Ybb%yx9bcXo8c82)AdxrQ9??|{#4b`s2wL4?a5Z?2X&U&3ipG+swKmckuHZ%Xz2w|O?<{`{I^WRPvM?p5lfQ>F>P~6b@g7o|Lpt7p zYw;BIH#E*$NHKdVcb5G#!}SH7T#o+6hJ~rAo%}to5qB!T(?#!cwPYdo(*DNGIC8S~ z*?NYJ-%P=eWGdbZo4K$7?@dnGDaIrs$HZAjLu2;9b+p^+_(n(ha~NyVOREly`-2_j zKjC&Sm5)1(IgN1x-bZWKUD63EQ?USgPi_D4w)#hXaklq^#8-MAKUU({(|@mnuNQpm z9v5<0kFg^;5FgbiHD>xVHvAt8d>U(oFW$)`=7XY1)L;E)HeSCNLf!vu!~fqQ;Qz^n z|F*5IcyGQXqu90%7^gX9Z83NwKvh7i%BR?^!?v~&bHJVQE0}5E!!LW z9z`Wjd#q2&v&fQ()n{w3nn+F-uC=$cV3r?zT5VfpwJp(@CJWcE6+DSf`P)Ud@z+28 zMbn3*u}^i~V*XwL>HW#ACHO6s#rRE?V*IvB5q@K(u#0S)4`V=cDf*{W>&%;YZ%V@@Y77=j#RJ?@@2>`Yq+?G;~WOgu@MD*Dfm5`hOq^G`c&4@FjnBN zug3o3LjLeZv~I=Ixi^b^H0HV0S&`%0KpI2Z~^N}Jz4r_&j9`ER z3x!>MBT9OKH!dEW`uh%k@8}PwPEAzfd2;I$&V0ahC_t&^vl^rvlv5u{EEw8(b#US62Hi& z=}5k!0RbQTZ#7YUM6aVB`W+>`5IW{!{P&dTx0I+qLmRhZId0cmm7x08zsl>v#j^S7`Ic;U~XSXa~r>>v~@UsXH4s;#N6Huoqu50 z`MtVc(6?xk-s8tyJGG5$T!-GR9|oNtjyXF5e00bm1-~uj>R1OkJd3)H&R~6WpqmTy zf&)wOEWDoqKSWHu2z{Bh%W`VK>t~tnWG0v3wXibPN6-)Y6{Yc9Na&V=kwG z?p{qhfi_fbgRL8ZxwRKKdm*E}kkK~(tX{HJgtvm^26++ulqxe zv0c~F+X5$92kJht_u=-=Wt!fWsb#k9IazuK#-)3=i}mdvmD0X>a>{c36zj-vvlCMu zzO(Zar%Lab2R)@Zcm%dv*^i}vy6$$}tsjIfKC$05zP%BB+;ClMZ#(M5ZF3}J^g)OT`g8OCcV#%&44uN3Q7Nf*Y`w8vSHWjg+{FjkmYf_Qy3!hNLwP%J>vr7MITQG|u~7&A zb?Tu`qI+E%)>f-s+ICPor+v0-RN6+2a|q>W6WG|`cs{a+9ho-fY;vXFLbtRY29fq*4N`6oxK|P)bG7m zOCjUFVUY83&@IK2`neqaqdx!Hot8ZY{aXaRq<)W@_CjZxn^peBozr~+e2%zNx{HYq z_#@KZ7)mj4j^xD!}BLk zRc4JZxP1}&cM!IO_-+SZ^dAWQPc_yZMExuAw_IljAiv57QP*pz zXVk?%?R<6m^N?Lm8+dd-h`HF~PRTBV%*s$_8h%rcd=Xj`)&?7cq0K>7QcJJ5rL&0b`6o`S9Z1M$Kcqv(X~3i0*Sf?A8evYpd}%o= z3r3A_#HgXlC|?+CUFwfgsyGme7?G&Vt@KAC9O^^Mssje4SA^>QHNF5_)6g2B#GE`c zIe)I1tcZrtIHRbguFeS0pIdTGC9Ci^H3tkXk-76`OIfgWErCWKZ$w#eQ>cbFF~TaE zeKr1IeaXfa)FdhAjuNJhCP=GU8-4X?JQa1c9V1$XRtV?95vWjTf-z*Ci zPXSwJ)Ks=M8@!!dKgD3IuB(GYB2g}f;?O22S-l|{@YX~9WL;r@lRxU;WJFAms(~Pj zjj(?cMt_sBBphmK=B@7!CYHW1;Cw8(8V5o(jeLlWTGF!Eg0;aA>4GS#@R0(>BXX3) zQZ@K$p^D`g(zv8?ieu>42K{xRa1&$}iTczaGYOTlVONL3jrG)TRvZpRB35<{mx{qk zTY_BqG5Il({WWY&OQgZ%Sr`p9`D=vQg;{YZAQFY)u&+!Lv|MJ#Yl4l zv&L7`h-9&R7Pa^T(Xt?06;s$`MFt{}}hl0eVELe;6pvWI2wZpuK)L>4+oK_gHPjz(>JYac*oG2wFKpL{f z7xp#L$g)CfiKnwk(nqtU{sw6nqlq10E?K&y;s z7sOB>$i#xV{)fm#9q zGb4I|X;8-PM2&%@*?A6Dt0OWie65)0N@8MQ$bnd4Y%&5cwJY7n79Ai<0-KQui=0T)5Ryot41rp# zZ^GlVLl*n75-Cr3b@c{hV(?5*3?fh}v1Ae>p7d>@q>^QEO9V?Y7q`SvPP+*cY%4>& zVP<g^uyX+R!f^zFkfS>9qcXE6+SwE@QfPJvv7F<+ap(2?sy z3qMSI0KR5rsH7H-7*7Me8M^}cSm_UkL*%Qhf;S5Xg9%H-%Im9rbMor=Gj~3oDzlJ- z7FNKWZ9-CjIYw@7-4gs2<<15=hk!@!e8SJ2U6_X_&wv3v1)tpcijkF4yiJG#@Fw|r z{kikSb0Hpc@+d9-6>x&`6eT!Si%8_omx+b+oRcSVxwCyDB>@tP>i)*@_m-MZTz(Zvhtl6>Y(?j?J0)S6VX`Av*eJ3;(x}ML0Vy z53pOvR0`4}Hy(2sK$TL!iUv3_^XAVJ1tK?3=0K1;oBqRww?1gp3a%;%4kj2o=e20Q ziDb+0ip(M)F7*ZKO5wgo;kDAgszrHo&7`QcDi5xsFM<^nYiJnp1@5NGWzUw5u$BHG zA+7W^8kGii#)X@Fesh;^Lf64ZmpgxGw%m?zd@@bS88!jbxsojymRfeL5e~`Zs!(*5 zZxyBnoW(k}s^VIB(}B=tOd;$x$t`8&l_mJQ7JqB-w~E2Jgov?~;g4&LEm3%i_@}6K z9YqAfaDrEbxXVROtFIXjHu>D-e$$g&Z;__d>R_Oi@hneSg|q`eTiIgrcVv2P5TTa< z2dN~cE*5HRyU}`okZOQtNze)-SPvzGFw5X}aqknN^=+}`%;d_JK-5n$kTnJZ5wu%_ zHwH({Co^Ti0QR@MYMER^-QuIh3TrmDV5Ncu2^d(lRbFK)3^+aTTCod*orPLO&@s{z zzWZEhG=&f_QhtTZnhui8$L>8PFlKKlVSIJTB|NlVwonE9KV ze9Z`wG@~}&ND5Aobfs5|CXgBjgrgN^g0I}eQ-x@hJydCJZIpv!L3oWzu;0X1iJJsy ziR2_2L(?I`gEC4_MMwEAe{pNjhoA=cmuMp_T2#v^<0IHZjssyNX2DBnb?4-=N{al@ zuu&s80$=%Mb9h?DWTf_zlosM2gxjpmGleS=aV<9@*dJ2>PtwDu;5_k^5NGu=^dd)= z$5TamWrb{|=r?Dh3R=5$XMSA>ww9}@ zg;NLEGXA25mB{(g5kmSaETMfPsAorc4t0J{c;y`pQY=o$Y zEWL;?S@AHy99m;rCs0TmKLpEQ7-BMO!l6w(vgr%Z*aM5t!2VzmV?z}21*{zqwn<>; zK$V9()(qyYQX%sArC3U^w?MnpFwhV(tB<1M7y z{eZ%msHh1wbGsM!5Ww_zNTBN|&W;U+Ts$N2c0o&y^d@0wc|gF| z?5p+%u=!K!D3SO8@uiK<6Q~Mo58|T69u*CQDQ60K0x_Hy!>x`Ql_6)`lWPiZGtN_M zcu3D`1aZLGqgrqyd1b3AOX!ezRR~9K&1@g}h+w7(F%x{P=Vu8Z z#lnLEj83%?mKi!1fXlMFnM?s5c6_8MR3*1pyo~aK1$GL2fQbh7qLmK~XJFK{kdw?0 z6jnD|T|yxp4z8mU6p<_n;rv=8(O;PoTUUw8U0hip23q0s<12wB>=4drIe+OP@!29l z!UYn=(y-V;kUrIy>5G(o36&RMK>KY{ezm`CG_zD2S|@&)ma3Er{xb+1bL}H07vI>DSdQyaz zo~0tv$%`nOz?T?=`XFU~6QP-IHmwe;%TBACxjOTD%=<53Bn^tV$z^5{33fnMle8o< zwyjnMsK`_x>dAXtrs&FSJl4uqRN{gaA;)IzrHa~)qF`&OM~a0lZNe2|g(_5lQuN(S z^WK{|l-L?t$_woPlq+s%xhS^-P#)VGf#QJKxR^EbsuU{|8q3cFb7UJ+RZ!93uZx!Z z>l>oBmBEDBVlj|9f$0{Vg$Z5R?2j0HY-RcyT<76al?uc_ixEb7sox0Tyo44$fx`h6 z)?%h`*2aL!aq9uGH9;c6>X;d8YPSG_2Pt{!W`8ZB^a2dcCS)p-Nl|RUw-kpcS|^dr zj6gH9CAgWg4sFG49rBcMqers5m;J-LQ!gh*!r3IBu!uf~E zY^^<0fwK@>i7g`rU(j<65lNvSYa0BZT7kXbN+V1+3Z(_0-G>CM@KxicD|86~OTJo* z1SDF^L;1pDZN{QN1HatQ?OeHmlOk%WNZ>Gu`{Fq1F>uX^-_}C4{yM}Ln{XQv#{$5$ z@_dKJy}80jYY^^sGietGQ0SlU8)(@TD7;3Ijk7obhQ2vqCc%Q%;O?w0WL`5?ljJ= zVlc3Ti!(&7!q@|;y{bG2RN3M%T|!<9AuEU!yvkw`H%p=D(H0t6d6LR;;APYyz!I#7 zM-UQyT5Qz$P(OT3K5Hl(Q@d($IZ1#rA~2wx-BY~2m%-5)R@*6+aS>t0tC)$3*v9#5S<)w|4r>&d4z-OwG|R9k$#v1 zEWAi3(6V|K17IrW!hzn;GFn7tQK>)7J$xrA;tbqRbii>^Os;`E8IpF{#+H-8tFZhD z2LnL~4CPnEEr;h&yP~29!c17aGG4K@op;d50FX!`3hnERB?9}3 zV?pJH$iZIjj~r0@dSr31uUHne)V6k6Q0XH$_^!3BZ5FP5#j~IoAj_Y0@R4QQ#fV=N zSIjYc5eJ%1*Ac73uv(87LablEg)5L7N`RP zI{D)USoA`HZ6K0@8L`I>L0l;3---#=%j@9WMMso9L7_ua)~JgmIK`k9o31nQBLv&G zuV9qxan(#5EyTbpjc^n0wM7k_A&T*$^F~_^L3fIC2IS2n5$?vFA%RSnPjDGreKSJ< zZGk-diJ$Ti`4=b59SV-V=mO^4Eem=3DafDTI1`VriH@7V3ArhJad&x8G;!D^za&yg`xe|p359FLMZW=CrcTlMvF3o7b~P~g z{pN)2vYjpuEH(Arg8qYHmtL_CidPG*C@d^066ZDpwlw}7?S!p0(XHFyF}U!!`DO8# z8{cs;5-_m$MO0?H=pDnzj>)UF-vAfqOYu%bX=mj)C#4txpQZgu_`yp2B5Wtfj+1ff zM<$L-c-cS)owTKkcL0i=xq&ZNTB{20sydYA5t9UEGq4+kh4qH&yq8~Y;mq=z_x>VR zUO9u!*y4@A${^9I64$AOh`M-d=#nK6L`>Big%Lnbgkij*7Ub#68g#CSB({R$YgkD0 z34*7bWnO+@g}ilh!3!^&5L%;#SIj)*t|=|@ifaj04Fp52aNB{v&!ViXi0zvB3d2CJ zfq&79Odz4juM&E( zHi`R6)>pt#Ob375d~=a_VSLGuMZINMscMNQ67?|Y@|3WBL@5w8wuLz;DN6KwlwjPGEemZ<>%Dq0C7dD z!$OG?>~8Q7LKW*FDy$;tEHlf$4@UyNnxcdt5?8eG-P;JSQL2Pjw$0QL2uG-wXp~h> zO*9MTL7FP%m(szOYk^TqO{}0Q#c>-_e1TTj*ltl&PG!ZEBpQCw@0~4FdX{%)>Wn4< z%C$f_IXSGd!SLcDr9qPkH!-~-ehAKSa@Y)c2CLY^0}c4=5Qsz#B0#1}EM1u`K)gx| znrlI+))_po1}6H%k#W`F)?XTrK3@yW3n!@*&}1|P&Y6;_Md9UMBXGntAZZATWhT&Q1w(^vc8YMh zLeg0<(tKJP1eM)IiXux?MDZEQa#bTCE7epbSOUVh=ZbX~g*@1R=i(a>h`Ip@6?cGU zb34Wl9!akj8&Q0902uUjGCZWxBE>D1S1E&-R%TXx-@ydXyv5BJGcWHafse3}NNmAh zEB;JjA}#ExP=92tVYbpFGI1t{1f5Zs4EfoHnd4^|KoN%!#EgI8771&r%kVN4awXwI zBa>9m8vLPoxGIZ;X=9MaoJDA#O63s-E7e54sQzf5p?eyWHQjlQxVv0 zwLD_U^vcoY6lzK10YhN(a=I!*r5qUXuE19jkV7~VdkLXhwBQEH$oBEUlJoPL8SEP1 zAq-6Dv=NDVrRvI@ZLJ|~q+2*%&W7rhp5O7v4_VOqwk~}zyC*MHeN#_DyAqwPRRYeAA-YUtj3}2_j zR|#fNZ)l&2Q5RoZkUcOxQP4GuP#scg3u`XMtJZn#`#~~3!sbxbzE-bl6n$~dOZ5O= zQB>&_n+MB>vBAJXxGnTD5VIm;CVXFTpgokVz~0VE?8O0=?;Su2Uud+P4w~1ZQ}SEj74|AMv6K{wAn; zq@|ex2}UhKKyPX>^ZCT2nWh@>&wkEI;H(7BO5m&n z{>dePlR$c}jW=^%Uf%54bMw5_aM5eMp`bTBXYTwt3-fETyfpzF;Cktx42y$zVb1KF z1>VetXtX(U*`=3ab4Cnu>O&!V-4x%>=hTFnE{)=bH*QS$gO>{W>Us0(@@nTA)pfOV z=2h3tpF5{EZ$WK!jW4&lIxlZw{=5aVXD^(eyC5qm-hsfTChwe@Ir($yj0L_0M(&*I z*>%;vxxShO^L(>&eZKh%=hQCn&8yDMt*HfTvwJI6tXnDi64?~YQlmUZCba9ynf93r zw2!4{FoNOz!~AoRd=d<=3gsUiFB_!~!3rpWPpx=x7+xaEKXzKYuaSRh@p4A`5bbAp zim}Bue)}YBDPA5+AHw@8Pcim)k4O;gF$uHR@q8TEVF^=hC)zjT;Hf^@`JE@*Wrxj< z15@p{<6RR6FCby|wrr1sM=x`wkDcEGacI9E2k+-`V0fJ?|73~>muYVtymUD>_IkZ> zU~}WZmP(j-YpfWzf03}};i6)aeY1oe#*cB*hwyKdumAzpq@O?L9@m#VcMRXJe~!PV zmVI@Q@*fURPO^SQmhUr=3E26kem?yRqwXAY*VxW+cTe~t={&V(oYcMl+ur+tM_FBa zqx+o+Fp~rb5JCcI2E>{KjY$Y0u~;SvK>~=81f|qE`8O~_LJ~5=pNL98+b=NK620lBk&bTl>$?15) z=x?YkL%&IPZja-o@D0Iue@I8mv#Q_VBeF=&Yh+octGA6l25!8eWMG}*1RxF~WLK*SFSEl%Urd64gim0g|99%Q4 zCu*69TIR{Za1Htbc?)DLE-V8QsY&5^vM@sHcx=_YVD17Q z&l67^nAOFL;2|1(J6I#m1iM>J3W}$EWkFhvQ#>|$+1w&tsf@qrNTErCg`$|~f=QWN9$Ac@nU}*O&!H%sNvV8s@KK(ErVjH`mE z=Wn5N=w(~V^8K)`WtD|4{EtFsE;I?-1Z}R(P1va8UmS&Y6f2`pUq&QxVusOM#mQZ> z!prGhSvlWTURmH;QJ9P;Oy(t~M*7A1i$P8S992FQONTn4O{)(Rl<>^Y!*UT7kSgF-u^=m*zccDdQXv ztx#@+X*ZNmZX!<(*{ibLTzY0poV}_KiOsdPs?s8}WTu*=~<(9UYy*y8atp3BXf$K!%J$ zwK+p~kvB4=5K5ecyOHp7LM6qG5r3x%zFy)~oKRI`#IKfk8TL@cn2P;9z?`EG2#(xm+-C0@m)RW-);H=DHowp}0&D4F-HOAyRrSxOz^2P-Wv;l z8wf%b!^ZzYiC3|6MTW8c3KP6%l~LJ#jQ{gZ@J@-3CBHQ$_{LGT|CkAW-zf3FFu@-kCH-%i;Cn~e{v{K99Ddl7 zu2|z|3I;?p`DI8v#qsr*as1q6g0C25`wyGo{iDQhH^DzYO8g5Z_*X}XKVyRLm3Xyx zqj-qo5!a_C_%9@0?S(0j5ub{Aj^u}79C0_#U3F0wew(P4HK{1c>kHje!4? z3EuId0P#J)5%A?;e6;bG`f~x2W*}69k^W8-{OuA?`+@q)i2pAVZ(uWfRN`aV-*-&f z@0NJJ&!{87*#2Kk@E=HgEdG_@2OXpF@10-BMk!Nw8QXu%4F8`6i0@sFfWH;HkGp2~o z3a4`aS>lcJXNSah7#vn(f2cmA?WVeuz7Q?^@2FpY8QZUH*;0jb(7x=tmX_@1I~}?6 z3kz}Bxga;k;h3M3>u@;oaOZI3=HwLQ=Q|t)MFsQ`S9Sc3vK31#TDV4y{S(&(eS37j zEnI{-d8U(%p-AxG&vq{mXS;_TrZn5R;oSSCe=ucoIT>7gDVyQ78&r@@l6d2oaY|^c zF*9A_W%1BkxlT_)iBZZ@v1mH4@L76r6#Siq^SB19Ke2Q^e_nne9|T`P=RepNCc?>Y zoj7w}$A+xh*-szTf>-ae1g~$m2Cu)tIv;rF+rK}Z;vBqUWj%f4*r46!9L%`Y8O+pd zXELvsyt`;T+hk8=CpOMtRoRo;)fTGKUq!_M)n z3jEnOi?PlUOZzG`z2Ao4cVA|2pKROt@PLik0(QIeM5Y!WpQ+uHXUFfpdr+r0-Z>aA z>&&Fzy>IgzSJ7L%H4~ow7))}Y434fu&z^mvbO!!T>4{HVJaFlX_M67l&;Hepy62*fhU=xz zG(47gP}36nsXWyQQ=j}g+UOs5Q(kgr!okB9d%pvpKe5_-x_|U=p@*>o$4(dI$o3z$ zOzpp5o!V18G*spP78}&d<3*`AHK38ol5GDLI^c&6bXcG_kXgIs#_3ixea?V9JZssB zK8?+%v36mca}eXDzZm?vzP%LVu_XBEgT+CN&(2d;*ZX>Y5D(~OOoI(d#=K23Os26L z*7qq~$A^Zre0CbSr!~h1<5-{8h5HVxA81zN^4v{UH#g~rxY^K_(50+ir0UyWm@tsMe^^f@hwuZ&@r zw4~!>*vporm&dRVEVlh)*nnlf1xb6yJV|s8X*abb!b3s1_BbjxU`4sqeR1qBmUi?H z7nNbhXW#*#88hFzmAyCPP0S|GJ7&IfD?92qir_7k5&cD<{I+hZ_Gr@cR_&;k_%gbo zIrdw%LmBz{=jCPX5sv*Jsswqx3hS;sZOD=iTv6-bR|1@aRMD zShWwd4v=Qx4S#TDrfngcb34&9U;EaIxT~7>yq58W1}Yw6?2sj{+rqjmX!2!C+;K>R zZuQj&+?u!#G_75m)2nH}AY8j8Zm$K8%%Jc-OWYxgwm%B)CN1fqjD4E+q?QCd)8Yoq5_j67?X_&fV>#BieOBlfTH0@o>#}Ok z8<@i7O>$|sBtCCtdo84F#2b>)E6{^ithPVe@Q6y{+cpM{_S)Db>nSNC(v{OFbJ}YA zXe?My<#An^c=N#Z?OO19DeJsq)wtfHRzCkAd;dAuFM6jJ#s{}?SMU2TnEM2V>`E_i z3VVHfaqv7(qd8+r&(-^0?*=w`=nd`c;1o7E;Id+z#$mjUK^Ur*XD4Z&@_7% z(X8wc@#MlpVdrMS&e2?Qeftvdt_(a}92{_!1_!4&2f^~s z+d3gL!5=lBD_#&SR1c?PXlNSQML|e`q^SzFpw4igzE;(h^*#qY-r+yxaNog>f_T8td!_cRy8D=+)SQPp#=$ zkB(vYU(jp?;(}|agLnZQ3-RlmHHF`M_BcU)APVvE?3Hbe=M8yp~coP z7run5=TFudSsz(viaKsa9oqDUE{qGp)0nCq+rDZRd{p9f4f5%o($9~(IZvgZvrgxD zo(`WRoSw$hA3=Y%puW>IhM_B`bmNxB6MRliqZ)6@H@&7CZ!|{3{TAcZyH3b$`IVun zKKKbFPc@ES;QqorkoywIzYKb?82V5e{Gz!8zJtZoci{RY#}V;}`aAT-Sm@JK;8Re~ zG}M=hdefj!(_z=fcBX+JHoU$Ey()sr2Z*kE5J{K$m%yQOSI+t0BpwEwhlH~M=a9qk`vC(eUrVaJ4C9f#a5T4(0jfZ;y76+ZiT#^q?U$~DU7>60_H zG`>dZyM^%6dOpKDwcmG(v*_Y&#lhuP=Wo(A)|z;|_}v<9_kms7o&&wsRNhA_QrHsq6Q=d*t_zJ-yMp zabWMQ&Zl2)Ydn5fOKB*E9>08-bMRx}yRk;I!584Rq^4=-30$(bYld9M@4J4^F~X zE54FG*|ad<-~l9)?Wc4cOXBZ0l6KMyYCG0=AR9`2Sc~yMc9i&0ZWs^ObmJjSj)$M< z#>3#S@gTA7}Gmu+zebrG$A=AlRQhN~U*o~Q2BJBN zJ`ztz7ma$jRHujJb6np(vL2G$Nw4CiUO~QGzc5!O6MdBD(T(97L8H>QPbS_paP>a; zq1zFQc>*@GL(FwAfo?TFe}XxW=IChi-Z9L3C*{0%eR~PUTXFD{ais&ae#BfbqOU+U zoyIK93s ztebF_s)~FGiV@M+pxBTHzU0YuY?E^wtHR1J*#keddo0WM{%T3EF>7hC0ro=Kt&d^1 zmTQTDldxsyV6&=s!Ty7W29)!{CK9$miw`uyF7Ab0%=9)6G{7#B-;&Wb_xJ|bx*f8; zQ&v`m^*y;O8-_yp0H?y&y;{j8S`PP5ws)GumF^pVfW{PR}SQJ}H> zt-#UTa_ZskgP6~YK81hcnamd0VE4Nxv!m3 z;pMq*>f&M)N9eWMxNJU!Ji;`Sk1lKpwN?F(&Y+@0-`=O=((|Ye_+PpA!JypP&Qx3f*BNSEO6^+NtO3!AU}H8Ee_loyY2 zX-uQ}L7!GjF+lW1pLX7Q6JPr&IeZn`a@tNh_i_dBdsIdt@;C|cqjw$Iku}$#6INwjqI1o^WBDY2K>1Mp(DK-J35H+)b^=|(+h^o#nH9gD~tCv{kFyI~WdizjSYr=_>CO|aP^ zJ%s#{=6XGaN)J8YGs!{q5xz%AZs!wN-mkvY=_Wq+=s%^rT$F#3HWM!S7W8F>mM%a8|hiPr0wY443hyxFIvrS9Ku&UkQ-Jb29 zZJGA?fCFP#*$uOK;baQiw0|tS|AqMQ9Ci`BCc39XMoZst9ruF&z1HbHGjEMQ7`87n zdx%b~VS9)^qLcEdpL=Yq>ac|+E8iXd#d1pjSIp7>fOI=>nR0&2m^1yLE!SCuKIEIx zIvci|>Yht7kaLgT4ywJJlX;>q#nMmMj&(QDehK}ViS|4R?Ea4bz&wEQ6n|^t!R4?O zbK}?ooH6d4CF`cVOwja55B8@pW@+D}0qgK(z&k;Q1M#UZBJAvR%!`5-N>)TG@s#@f z(sIPgEbw_Dt0LG08}>|WKPY)-k=528xI9#~8vL+1* zQ>xFuRpw(ni7~@Ezx_4(dMaAKqNKG);YqJ$c>kSI(z@Wo8u^5IVpy8uoddpC-;Z}q z_E>ERoEJY8ef7XUQ+>Vb51s)WpH3!uQ`(MkY!lY)o#a>ErF9?!O@3XZ{)$j#R-mGnU4SqcNjULzyvQMxv_h%v2=(>Y# zItRLx&2jv}b9^&&4P$A)nU5SA|8rRt`NFt|t!dmIkv%_$eu%X2y*`GDc}o{VmFoq>P+|Kf!RGN8DvgN}j0cMO zQ(b0uU)gmkPyU%&7mmcg{qeB77PcvIV5sU#8Y`GDjB9}+*zvTfET4GB<1F7R<1yfb zsbc=6H8FURNBk_m<@eJUX=xjvuT{4HxnyuFXu*Td!Lp-Y;Sf zN?*+UCB1&FlYBCcZPGV0e5~=UVSMZ74Vp8~TW{vRyRc2|+%{$5{KT@?T*rHuZNam! zE5C(Ji-(RDgC^Ba8aJw+&&G=w38j&J6!i+foUje>zbPg}dnJ6&Mvfb^ehk4DLHTud zO6-?h<1wRY4b+dDK}%$Nq8~)>Nwj$e^gf62O6?L4N7L?b{)u+UKAr?k)Go!H)P9DD z(T%*HK{g0H5oa8fos@eR2iY&#Z`tdt0R7uq`@++0&J${`K=aTO z=(6Mq#Wd8t2R<#$Eq{x>;UMZ>YHwe))M|@QpT#y^v`){9o3!kaj7g9y_B{7I?tEqr z-v{~I?Hhl#9{XKy{P*2AHpXj<;fK?{_a}&zQmh9tk%mmH@v596HjR0l&&3|BacF%U zd^~vY6QtR_-oo98L1Z8XavCuZ%uUIZ-;K2_*4#Lg#EuHtiWp*Ok6YG5^~Jx?ZDns;D8(}5%$9v8`h6`Dz867p?o=7UveL-y10n?mQaIu%nKUd*UKzs zoe7K$COX-mZH^Y)fcSVd;MA=y<2^ALe@zSCPD9H1ID&e#1-f zX>i^)xjkZj5%&K2_A=1F82u!z6^RRFf@^k?C&jaxh-4gHv(%xKun z=lEnEYyYZr&>R(wj-gWR?6m|o`00Zd@C#>Ww?pRGqtc%pQ99Cxcu?|8oGXA%lmEhX zSr=bRK}_<)n^`NZTW*D1NN3MY5##;Z6jsE`%Q@bL_=iXGvH-p@;TU4Bdd$Cl$5#2N z#4W)3kMd4GZmU#v{@cSzmDpS3^)A4=Pvj?s^B+$Q<^R*?L-T2kMP*cfK*J=G8POqV zbDjv|jK@W+-4=GAh%iG|>)9*V%e%fk0q0dL zot3l)g*s?2zx#=saW+`kj&tDgP&zw7`}%yZ*~)^wPdtG={ap)(o}qN>k=_~N8~}~6 zc)V!MxePDIc-u-!E7sQkOrJg*pDDf6kUmGIm&tUZLDfZe>{~Mb9s@2%rWfOUg1#NB zsgE#C!^?t~6|XqF#^5y;uW@+U@Ur6-k5>X-iFl32YXV*q@k+vL5?+(>nsS7_(0;c= zwx#WCUpTB^XrK4XK!;`L&V{Pa)}6Z+4(qqXl^JkxJD*sncrs?^lM5AJ6i>b-arYQ- zV|V^wq2krJoj+VSj9(JxG~kkU{-=eCmuzRpLZ^Yxvm~y>fYWyFUN}qg#j*x;zzM8r+BaQfb-&%-S<~s7in9effD;`j~(gnJw{!>5ce(X(& zN0ctm=Nw(0LwBD9y;psra!S^8KU-H$vrjmp`bT+6wsb#7S5Ebn(v=+PUQefW(!?XG z@06#fN8dghGbw^LJw5vN^>mrnH6@}hDmNxA>4;@K#`p_#E=tCJ4DVzcgHJrn&(yqt zwcPdX%Y#=c>71Z7WK+p+3ggAOE~B4HHZA$RB|)-hRNh|9I=d~&{gBt76Z1$z3Hj|) zdNyEReHr%E_gLZsD^T{1r^PY+u#A!0nyHI-kE4ZOQu2 zG$%&*z>pEihkPk6qZ*v|fxo?bLi)gl3F8LHme?J|MYPXBXX} z*)DzW4xR5!aRPOgIkH{seNfw2E0V94jAv}J(Dq!keFgp6V_}006KuTw479tuR?tB0 zcVuZ_t9^#`5%EL6?%@8vNZ(Iu1)^826?hyJ^wG0J4DA}RDt`*{t4qXKGS;DQi}=L* zjQ&!e<8RO!ht@ZsZ5aKL{1$Si{*tWi;5EtF3pwwJA?H|YEVWKleIJdyiDydQSIGuI z-T|Gwy*hb&q`bc_9eNpX{xh6A1pkQ_w5CMbpoi9yS&{l|L!Re{4CnkK_2TQ+N4iCI z+MZ|bA`|WISL)=ZRWb0g52T}aWRfGKp0ay$ z6IOq3!+!il^l|z4#f5WmwqY6k`FNb!oQ-FJ=v?DPU|wfzem~ynd}DkDbQ1ZyhKBN8 zHgOh)+M+gY(NY&AB-1lk31^_k$^F*&9$MGw+e^qP4&prMnFdXJiPG_?PnC<#hvFUW zAFX4l1@VbE^9_6VbLJ@6jTnR;{{-^s8Nf`~etVY|d;(=`Xw&xE+<+~W;kkhX%sEl| ziCEM*s|C*qq-Vt;7Sztt-$%JD;)g0f;CdBngUII((YMRACcX+RVkteeXLAMh4{T?7 zuf13tT*Pes7SIm6cV@R`%9%x)tv}<}9S732)c$F|e*VBe!QRrDy7O|s;{gB@$mZ^c$m`hJu zru6qChJmjO;IiClaTalT&JXja7yQA#UMKcSI;nhvlqI!K`k|MliY-w5_KRi>F^}jm z+(ponYVai0Q5sBn2)vf@j&z(4p!Plk-OGMlHt^kBSm%7uMm$@N_d%p*Ok9Fz9vxgC zmLQGFeh+0IvVMPHbsalPG^zc%ZuG|k+Ypa<-dpsn0p!$ycKeXljkCC!ZRwTpg^Gd} zR)nvNNZy^bIGBmkj)*s&rLu1!W+BFa*#D!mO&zeK>E6u3-SADQ{&?%mGhVzp5PN(H zJfgFUr0X5OS{(Ffw!k)=t;92G z?<4#UmCwi82y=qoKI-q)STVj2PMk3?;L>30B4b4u*G0m|)3P#f#(noXoMV9;=R=N* ztW&uU4Y?OQhgi`a;9(kM^n2(7<&iIaatZr2&V;}gvIReZ3~B#8V|#if&S_2R;I=He zXBN_a0(^$G{pr4;KmQeHg!|D}70z&V20z>JF4>=q`Oh9m|316?B6N5F_0w6YfzP-9 zhUO#URqDr&VlESVZWK>E4_$?w>>=KsT+1$31E-!Zv*8&C>=RMkdN2d}(lHj#6j;&% zQ(z}ZXZ10m0atNwa9kO;S7CqUB;sh?Z{z1{s13c(MEt_}0UkpmIjLuVG{_cu#`i!< zU@ysDb1W|}?o}Il+e&p%IVF4UUx0SKE&Xz0I`<8z+-K|mSHwk!%aYS#!l4Ip z$=-EC|5G5de+N%t^Rs9ide=IGS&%W#F`ZpzO*!Mj`eHWr3Er|K2QGr=bG7Mbmf=Nn zbSchYc~Hkz$co0$R-GJO7(bAE)zZ&*Am)$z+})#=;UN0_TRui+-O*AK*VMu){t9Q$#d-ApfBa8HHm0495dW z_Mff)7e0q7Sw)kJ(H|Qr)-J}Ag|C^&cj(aZU-6#C*InR!Ie5Paye|O{{{wVqTH2r9 zV4Z#@6TBxI_XN)I^vOPxPnA559nG)^StN}hiyb7F+=E;eyD-1ec*343A5W7dPVx@p zD3W(U9q;<^oCVI>aQ@N#G~64Njw9W`@|8ERyV?3kE{TuVx zzmn0&wk*th=;neya9fq!PwRW)-4^IE*44*|AJCUUl0^}>b;SbSW|QxT@A4SLf}x0fDXM=b=2x4}kD^#Uc*~zlrkF(d`ChS?)(c;N#(y_r9cmx{ z9G?%!Ul!y26MC*!7yBn0PUDf=a*0>AnYV@Yz5dx0@ec;P@ekk!8l~7gX*Mbq1D=f`m3j#_AtRW zK1cnJGfZlc}IFSYHH6%@=O`lQa9{5dEXS z6=Ra-U*Ru_&m)bo^JZhrYB~Ek?33AZ=K5#H$X2!6+0hQHYrRZ6^Ig0KtYfmEZ~b_# z3~PBS*7TO1X|EkVuxK2+oFHurjp_3^w}`XlVob5L{#o#ShQ_kX%i$XhJ~&XM*(zBq%B+=qDIbZ)Q3+0vz$=cp{rlh>YLL6jRL9G#KG z9(k5pV=ih~K=TLU-gu4|`;y{$ex>x+fd0c+uaj&juAo2vR17TPu5TZH2I_ONq4Jq-YL{rC zv8tzqu#{&uM^Ei?2JtMPh$(AWbK7?J?}m@!N8gWGlFuCfvg8>%e21*-kH3rWr#NQQ zlFwZH^N!!R>>d53v{t`f{0z+9)FkUq&37qd}`o*j!6Z-(jk+Sp27IE0OjM{+2s__^Aev=XgpC| zK%5iUx|RjWH^tm_l=NE7HMG~P))lA&arQ``Q_a6PqtJ5>IGo-IweeSOp!Q*8pw+8uX)~SI- z*6IDHah{y`tgy7_VMG3fE9^JBd-nV_*wg!0;(0fCU>hW#C9VIic^wD-9scOjanl3r z@?)Hr6es(f&JB&78kqXM83!#$S8`Z`&&1Cm#I!PSPwVaryIcdkyZ-CK;I8z6u3bM{ zIQ00U;Lxs{2d>q!vxhCy`j6rL9O4N6hn+#fZJy17+rV!Juvai1Jn}o7dQlJ6eHby8 zYtTPhmnOr{5HgAGPm)}QzQlNjpG0#EVlkF($o(C$OKQxO-lAudMi;9BsM_H}HC<4!|NQ z;d?GV#QJtA_Qg(I&p9il?xc?a6xz+xI9Y>DrWS95u#Ph>HSahTT?=|4{A}s}S zi|=uQz6&YN!jq7_eJU$_0eN&5Wi&LsHaJu@;|9|7A-*e&XzD`$j5PVs-yQJpqs8yk zSRN|1;2dTg?7$erT*l%I3ceF%yA5##OXT<4;rVwPWM^|Y&-7^dJvnsiuvI= z>>*Nom9HVNX4sj=sy1UR?*`xB!nn@BI3@o%-cB(w=*Y2-0~RaR6R?rbPOzO>^F`@1 zr=UM#3?}ysT5V@&oRGfT#-{~fx05%#=nOWXPA}S_7=IP&%+eCh9GLWh&?@d1m_5!w2q4g54N;?A^XpcFcK2 z*pA0Q%ToT`aO|?TmUT`=xuIWLf;huZ%!g>h5X__R$kg-JQwS{fyT5)nnW5K1bg<0(=(s zf0t^uGkw;K9vk+5@l0QUzGr~pSySrQ1E7)ibdOI+4S3G8;7UpJvZ0c94_i|E?TPUL zTjKP913Hjc%FZU-!p`o+dbI&IeDC$rckx|#?>+^+I5~-3#`kY@l8w29@kiq$dtzeX zcZjDg(kAquNBRmp-=3J57}z_Dbsn}P_EWiAFou8i@#9Y?p`Ej^;dj=t&fB#~h<{HC zBw;LHwod5j#aR9`#&7OqcA5Qf(UGKGVl1CTyGu3;CIjq8V9cjdw5x{wL`DTrCNEcu9dH#jNu$x-pQ1G0=ti409Ww&koBm z@G@je^JSwP16wc#ra}KnU$;VEe7Vy;D;I#Or#bBx;W)9Z$rpKYrqyDWS| z+UNKLvGZ#5^Ha#;yXgPcZ(&aZb6g3@622q(e8#y1vHoYy!`}2wNDGiGQ#8vNB~PN6 zk1fn2Bum&ZF3U8?vIw%wfGn3nmJTUPisyd{KWEE}EQmv&T#gwNS?73qmKp1p6fVm& zF3Ss$Wu}&T=61+(k2XFKfDCs)mgQ2G7oig*%L{mS;5`vGjqKNluwNw0c<^``KBrr; zPlPfg%SI{7A48TCV7vd-GBGgKI+4rr&(_4AQ?O^hgZ%!CcJ#8Ob3|RJ^CcK8{8~QOVl2|y!)zS@UWUf{-^b$L$Kv0|;{P|sVyy2hqVL^W zO5eAIcoNN(v=*oM6JoPP9oT!IeYZc#eYb;{2deQ*CZ%t{9z+82T=0p#n7e3?MeWHw zguMtV`x@50zeIWizE^VkE+FUs5`I^(19`@?7dRFiQ-WX z#F^;);W?xipsqc9uWv?w3D%BpS!T$+zM0tTn2EiPg#NlIpl_VmU-~x6dtfJ1_*zix zEu6+$@N*f%qIw{mMF2h&FSw_}#5p&BMXe%AZfXEKp*^Iy<(5v$LKzBp`_NQOQ zTxw?tfgVdjU_8#){XaOrLu*4?7s3V`?C%V2f0s{n79O_5_s^B<4dCKrgK&Uc~1F_|iMTTS~Wq=Z)a& z1YnPVx0&$iU$O{4pXRnMvF`4Kzkc}?{1lq!Xx)8S6TEHYyiMr8UGmnBy1~OD?2lnT zbq3#0wP8QiquWm-m$S}y|>QMw0UE#yOrH}r{mt{`pu1Q#{>AqXK!3ZJQ%Q56HZW7bvg4&F83TbvtUCH#hN8tQJ-K>OAg^HMcu9Zua>dwQfgFh=?Xo zv$@Vs4fx%y8@)}ub|TDO)7sd^9A&Fk-M8v?hqtM&xwX|@=a&RJn%6m+@nh6AP4zxU zU2~If^G0`lw!=~EcQ6$8`Q2z1WyA;71b&;k)$iC^<3qZGcY2|>{yQv#WwN`NgRN|C zax=$lHk)~y{Dm$*z2z2&ce*dg$Njp-<{FX8@5E=GQ;T1@ppKzGti|7o@50V4U^G+RQMRVF%>{XFtl4JF zb#H5F^wxR(t}X6XzZ<_9UPC_w4)KNxuCHs74e+Fu54c1ZT^nnB4X$S3TD|pdR~_Be ztaqzI>)p+$2klDYT55bgzo)f%^Lmdevc>D(+5(MsarWlPvdDKLJpd_Db|xvIYweXPUhR&SjuveE7HDAF@@e9L5uy*`iwSv0me*420+O-P}( z#^lv}KuEyWoy0GdycikmFxifs;N8B#xb*AICrrR9uZFO!pbQ*m1Zrr@l z;oICo{lSoP^XS8BbyKNsmfTyjO=iiPN|gdsy+Vl_pu|mi6GYw8+=!7}?1%M$3Q+Z>n`_-m zYU)5rePlvub8{=Fvr)>Nw>n5x#Fm0bdJ}s?c&N zY@i?a7+D+9>=yU11n|OJ=k}pYX`{CV8sx8Os&j`MDc#)II6QR)@gZF3UZ^C|sA^ZA z!YRz-N!pka}w?_(&j5^{7mOD@RvibI12#g@qNLj9NH1gX?M)e4ozr*aa_ z5+xa`n;SEd%zbj4m&##|%qU5bKe-*l3 z)8u1|-RoQ3WL&&WthCt&m1ttcK71&y!>3}1nzB5U=b=mw&&6M4<1g~X-#k{)yp@%0 zYhf#z*VB6*-N3YM!o&?j0F86=`^98qVUl6g*}XNeIoo6|!&JVG|EUzS6ODOB!<-L# zm;f^3^k+5wSyI{v8L>+7wpzRaf--(L(l`h>fN-QS%x89)uY}G*?<2iIZ)}(&1>Y!=Yrn@;UXcou^G;I z=yMTy1uZml{he!n=fG$=@b}-olfQi@7>4*ZzqCgxR;*&$qcT(V+t`c>wf&H)L$>|ggy)m~A(_+pjwsHK<2_V9f>!Z`kpr?^g+*7c zI$FJx4o|eUnGuj~rAr zAaR%Q9^z9}zM}sqPqg$(%m=tP(n9=U=o?*r`V*3+kn>ELcPb)J$TIvnMZt|bEV)))eer=<_A-;&d6JHBuetVRB8dGazzG|O%-6+#CA}}^S20LUP z$&D^5e@Ld0?87wJc;0cD_oyL{XnRlQwMXQIX~#JResMk<`bO<0$BFz3dJE-?c5`Ij z8bcoSd40nWlJ1X|EX4<{*uJCXKE)>CZ6Tf}KG! zy)MaeoOXPszB1?tT~7L=>noL?Df3z=50?Y49GMoqtt4)5x?~v|dx~}z!`@JPcovOc ziU&lWsw&Q-2BM@TVpE+iRc;RM9Ww3qsN+r8aH4am zEXQeID#s<#sg74UV^GCW`q_mUE0y z&VhF63vB7?!YfptPA7hh>YbvL?P-60d8E%KedQmOQ z8TBFqut#Mc(K-^(9mwuh^^o0;;GwYl)Q?m<{@{8Ux*?03*Nbvo4}9=9TYxwo;gY}Lw2e}T)@RNs)B zJ5NM~n-La9UFCHvD|1}AxpkhJR+qoE#_RW$*OlR_SY8*dDuizIm9MOfRvaz3hE-kV zDl4lja7C|bSm~%0H~PvpM4=o=B&M(OhN?nD#lyLFqiEK#VZPqX)oxxFeL91+ zFj%;V;cz4B(|0{;eee@Z=_{M>MW(xqhPbPMwwN2;y1^V)-f(wEtgZkX4`{5cqOLJ) z5~9@tJ7r4LaHcKrx!n!T>(-TRLtde`*@v?QJ~vOT_qOV%?HklqOS6wGef~P!loxHR z#pbFX8|`JWni`Qg`M$QMI^FR8>e4F0iJPrBc+vLFswvp!TkrNa-DoKlVdK-?ijyr{ zzfmXWZyrq*Urm9ET57TVM@K94Q*Sh78Bu~@9Na}PZuyPX??T$e=DpTA249)F*rsK~ z&Mp3CmgJj_(Ge-*RsT(fC(_)F4kk<&1W|DQek_Q%9uzWx6Hd@{n@n<+{k2 zhE5vc;MB&A%}wPiYIDoV@^V}*IwZB#rQc+XI=W4Y8di^yyOpJR`h}{iuCb~T5zhZzHFn83&Y%Xvmx+}S_BI=Mw<-3W~DwK&W{k^qE;$h zyXFx+)Oj#sdTj`^c2w~B>l&d`QMF)n3rlzjILpvxVz1!EyFj3ef*LpzgJWAh_omHm z9BzuP^JTQA85X_>hYTu~SLVB-G7CYKmYRAO&Vjn*LeL~8LG>3&p2BT$;Zz)svNpGt zt5zsXf>tUE=|7PZa#G5W97X!N)s)^tq{URB%cXQR4Ac!+j7hN+<4(}m9j}T2>e|=R zMEFPfu5tv3Vw0R3_8!05v^@`M997Te*ON-nTGYtB+#;~AzMfk=*b9|+FH}X$5MF(k6Ny(obRe~RhEFs zwLV|=J&nG`N`HO+{2YE*b|nr1`$EAmXhv>!F3aYTu~v5@f@BDgRXw0{s=vXi4{IPp z#ici>;v9r1LdGf-NT|$%sts#X-ht2l}=47w%ZT0%=JlQ-J|Mlaodeylxb!O)l6-9RF2GyH~ z{j=>Y?o{OHXP^2fz#$DY=HRNTwBmGIh*hWSawsh-<^HW%GGyZ zrCry+vfUmRjz{8Qh8uI?nOH{KNOC(eRH-v`7kPv2tcVNWaWEpD&iv>vBOYJ!%JK3D zM5yTPvfxLC3?sf=;*Int$^A*bR~@RAF(ZDz34ZY?@gJJtw@EymJJMgq_GcnL8vhr| zy|&|eFz$``4JP<6B%aPE=`SPxkO_W;+{mYMO8U!)$1{FW>3?XVK+$<6{bj^oHNn44 ziiPVT@fP}P#HXWvR546{GjN`XE;`qwzl`|rOT2+hmUOE?wd=vSH$AQP5xIUz9R-6-@6?Z|L9x+bjFb1k4^Be(&0l~bnZ)kp?JilAwL@ZbMizn zekM$ZFyb91__yZ?&^8^GZjJah6Z~RnINM|3-!s9#De<-#_(?F_(fa?k#7i{{)ncT7 zr3wD3#3zT4;>L)7#sqJhFUs@tKe{@M_zz6*g%Z!t#EpQTi+Lhi|Bp(1yADgY#`d2y z!RO;aYPw?S|A!{{S0%neR1^AZZ2wLOI2!$lG_m7aBi=%PjrbiV_oeADE zN_;Zr$!PR9O1wH3s5)S5zug3Xs8Aqc=^y==P_*`6k$7}3;xe{>M|^br@loRaCiqhl z|7Jw%!}affF~L8HFHfOsjd%IfiwXYuQQ{LPM5n)Nl=xL9_-={kXH|6^H1hA4CiwTh zBS5j_{}&T{pTx(q-#5Wek0!suMWX#!^WWVjc#p)#(x0^^c)!Fy6l44xF~Ps%6!gy# zZ=t_N{=aR4zbf(VG1{M%6rF$m644|-mm6w*xc%H>f`7AAfELDR|CkA$l?l8f2L4kM zykm*LcZs*qUnBqS!a9wbfEyHXosxKdo>rG*#Q)p`U%ym<=p3;AGUC&*zKhm=>N0`i zXM%MV81ZXN@GF)JP^|ISWrDAk_*nf#VWBVB%f!d}A zC;62jqOj8c(^AKmk~ct;*I=sn6z({-~A@|9EnejXnnZ+TTSpw zM~UBWg0Gf%M~wDQnBdz-i64&+M$^A8iC-F{eYXj|ZE>qk4BryaCSc-)Kw`pA}B!R!F>2|JO*oBVLsh??(Em VKBMka$!%Lj`L(EDe;M2Ve*vws@+$xU literal 0 HcmV?d00001 diff --git a/android/arm64-v8a/glslang/libglslang.a b/android/arm64-v8a/glslang/libglslang.a new file mode 100644 index 0000000000000000000000000000000000000000..9fc260737a5161443930065f9286475c8a25c78d GIT binary patch literal 1986142 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